From 817877dc8b6a120b65f8f3753615a6911f86ef9f Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Mon, 23 Sep 2019 16:03:29 -0400 Subject: [PATCH] Typescript some of `src/legacy/server/index_patterns` (#44993) (#46349) * TypeScriptify errors.js * Fixed type errors in errors.ts * Prettierize resolve_time_pattern.test.js * Prettierize resolve_time_pattern.js * TypeScriptify resolve_time_pattern.js * Prettierize mixin.js * Fixed errors.ts payload error. * TypeScriptify and Prettierize mixin.ts * Prettierize query_params.js * TypeScriptified routes and used core.http features and fixed related tests. * Fixed type errors. * Removed anys * Prettierize params.js * Prettierize response.js * Accepts string array as query param. * Returns 404 when there's no matching pattern for fields_for_wildcard. * Simplified schema. * Fixed types. --- src/legacy/server/index_patterns/mixin.d.ts | 24 ---- .../index_patterns/{mixin.js => mixin.ts} | 36 ++--- src/legacy/server/index_patterns/routes.ts | 134 ++++++++++++++++++ .../routes/fields_for_time_pattern_route.js | 53 ------- .../routes/fields_for_wildcard_route.js | 48 ------- .../server/index_patterns/routes/index.js | 21 --- .../service/lib/{errors.js => errors.ts} | 14 +- .../index_patterns/service/lib/es_api.ts | 19 ++- .../service/lib/resolve_time_pattern.test.js | 10 +- ...ime_pattern.js => resolve_time_pattern.ts} | 30 ++-- src/legacy/server/kbn_server.d.ts | 4 + .../query_params.js | 63 +++++--- .../fields_for_wildcard_route/params.js | 33 +++-- .../fields_for_wildcard_route/response.js | 41 +++--- 14 files changed, 273 insertions(+), 257 deletions(-) delete mode 100644 src/legacy/server/index_patterns/mixin.d.ts rename src/legacy/server/index_patterns/{mixin.js => mixin.ts} (71%) create mode 100644 src/legacy/server/index_patterns/routes.ts delete mode 100644 src/legacy/server/index_patterns/routes/fields_for_time_pattern_route.js delete mode 100644 src/legacy/server/index_patterns/routes/fields_for_wildcard_route.js delete mode 100644 src/legacy/server/index_patterns/routes/index.js rename src/legacy/server/index_patterns/service/lib/{errors.js => errors.ts} (84%) rename src/legacy/server/index_patterns/service/lib/{resolve_time_pattern.js => resolve_time_pattern.ts} (73%) diff --git a/src/legacy/server/index_patterns/mixin.d.ts b/src/legacy/server/index_patterns/mixin.d.ts deleted file mode 100644 index 0ebbc41608b1..000000000000 --- a/src/legacy/server/index_patterns/mixin.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { IndexPatternsService } from './service'; - -export type IndexPatternsServiceFactory = (args: { - callCluster: (endpoint: string, clientParams: any, options: any) => Promise; -}) => IndexPatternsService; diff --git a/src/legacy/server/index_patterns/mixin.js b/src/legacy/server/index_patterns/mixin.ts similarity index 71% rename from src/legacy/server/index_patterns/mixin.js rename to src/legacy/server/index_patterns/mixin.ts index 1903af7683c2..914bdc01063b 100644 --- a/src/legacy/server/index_patterns/mixin.js +++ b/src/legacy/server/index_patterns/mixin.ts @@ -18,26 +18,12 @@ */ import { IndexPatternsService } from './service'; +import KbnServer from '../kbn_server'; +import { APICaller } from '../../../core/server'; +import { Legacy } from '../../../../kibana'; +import { registerRoutes } from './routes'; -import { - createFieldsForWildcardRoute, - createFieldsForTimePatternRoute, -} from './routes'; - -export function indexPatternsMixin(kbnServer, server) { - const pre = { - /** - * Create an instance of the `indexPatterns` service - * @type {Hapi.Pre} - */ - getIndexPatternsService: { - assign: 'indexPatterns', - method(request) { - return request.getIndexPatternsService(); - } - } - }; - +export function indexPatternsMixin(kbnServer: KbnServer, server: Legacy.Server) { /** * Create an instance of the IndexPatternsService * @@ -55,12 +41,16 @@ export function indexPatternsMixin(kbnServer, server) { * @method request.getIndexPatternsService * @type {IndexPatternsService} */ - server.addMemoizedFactoryToRequest('getIndexPatternsService', request => { + server.addMemoizedFactoryToRequest('getIndexPatternsService', (request: Legacy.Request) => { const { callWithRequest } = request.server.plugins.elasticsearch.getCluster('data'); - const callCluster = (...args) => callWithRequest(request, ...args); + const callCluster: APICaller = (endpoint, params, options) => + callWithRequest(request, endpoint, params, options); return server.indexPatternsServiceFactory({ callCluster }); }); - server.route(createFieldsForWildcardRoute(pre)); - server.route(createFieldsForTimePatternRoute(pre)); + registerRoutes(kbnServer.newPlatform.setup.core); } + +export type IndexPatternsServiceFactory = (args: { + callCluster: (endpoint: string, clientParams: any, options: any) => Promise; +}) => IndexPatternsService; diff --git a/src/legacy/server/index_patterns/routes.ts b/src/legacy/server/index_patterns/routes.ts new file mode 100644 index 000000000000..4fceae48fc58 --- /dev/null +++ b/src/legacy/server/index_patterns/routes.ts @@ -0,0 +1,134 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { first } from 'rxjs/operators'; +import { schema } from '@kbn/config-schema'; +import { + InternalCoreSetup, + KibanaRequest, + RequestHandlerContext, + APICaller, +} from '../../../core/server'; +import { IndexPatternsService } from './service'; + +export function registerRoutes(core: InternalCoreSetup) { + const getIndexPatternsService = async (request: KibanaRequest): Promise => { + const client = await core.elasticsearch.dataClient$.pipe(first()).toPromise(); + const callCluster: APICaller = (endpoint, params, options) => + client.asScoped(request).callAsCurrentUser(endpoint, params, options); + return new Promise(resolve => resolve(new IndexPatternsService(callCluster))); + }; + + const parseMetaFields = (metaFields: string | string[]) => { + let parsedFields: string[] = []; + if (typeof metaFields === 'string') { + parsedFields = JSON.parse(metaFields); + } else { + parsedFields = metaFields; + } + return parsedFields; + }; + + const router = core.http.createRouter('/api/index_patterns'); + router.get( + { + path: '/_fields_for_wildcard', + validate: { + query: schema.object({ + pattern: schema.string(), + meta_fields: schema.oneOf([schema.string(), schema.arrayOf(schema.string())], { + defaultValue: [], + }), + }), + }, + }, + async (context: RequestHandlerContext, request: any, response: any) => { + const indexPatterns = await getIndexPatternsService(request); + const { pattern, meta_fields: metaFields } = request.query; + + let parsedFields: string[] = []; + try { + parsedFields = parseMetaFields(metaFields); + } catch (error) { + return response.badRequest(); + } + + try { + const fields = await indexPatterns.getFieldsForWildcard({ + pattern, + metaFields: parsedFields, + }); + + return response.ok({ + body: { fields }, + headers: { + 'content-type': 'application/json', + }, + }); + } catch (error) { + return response.notFound(); + } + } + ); + + router.get( + { + path: '/_fields_for_time_pattern', + validate: { + query: schema.object({ + pattern: schema.string(), + interval: schema.maybe(schema.string()), + look_back: schema.number({ min: 1 }), + meta_fields: schema.oneOf([schema.string(), schema.arrayOf(schema.string())], { + defaultValue: [], + }), + }), + }, + }, + async (context: RequestHandlerContext, request: any, response: any) => { + const indexPatterns = await getIndexPatternsService(request); + const { pattern, interval, look_back: lookBack, meta_fields: metaFields } = request.query; + + let parsedFields: string[] = []; + try { + parsedFields = parseMetaFields(metaFields); + } catch (error) { + return response.badRequest(); + } + + try { + const fields = await indexPatterns.getFieldsForTimePattern({ + pattern, + interval: interval ? interval : '', + lookBack, + metaFields: parsedFields, + }); + + return response.ok({ + body: { fields }, + headers: { + 'content-type': 'application/json', + }, + }); + } catch (error) { + return response.notFound(); + } + } + ); +} diff --git a/src/legacy/server/index_patterns/routes/fields_for_time_pattern_route.js b/src/legacy/server/index_patterns/routes/fields_for_time_pattern_route.js deleted file mode 100644 index f7ec6e751c7e..000000000000 --- a/src/legacy/server/index_patterns/routes/fields_for_time_pattern_route.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Joi from 'joi'; - -export const createFieldsForTimePatternRoute = pre => ({ - path: '/api/index_patterns/_fields_for_time_pattern', - method: 'GET', - config: { - pre: [pre.getIndexPatternsService], - validate: { - query: Joi.object().keys({ - pattern: Joi.string().required(), - look_back: Joi.number().min(1).required(), - meta_fields: Joi.array().items(Joi.string()).default([]), - }).default() - }, - async handler(req) { - const { indexPatterns } = req.pre; - const { - pattern, - interval, - look_back: lookBack, - meta_fields: metaFields, - } = req.query; - - const fields = await indexPatterns.getFieldsForTimePattern({ - pattern, - interval, - lookBack, - metaFields - }); - - return { fields }; - } - } -}); diff --git a/src/legacy/server/index_patterns/routes/fields_for_wildcard_route.js b/src/legacy/server/index_patterns/routes/fields_for_wildcard_route.js deleted file mode 100644 index 953bba3e0b16..000000000000 --- a/src/legacy/server/index_patterns/routes/fields_for_wildcard_route.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Joi from 'joi'; - -export const createFieldsForWildcardRoute = pre => ({ - path: '/api/index_patterns/_fields_for_wildcard', - method: 'GET', - config: { - pre: [pre.getIndexPatternsService], - validate: { - query: Joi.object().keys({ - pattern: Joi.string().required(), - meta_fields: Joi.array().items(Joi.string()).default([]), - }).default() - }, - async handler(req) { - const { indexPatterns } = req.pre; - const { - pattern, - meta_fields: metaFields, - } = req.query; - - const fields = await indexPatterns.getFieldsForWildcard({ - pattern, - metaFields - }); - - return { fields }; - } - } -}); diff --git a/src/legacy/server/index_patterns/routes/index.js b/src/legacy/server/index_patterns/routes/index.js deleted file mode 100644 index dfce69167ac5..000000000000 --- a/src/legacy/server/index_patterns/routes/index.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { createFieldsForWildcardRoute } from './fields_for_wildcard_route'; -export { createFieldsForTimePatternRoute } from './fields_for_time_pattern_route'; diff --git a/src/legacy/server/index_patterns/service/lib/errors.js b/src/legacy/server/index_patterns/service/lib/errors.ts similarity index 84% rename from src/legacy/server/index_patterns/service/lib/errors.js rename to src/legacy/server/index_patterns/service/lib/errors.ts index b6c659c53ea8..e5a96c67c56b 100644 --- a/src/legacy/server/index_patterns/service/lib/errors.js +++ b/src/legacy/server/index_patterns/service/lib/errors.ts @@ -29,7 +29,7 @@ const ERR_NO_MATCHING_INDICES = 'no_matching_indices'; * @param {Any} err * @return {Boolean} */ -export function isEsIndexNotFoundError(err) { +export function isEsIndexNotFoundError(err: any) { return get(err, ['body', 'error', 'type']) === ERR_ES_INDEX_NOT_FOUND; } @@ -39,9 +39,9 @@ export function isEsIndexNotFoundError(err) { * @param {String} pattern the pattern which indexes were supposed to match * @return {Boom} */ -export function createNoMatchingIndicesError(pattern) { +export function createNoMatchingIndicesError(pattern: string[] | string) { const err = Boom.notFound(`No indices match pattern "${pattern}"`); - err.output.payload.code = ERR_NO_MATCHING_INDICES; + (err.output.payload as any).code = ERR_NO_MATCHING_INDICES; return err; } @@ -51,17 +51,17 @@ export function createNoMatchingIndicesError(pattern) { * @param {Any} err * @return {Boolean} */ -export function isNoMatchingIndicesError(err) { +export function isNoMatchingIndicesError(err: any) { return get(err, ['output', 'payload', 'code']) === ERR_NO_MATCHING_INDICES; } /** * Wrap "index_not_found_exception" errors in custom Boom errors * automatically - * @param {[type]} indices [description] - * @return {[type]} [description] + * @param {Array|String} indices + * @return {Boom} */ -export function convertEsError(indices, error) { +export function convertEsError(indices: string[] | string, error: any) { if (isEsIndexNotFoundError(error)) { return createNoMatchingIndicesError(indices); } diff --git a/src/legacy/server/index_patterns/service/lib/es_api.ts b/src/legacy/server/index_patterns/service/lib/es_api.ts index 1a22cf23ec0d..63c1824784db 100644 --- a/src/legacy/server/index_patterns/service/lib/es_api.ts +++ b/src/legacy/server/index_patterns/service/lib/es_api.ts @@ -22,6 +22,16 @@ import { APICaller } from 'src/core/server'; import { convertEsError } from './errors'; import { FieldCapsResponse } from './field_capabilities'; +export interface IndicesAliasResponse { + [index: string]: IndexAliasResponse; +} + +export interface IndexAliasResponse { + aliases: { + [aliasName: string]: Record; + }; +} + /** * Call the index.getAlias API for a list of indices. * @@ -36,13 +46,16 @@ import { FieldCapsResponse } from './field_capabilities'; * @param {Array|String} indices * @return {Promise} */ -export async function callIndexAliasApi(callCluster: APICaller, indices: string[] | string) { +export async function callIndexAliasApi( + callCluster: APICaller, + indices: string[] | string +): Promise { try { - return await callCluster('indices.getAlias', { + return (await callCluster('indices.getAlias', { index: indices, ignoreUnavailable: true, allowNoIndices: false, - }); + })) as Promise; } catch (error) { throw convertEsError(indices, error); } diff --git a/src/legacy/server/index_patterns/service/lib/resolve_time_pattern.test.js b/src/legacy/server/index_patterns/service/lib/resolve_time_pattern.test.js index f1b67d3d7f88..660e9ec30db6 100644 --- a/src/legacy/server/index_patterns/service/lib/resolve_time_pattern.test.js +++ b/src/legacy/server/index_patterns/service/lib/resolve_time_pattern.test.js @@ -32,7 +32,7 @@ const TIME_PATTERN = '[logs-]dddd-YYYY.w'; describe('server/index_patterns/service/lib/resolve_time_pattern', () => { let sandbox; - beforeEach(() => sandbox = sinon.createSandbox()); + beforeEach(() => (sandbox = sinon.createSandbox())); afterEach(() => sandbox.restore()); describe('resolveTimePattern()', () => { @@ -47,8 +47,7 @@ describe('server/index_patterns/service/lib/resolve_time_pattern', () => { const timePattern = {}; const wildcard = {}; - sandbox.stub(timePatternToWildcardNS, 'timePatternToWildcard') - .returns(wildcard); + sandbox.stub(timePatternToWildcardNS, 'timePatternToWildcard').returns(wildcard); await resolveTimePattern(noop, timePattern); sinon.assert.calledOnce(timePatternToWildcard); @@ -60,8 +59,7 @@ describe('server/index_patterns/service/lib/resolve_time_pattern', () => { const wildcard = {}; sandbox.stub(callIndexAliasApiNS, 'callIndexAliasApi').returns({}); - sandbox.stub(timePatternToWildcardNS, 'timePatternToWildcard') - .returns(wildcard); + sandbox.stub(timePatternToWildcardNS, 'timePatternToWildcard').returns(wildcard); await resolveTimePattern(noop, timePattern); sinon.assert.calledOnce(callIndexAliasApi); @@ -110,7 +108,7 @@ describe('server/index_patterns/service/lib/resolve_time_pattern', () => { expect(resp.matches).toEqual([ 'logs-Saturday-2017.1', 'logs-Friday-2017.1', - 'logs-Sunday-2017.1' + 'logs-Sunday-2017.1', ]); }); }); diff --git a/src/legacy/server/index_patterns/service/lib/resolve_time_pattern.js b/src/legacy/server/index_patterns/service/lib/resolve_time_pattern.ts similarity index 73% rename from src/legacy/server/index_patterns/service/lib/resolve_time_pattern.js rename to src/legacy/server/index_patterns/service/lib/resolve_time_pattern.ts index 21ea91baf593..d8c56a8082cb 100644 --- a/src/legacy/server/index_patterns/service/lib/resolve_time_pattern.js +++ b/src/legacy/server/index_patterns/service/lib/resolve_time_pattern.ts @@ -20,8 +20,10 @@ import { chain } from 'lodash'; import moment from 'moment'; +import { APICaller } from 'src/core/server'; + import { timePatternToWildcard } from './time_pattern_to_wildcard'; -import { callIndexAliasApi } from './es_api'; +import { callIndexAliasApi, IndicesAliasResponse } from './es_api'; /** * Convert a time pattern into a list of indexes it could @@ -34,15 +36,16 @@ import { callIndexAliasApi } from './es_api'; * and the indices that actually match the time * pattern (matches); */ -export async function resolveTimePattern(callCluster, timePattern) { +export async function resolveTimePattern(callCluster: APICaller, timePattern: string) { const aliases = await callIndexAliasApi(callCluster, timePatternToWildcard(timePattern)); - const allIndexDetails = chain(aliases) - .reduce((acc, index, indexName) => acc.concat( - indexName, - Object.keys(index.aliases || {}) - ), []) - .sort() + const allIndexDetails = chain(aliases) + .reduce( + (acc: string[], index: any, indexName: string) => + acc.concat(indexName, Object.keys(index.aliases || {})), + [] + ) + .sortBy((indexName: string) => indexName) .uniq(true) .map(indexName => { const parsed = moment(indexName, timePattern, true); @@ -51,7 +54,7 @@ export async function resolveTimePattern(callCluster, timePattern) { valid: false, indexName, order: indexName, - isMatch: false + isMatch: false, }; } @@ -59,18 +62,15 @@ export async function resolveTimePattern(callCluster, timePattern) { valid: true, indexName, order: parsed, - isMatch: indexName === parsed.format(timePattern) + isMatch: indexName === parsed.format(timePattern), }; }) .sortByOrder(['valid', 'order'], ['desc', 'desc']) .value(); return { - all: allIndexDetails - .map(details => details.indexName), + all: allIndexDetails.map(details => details.indexName), - matches: allIndexDetails - .filter(details => details.isMatch) - .map(details => details.indexName), + matches: allIndexDetails.filter(details => details.isMatch).map(details => details.indexName), }; } diff --git a/src/legacy/server/kbn_server.d.ts b/src/legacy/server/kbn_server.d.ts index 71c6fa37e726..e3de4f0286a6 100644 --- a/src/legacy/server/kbn_server.d.ts +++ b/src/legacy/server/kbn_server.d.ts @@ -73,6 +73,10 @@ declare module 'hapi' { savedObjectsManagement(): SavedObjectsManagement; getInjectedUiAppVars: (pluginName: string) => { [key: string]: any }; getUiNavLinks(): Array<{ _id: string }>; + addMemoizedFactoryToRequest: ( + name: string, + factoryFn: (request: Request) => Record + ) => void; } interface Request { diff --git a/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/query_params.js b/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/query_params.js index 2201b5631665..cc2558e4704e 100644 --- a/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/query_params.js +++ b/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/query_params.js @@ -27,34 +27,49 @@ export default function ({ getService }) { before(() => esArchiver.load('index_patterns/daily_index')); after(() => esArchiver.unload('index_patterns/daily_index')); - it('requires `pattern` and `look_back` query params', () => ( + it('requires `pattern` query param', () => supertest .get('/api/index_patterns/_fields_for_time_pattern') - .query({ pattern: null }) + .query({ look_back: 1 }) .expect(400) .then(resp => { - expect(resp.body.validation).to.eql({ - keys: [ - 'pattern', - 'look_back' - ], - source: 'query' - }); - }) - )); + expect(resp.body.message).to.contain( + '[request query.pattern]: expected value of type [string] but got [undefined]' + ); + })); - it('supports `meta_fields` query param', () => ( + it('requires `look_back` query param', () => + supertest + .get('/api/index_patterns/_fields_for_time_pattern') + .query({ pattern: 'pattern-*' }) + .expect(400) + .then(resp => { + expect(resp.body.message).to.contain( + '[request query.look_back]: expected value of type [number] but got [undefined]' + ); + })); + + it('supports `meta_fields` query param in JSON format', () => supertest .get('/api/index_patterns/_fields_for_time_pattern') .query({ pattern: '[logs-]YYYY.MM.DD', look_back: 1, - meta_fields: JSON.stringify(['a']) + meta_fields: JSON.stringify(['a']), }) - .expect(200) - )); + .expect(200)); - it('requires `look_back` to be a number', () => ( + it('supports `meta_fields` query param in string array format', () => + supertest + .get('/api/index_patterns/_fields_for_time_pattern') + .query({ + pattern: '[logs-]YYYY.MM.DD', + look_back: 1, + meta_fields: ['a', 'b'], + }) + .expect(200)); + + it('requires `look_back` to be a number', () => supertest .get('/api/index_patterns/_fields_for_time_pattern') .query({ @@ -63,11 +78,12 @@ export default function ({ getService }) { }) .expect(400) .then(resp => { - expect(resp.body.message).to.contain('"look_back" must be a number'); - }) - )); + expect(resp.body.message).to.contain( + '[request query.look_back]: expected value of type [number] but got [string]' + ); + })); - it('requires `look_back` to be greater than one', () => ( + it('requires `look_back` to be greater than one', () => supertest .get('/api/index_patterns/_fields_for_time_pattern') .query({ @@ -76,8 +92,9 @@ export default function ({ getService }) { }) .expect(400) .then(resp => { - expect(resp.body.message).to.contain('"look_back" must be larger than or equal to 1'); - }) - )); + expect(resp.body.message).to.contain( + '[request query.look_back]: Value is [0] but it must be equal to or greater than [1].' + ); + })); }); } diff --git a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/params.js b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/params.js index 21d254c739b2..37916d3bee37 100644 --- a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/params.js +++ b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/params.js @@ -26,41 +26,46 @@ export default function ({ getService }) { before(() => esArchiver.load('index_patterns/basic_index')); after(() => esArchiver.unload('index_patterns/basic_index')); - it('requires a pattern query param', () => ( + it('requires a pattern query param', () => supertest .get('/api/index_patterns/_fields_for_wildcard') .query({}) - .expect(400) - )); + .expect(400)); - it('accepts a JSON formatted meta_fields query param', () => ( + it('accepts a JSON formatted meta_fields query param', () => supertest .get('/api/index_patterns/_fields_for_wildcard') .query({ pattern: '*', - meta_fields: JSON.stringify(['meta']) + meta_fields: JSON.stringify(['meta']), }) - .expect(200) - )); + .expect(200)); - it('rejects a comma-separated list of meta_fields', () => ( + it('accepts meta_fields query param in string array', () => supertest .get('/api/index_patterns/_fields_for_wildcard') .query({ pattern: '*', - meta_fields: 'foo,bar' + meta_fields: ['_id', 'meta'], }) - .expect(400) - )); + .expect(200)); - it('rejects unexpected query params', () => ( + it('rejects a comma-separated list of meta_fields', () => + supertest + .get('/api/index_patterns/_fields_for_wildcard') + .query({ + pattern: '*', + meta_fields: 'foo,bar', + }) + .expect(400)); + + it('rejects unexpected query params', () => supertest .get('/api/index_patterns/_fields_for_wildcard') .query({ pattern: chance.word(), [chance.word()]: chance.word(), }) - .expect(400) - )); + .expect(400)); }); } diff --git a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js index 71e1bf29a28d..d909b51e94ac 100644 --- a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js +++ b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js @@ -25,8 +25,7 @@ export default function ({ getService }) { const supertest = getService('supertest'); const ensureFieldsAreSorted = resp => { - expect(resp.body.fields) - .to.eql(sortBy(resp.body.fields, 'name')); + expect(resp.body.fields).to.eql(sortBy(resp.body.fields, 'name')); }; describe('response', () => { @@ -45,7 +44,7 @@ export default function ({ getService }) { searchable: true, aggregatable: true, name: 'bar', - readFromDocValues: true + readFromDocValues: true, }, { type: 'string', @@ -53,7 +52,7 @@ export default function ({ getService }) { searchable: true, aggregatable: false, name: 'baz', - readFromDocValues: false + readFromDocValues: false, }, { type: 'string', @@ -71,23 +70,18 @@ export default function ({ getService }) { searchable: true, aggregatable: true, name: 'foo', - readFromDocValues: true - } - ] + readFromDocValues: true, + }, + ], }) - .then(ensureFieldsAreSorted) - ); + .then(ensureFieldsAreSorted)); it('always returns a field for all passed meta fields', () => supertest .get('/api/index_patterns/_fields_for_wildcard') .query({ pattern: 'basic_index', - meta_fields: JSON.stringify([ - '_id', - '_source', - 'crazy_meta_field' - ]) + meta_fields: JSON.stringify(['_id', '_source', 'crazy_meta_field']), }) .expect(200, { fields: [ @@ -113,7 +107,7 @@ export default function ({ getService }) { searchable: true, aggregatable: true, name: 'bar', - readFromDocValues: true + readFromDocValues: true, }, { aggregatable: false, @@ -146,11 +140,18 @@ export default function ({ getService }) { searchable: true, aggregatable: true, name: 'foo', - readFromDocValues: true - } - ] + readFromDocValues: true, + }, + ], }) - .then(ensureFieldsAreSorted) - ); + .then(ensureFieldsAreSorted)); + + it('returns 404 when the pattern does not exist', () => + supertest + .get('/api/index_patterns/_fields_for_wildcard') + .query({ + pattern: '[non-existing-pattern]its-invalid-*', + }) + .expect(404)); }); }