mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[OAS] Pass down env to router processors and remove added in...
from serverless OAS (#222189)
## Summary * Addresses this comment https://github.com/elastic/kibana/issues/221056#issuecomment-2917522252, essentially avoid stating `added in...` if we are generating OAS for a serverless Kibana * Refactors `processRouter` and `processVersionedRouter` to take in object (for easier refactoring) * Adds test coverage ### 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 --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
539409d082
commit
c76d06fb6a
11 changed files with 322 additions and 104 deletions
|
@ -5431,7 +5431,7 @@
|
|||
"tags": [
|
||||
"alerting"
|
||||
],
|
||||
"x-state": "Generally available; added in 8.19.0"
|
||||
"x-state": "Generally available"
|
||||
}
|
||||
},
|
||||
"/api/alerting/rule/{ruleId}/snooze_schedule/{scheduleId}": {
|
||||
|
@ -5485,7 +5485,7 @@
|
|||
"tags": [
|
||||
"alerting"
|
||||
],
|
||||
"x-state": "Generally available; added in 8.19.0"
|
||||
"x-state": "Generally available"
|
||||
}
|
||||
},
|
||||
"/api/alerting/rule/{rule_id}/alert/{alert_id}/_mute": {
|
||||
|
|
|
@ -4218,7 +4218,7 @@ paths:
|
|||
summary: Schedule a snooze for the rule
|
||||
tags:
|
||||
- alerting
|
||||
x-state: Generally available; added in 8.19.0
|
||||
x-state: Generally available
|
||||
/api/alerting/rule/{rule_id}/alert/{alert_id}/_mute:
|
||||
post:
|
||||
operationId: post-alerting-rule-rule-id-alert-alert-id-mute
|
||||
|
@ -4324,7 +4324,7 @@ paths:
|
|||
summary: Delete a snooze schedule for a rule
|
||||
tags:
|
||||
- alerting
|
||||
x-state: Generally available; added in 8.19.0
|
||||
x-state: Generally available
|
||||
/api/alerting/rules/_find:
|
||||
get:
|
||||
operationId: get-alerting-rules-find
|
||||
|
|
|
@ -311,6 +311,7 @@ export class HttpService
|
|||
title: 'Kibana HTTP APIs',
|
||||
version: '0.0.0', // TODO get a better version here
|
||||
filters,
|
||||
env: { serverless: this.env.packageInfo.buildFlavor === 'serverless' },
|
||||
}
|
||||
);
|
||||
return h.response(result);
|
||||
|
|
|
@ -7,9 +7,27 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
jest.mock('./process_router', () => {
|
||||
const module = jest.requireActual('./process_router');
|
||||
return {
|
||||
...module,
|
||||
processRouter: jest.fn(module.processRouter),
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('./process_versioned_router', () => {
|
||||
const module = jest.requireActual('./process_versioned_router');
|
||||
return {
|
||||
...module,
|
||||
processVersionedRouter: jest.fn(module.processVersionedRouter),
|
||||
};
|
||||
});
|
||||
|
||||
import { schema, Type } from '@kbn/config-schema';
|
||||
import { get } from 'lodash';
|
||||
import { generateOpenApiDocument } from './generate_oas';
|
||||
import { processRouter } from './process_router';
|
||||
import { processVersionedRouter } from './process_versioned_router';
|
||||
import {
|
||||
createTestRouters,
|
||||
createRouter,
|
||||
|
@ -27,6 +45,10 @@ interface RecursiveType {
|
|||
self: undefined | RecursiveType;
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('generateOpenApiDocument', () => {
|
||||
describe('@kbn/config-schema', () => {
|
||||
it('generates the expected OpenAPI document for the shared schema', async () => {
|
||||
|
@ -562,6 +584,7 @@ describe('generateOpenApiDocument', () => {
|
|||
'$name: $expectedState',
|
||||
async ({ routerConfig, expectedPath, expectedState }) => {
|
||||
const [routers, versionedRouters] = createTestRouters(routerConfig);
|
||||
const env = { serverless: false, dummy: true };
|
||||
const result = await generateOpenApiDocument(
|
||||
{
|
||||
routers,
|
||||
|
@ -571,9 +594,23 @@ describe('generateOpenApiDocument', () => {
|
|||
title: 'test',
|
||||
baseUrl: 'https://test.oas',
|
||||
version: '99.99.99',
|
||||
env,
|
||||
}
|
||||
);
|
||||
|
||||
// Assert that the env has been passed down as expected
|
||||
if ((processRouter as jest.Mock).mock.calls.length) {
|
||||
(processRouter as jest.Mock).mock.calls.forEach(([{ env: routerEnv }]) =>
|
||||
expect(routerEnv).toEqual({ serverless: false, dummy: true })
|
||||
);
|
||||
}
|
||||
if ((processVersionedRouter as jest.Mock).mock.calls.length) {
|
||||
(processVersionedRouter as jest.Mock).mock.calls.forEach(
|
||||
([{ env: versionedRouterEnv }]) =>
|
||||
expect(versionedRouterEnv).toEqual({ serverless: false, dummy: true })
|
||||
);
|
||||
}
|
||||
|
||||
if (expectedState) {
|
||||
expect(result.paths[expectedPath]!.get).toMatchObject({
|
||||
'x-state': expectedState,
|
||||
|
|
|
@ -17,6 +17,10 @@ import { buildGlobalTags, createOpIdGenerator } from './util';
|
|||
|
||||
export const openApiVersion = '3.0.0';
|
||||
|
||||
export interface Env {
|
||||
serverless: boolean;
|
||||
}
|
||||
|
||||
export interface GenerateOpenApiDocumentOptionsFilters {
|
||||
pathStartsWith?: string[];
|
||||
excludePathsMatching?: string[];
|
||||
|
@ -36,6 +40,7 @@ export interface GenerateOpenApiDocumentOptions {
|
|||
baseUrl: string;
|
||||
docsUrl?: string;
|
||||
tags?: string[];
|
||||
env?: Env;
|
||||
filters?: GenerateOpenApiDocumentOptionsFilters;
|
||||
}
|
||||
|
||||
|
@ -50,12 +55,25 @@ export const generateOpenApiDocument = async (
|
|||
const converter = new OasConverter();
|
||||
const paths: OpenAPIV3.PathsObject = {};
|
||||
const getOpId = createOpIdGenerator();
|
||||
const env = opts.env || { serverless: false };
|
||||
for (const router of appRouters.routers) {
|
||||
const result = await processRouter(router, converter, getOpId, filters);
|
||||
const result = await processRouter({
|
||||
appRouter: router,
|
||||
converter,
|
||||
getOpId,
|
||||
filters,
|
||||
env,
|
||||
});
|
||||
Object.assign(paths, result.paths);
|
||||
}
|
||||
for (const router of appRouters.versionedRouters) {
|
||||
const result = await processVersionedRouter(router, converter, getOpId, filters);
|
||||
const result = await processVersionedRouter({
|
||||
appRouter: router,
|
||||
converter,
|
||||
getOpId,
|
||||
filters,
|
||||
env,
|
||||
});
|
||||
Object.assign(paths, result.paths);
|
||||
}
|
||||
const tags = buildGlobalTags(paths, opts.tags);
|
||||
|
|
|
@ -7,12 +7,24 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
jest.mock('./util', () => {
|
||||
const module = jest.requireActual('./util');
|
||||
return {
|
||||
...module,
|
||||
setXState: jest.fn(module.setXState),
|
||||
};
|
||||
});
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { Router } from '@kbn/core-http-router-server-internal';
|
||||
import { OasConverter } from './oas_converter';
|
||||
import { extractResponses, processRouter } from './process_router';
|
||||
import { type InternalRouterRoute } from './type';
|
||||
import { createOpIdGenerator } from './util';
|
||||
import { createOpIdGenerator, setXState } from './util';
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('extractResponses', () => {
|
||||
let oasConverter: OasConverter;
|
||||
|
@ -149,24 +161,39 @@ describe('processRouter', () => {
|
|||
} as unknown as Router;
|
||||
|
||||
it('only provides routes for version 2023-10-31', async () => {
|
||||
const result1 = await processRouter(testRouter, new OasConverter(), createOpIdGenerator(), {
|
||||
version: '2023-10-31',
|
||||
access: 'public',
|
||||
const result1 = await processRouter({
|
||||
appRouter: testRouter,
|
||||
converter: new OasConverter(),
|
||||
getOpId: createOpIdGenerator(),
|
||||
filters: {
|
||||
version: '2023-10-31',
|
||||
access: 'public',
|
||||
},
|
||||
});
|
||||
|
||||
expect(Object.keys(result1.paths!)).toHaveLength(5);
|
||||
|
||||
const result2 = await processRouter(testRouter, new OasConverter(), createOpIdGenerator(), {
|
||||
version: '2024-10-31',
|
||||
access: 'public',
|
||||
const result2 = await processRouter({
|
||||
appRouter: testRouter,
|
||||
converter: new OasConverter(),
|
||||
getOpId: createOpIdGenerator(),
|
||||
filters: {
|
||||
version: '2024-10-31',
|
||||
access: 'public',
|
||||
},
|
||||
});
|
||||
expect(Object.keys(result2.paths!)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('updates description with privileges required', async () => {
|
||||
const result = await processRouter(testRouter, new OasConverter(), createOpIdGenerator(), {
|
||||
version: '2023-10-31',
|
||||
access: 'public',
|
||||
const result = await processRouter({
|
||||
appRouter: testRouter,
|
||||
converter: new OasConverter(),
|
||||
getOpId: createOpIdGenerator(),
|
||||
filters: {
|
||||
version: '2023-10-31',
|
||||
access: 'public',
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.paths['/qux']?.post).toBeDefined();
|
||||
|
@ -179,4 +206,26 @@ describe('processRouter', () => {
|
|||
'This a test route description.<br/><br/>[Required authorization] Route required privileges: (manage_spaces AND taskmanager) AND (console OR devtools).'
|
||||
);
|
||||
});
|
||||
|
||||
it('calls setXState with correct arguments', async () => {
|
||||
await processRouter({
|
||||
appRouter: testRouter,
|
||||
converter: new OasConverter(),
|
||||
getOpId: createOpIdGenerator(),
|
||||
filters: {
|
||||
version: '2023-10-31',
|
||||
access: 'public',
|
||||
},
|
||||
env: { serverless: true },
|
||||
});
|
||||
|
||||
const routes = testRouter.getRoutes();
|
||||
expect(setXState).toHaveBeenCalledTimes(routes.length);
|
||||
routes.forEach((_, idx) => {
|
||||
const [availability, operation, env] = (setXState as jest.Mock).mock.calls[idx];
|
||||
expect(availability === undefined || typeof availability === 'object').toBe(true);
|
||||
expect(typeof operation === 'object').toBe(true);
|
||||
expect(env).toEqual({ serverless: true });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -25,17 +25,26 @@ import {
|
|||
setXState,
|
||||
GetOpId,
|
||||
} from './util';
|
||||
import type { GenerateOpenApiDocumentOptionsFilters } from './generate_oas';
|
||||
import type { Env, GenerateOpenApiDocumentOptionsFilters } from './generate_oas';
|
||||
import type { CustomOperationObject, InternalRouterRoute } from './type';
|
||||
import { extractAuthzDescription } from './extract_authz_description';
|
||||
import { mergeOperation } from './merge_operation';
|
||||
|
||||
export const processRouter = async (
|
||||
appRouter: Router,
|
||||
converter: OasConverter,
|
||||
getOpId: GetOpId,
|
||||
filters: GenerateOpenApiDocumentOptionsFilters
|
||||
) => {
|
||||
export interface ProcessRouterOptions {
|
||||
appRouter: Router;
|
||||
converter: OasConverter;
|
||||
getOpId: GetOpId;
|
||||
filters: GenerateOpenApiDocumentOptionsFilters;
|
||||
env?: Env;
|
||||
}
|
||||
|
||||
export const processRouter = async ({
|
||||
appRouter,
|
||||
converter,
|
||||
getOpId,
|
||||
filters,
|
||||
env = { serverless: false },
|
||||
}: ProcessRouterOptions) => {
|
||||
const paths: OpenAPIV3.PathsObject = {};
|
||||
if (filters?.version && filters.version !== SERVERLESS_VERSION_2023_10_31) return { paths };
|
||||
const routes = prepareRoutes(appRouter.getRoutes({ excludeVersionedRoutes: true }), filters);
|
||||
|
@ -98,7 +107,7 @@ export const processRouter = async (
|
|||
operationId: getOpId({ path: route.path, method: route.method }),
|
||||
};
|
||||
|
||||
setXState(route.options.availability, operation);
|
||||
setXState(route.options.availability, operation, env);
|
||||
|
||||
if (route.options.oasOperationObject) {
|
||||
await mergeOperation(route.options.oasOperationObject(), operation);
|
||||
|
|
|
@ -7,6 +7,14 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
jest.mock('./util', () => {
|
||||
const module = jest.requireActual('./util');
|
||||
return {
|
||||
...module,
|
||||
setXState: jest.fn(module.setXState),
|
||||
};
|
||||
});
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import type { CoreVersionedRouter } from '@kbn/core-http-router-server-internal';
|
||||
import { get } from 'lodash';
|
||||
|
@ -17,13 +25,17 @@ import {
|
|||
processVersionedRouter,
|
||||
} from './process_versioned_router';
|
||||
import { VersionedRouterRoute } from '@kbn/core-http-server';
|
||||
import { createOpIdGenerator } from './util';
|
||||
import { createOpIdGenerator, setXState } from './util';
|
||||
|
||||
let oasConverter: OasConverter;
|
||||
beforeEach(() => {
|
||||
oasConverter = new OasConverter();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('extractVersionedRequestBodies', () => {
|
||||
test('handles full request config as expected', () => {
|
||||
expect(
|
||||
|
@ -122,35 +134,35 @@ describe('extractVersionedResponses', () => {
|
|||
|
||||
describe('processVersionedRouter', () => {
|
||||
it('correctly extracts the version based on the version filter', async () => {
|
||||
const baseCase = await processVersionedRouter(
|
||||
{ getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter,
|
||||
new OasConverter(),
|
||||
createOpIdGenerator(),
|
||||
{ access: 'public', version: '2023-10-31' }
|
||||
);
|
||||
const baseCase = await processVersionedRouter({
|
||||
appRouter: { getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter,
|
||||
converter: new OasConverter(),
|
||||
getOpId: createOpIdGenerator(),
|
||||
filters: { access: 'public', version: '2023-10-31' },
|
||||
});
|
||||
|
||||
expect(Object.keys(get(baseCase, 'paths["/foo"].get.responses.200.content')!)).toEqual([
|
||||
'application/test+json',
|
||||
]);
|
||||
|
||||
const filteredCase = await processVersionedRouter(
|
||||
{ getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter,
|
||||
new OasConverter(),
|
||||
createOpIdGenerator(),
|
||||
{ version: '2024-12-31', access: 'public' }
|
||||
);
|
||||
const filteredCase = await processVersionedRouter({
|
||||
appRouter: { getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter,
|
||||
converter: new OasConverter(),
|
||||
getOpId: createOpIdGenerator(),
|
||||
filters: { version: '2024-12-31', access: 'public' },
|
||||
});
|
||||
expect(Object.keys(get(filteredCase, 'paths["/foo"].get.responses.200.content')!)).toEqual([
|
||||
'application/test+json',
|
||||
]);
|
||||
});
|
||||
|
||||
it('correctly updates the authz description for routes that require privileges', async () => {
|
||||
const results = await processVersionedRouter(
|
||||
{ getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter,
|
||||
new OasConverter(),
|
||||
createOpIdGenerator(),
|
||||
{ version: '2023-10-31', access: 'public' }
|
||||
);
|
||||
const results = await processVersionedRouter({
|
||||
appRouter: { getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter,
|
||||
converter: new OasConverter(),
|
||||
getOpId: createOpIdGenerator(),
|
||||
filters: { version: '2023-10-31', access: 'public' },
|
||||
});
|
||||
expect(results.paths['/foo']).toBeDefined();
|
||||
|
||||
expect(results.paths['/foo']!.get).toBeDefined();
|
||||
|
@ -159,6 +171,29 @@ describe('processVersionedRouter', () => {
|
|||
'This is a test route description.<br/><br/>[Required authorization] Route required privileges: manage_spaces.'
|
||||
);
|
||||
});
|
||||
|
||||
it('calls setXState with correct arguments', async () => {
|
||||
const testRouter = { getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter;
|
||||
await processVersionedRouter({
|
||||
appRouter: testRouter,
|
||||
converter: new OasConverter(),
|
||||
getOpId: createOpIdGenerator(),
|
||||
filters: {
|
||||
version: '2023-10-31',
|
||||
access: 'public',
|
||||
},
|
||||
env: { serverless: true },
|
||||
});
|
||||
|
||||
const routes = testRouter.getRoutes();
|
||||
expect(setXState).toHaveBeenCalledTimes(routes.length);
|
||||
routes.forEach((_, idx) => {
|
||||
const [availability, operation, env] = (setXState as jest.Mock).mock.calls[idx];
|
||||
expect(availability === undefined || typeof availability === 'object').toBe(true);
|
||||
expect(typeof operation === 'object').toBe(true);
|
||||
expect(env).toEqual({ serverless: true });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const createTestRoute: () => VersionedRouterRoute = () => ({
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
import type { RouteMethod, VersionedRouterRoute } from '@kbn/core-http-server';
|
||||
import type { OpenAPIV3 } from 'openapi-types';
|
||||
import { extractAuthzDescription } from './extract_authz_description';
|
||||
import type { GenerateOpenApiDocumentOptionsFilters } from './generate_oas';
|
||||
import type { Env, GenerateOpenApiDocumentOptionsFilters } from './generate_oas';
|
||||
import type { OasConverter } from './oas_converter';
|
||||
import {
|
||||
prepareRoutes,
|
||||
|
@ -33,12 +33,21 @@ import {
|
|||
import { isReferenceObject } from './oas_converter/common';
|
||||
import { mergeOperation } from './merge_operation';
|
||||
|
||||
export const processVersionedRouter = async (
|
||||
appRouter: CoreVersionedRouter,
|
||||
converter: OasConverter,
|
||||
getOpId: GetOpId,
|
||||
filters: GenerateOpenApiDocumentOptionsFilters
|
||||
) => {
|
||||
export interface ProcessVersionedRouterOptions {
|
||||
appRouter: CoreVersionedRouter;
|
||||
converter: OasConverter;
|
||||
getOpId: GetOpId;
|
||||
filters: GenerateOpenApiDocumentOptionsFilters;
|
||||
env?: Env;
|
||||
}
|
||||
|
||||
export const processVersionedRouter = async ({
|
||||
appRouter,
|
||||
converter,
|
||||
getOpId,
|
||||
filters,
|
||||
env = { serverless: false },
|
||||
}: ProcessVersionedRouterOptions) => {
|
||||
const routes = prepareRoutes(appRouter.getRoutes(), filters);
|
||||
const paths: OpenAPIV3.PathsObject = {};
|
||||
for (const route of routes) {
|
||||
|
@ -129,7 +138,7 @@ export const processVersionedRouter = async (
|
|||
operationId: getOpId({ path: route.path, method: route.method }),
|
||||
};
|
||||
|
||||
setXState(route.options.options?.availability, operation);
|
||||
setXState(route.options.options?.availability, operation, env);
|
||||
|
||||
if (handler.options.options?.oasOperationObject) {
|
||||
await mergeOperation(handler.options.options.oasOperationObject(), operation);
|
||||
|
|
|
@ -351,57 +351,115 @@ describe('createOpIdGenerator', () => {
|
|||
});
|
||||
|
||||
describe('setXState', () => {
|
||||
test.each([
|
||||
{
|
||||
name: 'stable with since',
|
||||
availability: { stability: 'stable' as const, since: '8.0.0' },
|
||||
expected: 'Generally available; added in 8.0.0',
|
||||
},
|
||||
{
|
||||
name: 'stable without since',
|
||||
availability: { stability: 'stable' as const },
|
||||
expected: 'Generally available',
|
||||
},
|
||||
{
|
||||
name: 'experimental with since',
|
||||
availability: { stability: 'experimental' as const, since: '8.0.0' },
|
||||
expected: 'Technical Preview; added in 8.0.0',
|
||||
},
|
||||
{
|
||||
name: 'experimental without since',
|
||||
availability: { stability: 'experimental' as const },
|
||||
expected: 'Technical Preview',
|
||||
},
|
||||
{
|
||||
name: 'beta with since',
|
||||
availability: { stability: 'beta' as const, since: '8.0.0' },
|
||||
expected: 'Beta; added in 8.0.0',
|
||||
},
|
||||
{
|
||||
name: 'beta without since',
|
||||
availability: { stability: 'beta' as const },
|
||||
expected: 'Beta',
|
||||
},
|
||||
{
|
||||
name: 'no availability',
|
||||
availability: undefined,
|
||||
expected: undefined,
|
||||
},
|
||||
{
|
||||
name: 'only since',
|
||||
availability: { since: '8.0.0' },
|
||||
expected: 'Added in 8.0.0',
|
||||
},
|
||||
])('$name', ({ availability, expected }) => {
|
||||
// Create a minimal valid CustomOperationObject with required responses property
|
||||
const operation: CustomOperationObject = {
|
||||
responses: {
|
||||
'200': {
|
||||
description: 'OK',
|
||||
},
|
||||
describe('with serverless=false (default)', () => {
|
||||
test.each([
|
||||
{
|
||||
name: 'stable with since',
|
||||
availability: { stability: 'stable' as const, since: '8.0.0' },
|
||||
expected: 'Generally available; added in 8.0.0',
|
||||
},
|
||||
};
|
||||
setXState(availability, operation);
|
||||
expect(operation['x-state']).toBe(expected);
|
||||
{
|
||||
name: 'stable without since',
|
||||
availability: { stability: 'stable' as const },
|
||||
expected: 'Generally available',
|
||||
},
|
||||
{
|
||||
name: 'experimental with since',
|
||||
availability: { stability: 'experimental' as const, since: '8.0.0' },
|
||||
expected: 'Technical Preview; added in 8.0.0',
|
||||
},
|
||||
{
|
||||
name: 'experimental without since',
|
||||
availability: { stability: 'experimental' as const },
|
||||
expected: 'Technical Preview',
|
||||
},
|
||||
{
|
||||
name: 'beta with since',
|
||||
availability: { stability: 'beta' as const, since: '8.0.0' },
|
||||
expected: 'Beta; added in 8.0.0',
|
||||
},
|
||||
{
|
||||
name: 'beta without since',
|
||||
availability: { stability: 'beta' as const },
|
||||
expected: 'Beta',
|
||||
},
|
||||
{
|
||||
name: 'no availability',
|
||||
availability: undefined,
|
||||
expected: undefined,
|
||||
},
|
||||
{
|
||||
name: 'only since',
|
||||
availability: { since: '8.0.0' },
|
||||
expected: 'Added in 8.0.0',
|
||||
},
|
||||
])('$name', ({ availability, expected }) => {
|
||||
// Create a minimal valid CustomOperationObject with required responses property
|
||||
const operation: CustomOperationObject = {
|
||||
responses: {
|
||||
'200': {
|
||||
description: 'OK',
|
||||
},
|
||||
},
|
||||
};
|
||||
setXState(availability, operation, { serverless: false });
|
||||
expect(operation['x-state']).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with serverless=true', () => {
|
||||
test.each([
|
||||
{
|
||||
name: 'stable with since',
|
||||
availability: { stability: 'stable' as const, since: '8.0.0' },
|
||||
expected: 'Generally available',
|
||||
},
|
||||
{
|
||||
name: 'stable without since',
|
||||
availability: { stability: 'stable' as const },
|
||||
expected: 'Generally available',
|
||||
},
|
||||
{
|
||||
name: 'experimental with since',
|
||||
availability: { stability: 'experimental' as const, since: '8.0.0' },
|
||||
expected: 'Technical Preview',
|
||||
},
|
||||
{
|
||||
name: 'experimental without since',
|
||||
availability: { stability: 'experimental' as const },
|
||||
expected: 'Technical Preview',
|
||||
},
|
||||
{
|
||||
name: 'beta with since',
|
||||
availability: { stability: 'beta' as const, since: '8.0.0' },
|
||||
expected: 'Beta',
|
||||
},
|
||||
{
|
||||
name: 'beta without since',
|
||||
availability: { stability: 'beta' as const },
|
||||
expected: 'Beta',
|
||||
},
|
||||
{
|
||||
name: 'no availability',
|
||||
availability: undefined,
|
||||
expected: undefined,
|
||||
},
|
||||
{
|
||||
name: 'only since',
|
||||
availability: { since: '8.0.0' },
|
||||
expected: '',
|
||||
},
|
||||
])('$name', ({ availability, expected }) => {
|
||||
// Create a minimal valid CustomOperationObject with required responses property
|
||||
const operation: CustomOperationObject = {
|
||||
responses: {
|
||||
'200': {
|
||||
description: 'OK',
|
||||
},
|
||||
},
|
||||
};
|
||||
setXState(availability, operation, { serverless: true });
|
||||
expect(operation['x-state']).toBe(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -19,6 +19,7 @@ import {
|
|||
} from '@kbn/core-http-server';
|
||||
import { CustomOperationObject, KnownParameters } from './type';
|
||||
import type { GenerateOpenApiDocumentOptionsFilters } from './generate_oas';
|
||||
import { Env } from './generate_oas';
|
||||
|
||||
const tagPrefix = 'oas-tag:';
|
||||
const extractTag = (tag: string) => {
|
||||
|
@ -183,7 +184,8 @@ export const getXsrfHeaderForMethod = (
|
|||
|
||||
export const setXState = (
|
||||
availability: RouteConfigOptions<RouteMethod>['availability'],
|
||||
operation: CustomOperationObject
|
||||
operation: CustomOperationObject,
|
||||
env: Env
|
||||
): void => {
|
||||
if (availability) {
|
||||
let state = '';
|
||||
|
@ -194,7 +196,7 @@ export const setXState = (
|
|||
} else if (availability.stability === 'beta') {
|
||||
state = 'Beta';
|
||||
}
|
||||
if (availability.since) {
|
||||
if (!env.serverless && availability.since) {
|
||||
state = state ? `${state}; added in ${availability.since}` : `Added in ${availability.since}`;
|
||||
}
|
||||
operation['x-state'] = state;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue