From aac9d14eca79057ab47f2e5505dadcd63cbe318b Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Fri, 30 Jan 2026 14:33:10 +0200 Subject: [PATCH 01/23] Boilerplate from scaffolding command --- .../test/scout/api/fixtures/constants.ts | 14 ++++++++ .../test/scout/api/fixtures/index.ts | 15 +++++++++ .../test/scout/api/playwright.config.ts | 14 ++++++++ .../test/scout/api/tests/example.spec.ts | 32 +++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 src/platform/plugins/shared/dashboard/test/scout/api/fixtures/constants.ts create mode 100644 src/platform/plugins/shared/dashboard/test/scout/api/fixtures/index.ts create mode 100644 src/platform/plugins/shared/dashboard/test/scout/api/playwright.config.ts create mode 100644 src/platform/plugins/shared/dashboard/test/scout/api/tests/example.spec.ts diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/constants.ts b/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/constants.ts new file mode 100644 index 0000000000000..3007dbbaae230 --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/constants.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export const COMMON_HEADERS = { + 'kbn-xsrf': 'some-xsrf-token', + 'x-elastic-internal-origin': 'kibana', + 'Content-Type': 'application/json;charset=UTF-8', +}; diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/index.ts b/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/index.ts new file mode 100644 index 0000000000000..99c7c65006d3a --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { ScoutTestFixtures, ScoutWorkerFixtures } from '@kbn/scout'; +import { apiTest as baseApiTest } from '@kbn/scout'; + +export const apiTest = baseApiTest.extend({}); + +export * as testData from './constants'; diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/playwright.config.ts b/src/platform/plugins/shared/dashboard/test/scout/api/playwright.config.ts new file mode 100644 index 0000000000000..72df09a207161 --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout/api/playwright.config.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { createPlaywrightConfig } from '@kbn/scout'; + +export default createPlaywrightConfig({ + testDir: './tests', +}); diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/example.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/example.spec.ts new file mode 100644 index 0000000000000..78618ffe4b05c --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/example.spec.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { RoleApiCredentials } from '@kbn/scout'; +import { apiTest, expect, tags } from '@kbn/scout'; +import { testData } from '../fixtures'; + +apiTest.describe('Scout API test suite example', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { + let viewerApiCredentials: RoleApiCredentials; + + apiTest.beforeAll(async ({ requestAuth }) => { + viewerApiCredentials = await requestAuth.getApiKey('viewer'); + }); + + apiTest('should complete a basic API flow', async ({ apiClient }) => { + const response = await apiClient.post('kibana/api', { + headers: { + ...viewerApiCredentials.apiKeyHeader, + ...testData.COMMON_HEADERS, + }, + responseType: 'json', + body: {}, + }); + expect(response.statusCode).toBe(200); + }); +}); From 446d7748991c8c4c2492c679eec1b1967bfa096a Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Sat, 31 Jan 2026 10:12:55 +0200 Subject: [PATCH 02/23] Migrate Dashboard's FTR CRUD API tests to Scout --- .../configs/default/stateful/base.config.ts | 2 + .../test/scout/api/fixtures/constants.ts | 19 +- .../test/scout/api/fixtures/index.ts | 2 +- .../scout/api/fixtures/schema_snapshot.json | 27 +++ .../scout/api/tests/create_dashboard.spec.ts | 163 ++++++++++++++++++ .../api/tests/create_dashboard_schema.spec.ts | 69 ++++++++ .../scout/api/tests/delete_dashboard.spec.ts | 61 +++++++ .../test/scout/api/tests/example.spec.ts | 32 ---- .../scout/api/tests/get_dashboard.spec.ts | 63 +++++++ .../scout/api/tests/search_dashboards.spec.ts | 100 +++++++++++ .../scout/api/tests/update_dashboard.spec.ts | 115 ++++++++++++ 11 files changed, 618 insertions(+), 35 deletions(-) create mode 100644 src/platform/plugins/shared/dashboard/test/scout/api/fixtures/schema_snapshot.json create mode 100644 src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard.spec.ts create mode 100644 src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts create mode 100644 src/platform/plugins/shared/dashboard/test/scout/api/tests/delete_dashboard.spec.ts delete mode 100644 src/platform/plugins/shared/dashboard/test/scout/api/tests/example.spec.ts create mode 100644 src/platform/plugins/shared/dashboard/test/scout/api/tests/get_dashboard.spec.ts create mode 100644 src/platform/plugins/shared/dashboard/test/scout/api/tests/search_dashboards.spec.ts create mode 100644 src/platform/plugins/shared/dashboard/test/scout/api/tests/update_dashboard.spec.ts diff --git a/src/platform/packages/shared/kbn-scout/src/servers/configs/default/stateful/base.config.ts b/src/platform/packages/shared/kbn-scout/src/servers/configs/default/stateful/base.config.ts index 2c900a1e42b8a..57be897254e6d 100644 --- a/src/platform/packages/shared/kbn-scout/src/servers/configs/default/stateful/base.config.ts +++ b/src/platform/packages/shared/kbn-scout/src/servers/configs/default/stateful/base.config.ts @@ -170,6 +170,8 @@ export const defaultConfig: ScoutServerConfig = { '--savedObjects.allowHttpApiAccess=false', // override default to not allow hiddenFromHttpApis saved objects access to the http APIs see https://github.com/elastic/dev/issues/2200 // explicitly disable internal API restriction. See https://github.com/elastic/kibana/issues/163654 '--server.restrictInternalApis=false', + // Enable OpenAPI specification endpoint for schema validation tests + '--server.oas.enabled=true', // disable fleet task that writes to metrics.fleet_server.* data streams, impacting functional tests `--xpack.task_manager.unsafe.exclude_task_types=${JSON.stringify(['Fleet-Metrics-Task'])}`, // x-pack/platform/test/api_integration/config.ts diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/constants.ts b/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/constants.ts index 3007dbbaae230..106f3181d5906 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/constants.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/constants.ts @@ -7,8 +7,23 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +/** The base API path for dashboard endpoints (no leading slash for apiClient). */ +export const DASHBOARD_API_PATH = 'api/dashboards'; + +/** Common headers for Dashboard API requests (internal API version 1) */ export const COMMON_HEADERS = { 'kbn-xsrf': 'some-xsrf-token', 'x-elastic-internal-origin': 'kibana', - 'Content-Type': 'application/json;charset=UTF-8', -}; + 'elastic-api-version': '1', +} as const; + +/** Test data paths */ +export const KBN_ARCHIVES = { + BASIC: 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/basic.json', + TAGS: 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/tags.json', + MANY_DASHBOARDS: + 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/many-dashboards.json', +} as const; + +/** Test dashboard ID used in fixtures - is a saved object loaded by the kbn_archiver */ +export const TEST_DASHBOARD_ID = 'be3733a0-9efe-11e7-acb3-3dab96693fab'; diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/index.ts b/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/index.ts index 99c7c65006d3a..358d1df816071 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/index.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/index.ts @@ -12,4 +12,4 @@ import { apiTest as baseApiTest } from '@kbn/scout'; export const apiTest = baseApiTest.extend({}); -export * as testData from './constants'; +export { COMMON_HEADERS, DASHBOARD_API_PATH, KBN_ARCHIVES, TEST_DASHBOARD_ID } from './constants'; diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/schema_snapshot.json b/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/schema_snapshot.json new file mode 100644 index 0000000000000..3a669f02e3f0d --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/schema_snapshot.json @@ -0,0 +1,27 @@ +[ + { + "type": "object", + "description": "Markdown embeddable schema", + "properties": { + "content": { + "type": "string" + }, + "description": { + "type": "string" + }, + "hide_title": { + "type": "boolean" + }, + "title": { + "type": "string" + } + }, + "additionalProperties": false, + "required": ["content"] + }, + { + "type": "object", + "properties": {}, + "additionalProperties": true + } +] diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard.spec.ts new file mode 100644 index 0000000000000..c051488bb5fc7 --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard.spec.ts @@ -0,0 +1,163 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { RoleApiCredentials } from '@kbn/scout'; +import { expect } from '@kbn/scout/api'; +import { tags } from '@kbn/scout'; +import { + apiTest, + COMMON_HEADERS, + DASHBOARD_API_PATH, + KBN_ARCHIVES, + TEST_DASHBOARD_ID, +} from '../fixtures'; + +apiTest.describe('dashboards - create', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { + let editorCredentials: RoleApiCredentials; + + apiTest.beforeAll(async ({ kbnClient, requestAuth }) => { + editorCredentials = await requestAuth.getApiKey('editor'); + await kbnClient.importExport.load(KBN_ARCHIVES.BASIC); + await kbnClient.importExport.load(KBN_ARCHIVES.TAGS); + }); + + apiTest.afterAll(async ({ kbnClient }) => { + await kbnClient.savedObjects.cleanStandardList(); + }); + + apiTest('should create a dashboard', async ({ apiClient }) => { + const title = 'Hello world dashboard'; + + const response = await apiClient.post(DASHBOARD_API_PATH, { + headers: { + ...COMMON_HEADERS, + ...editorCredentials.apiKeyHeader, + }, + body: { + data: { + title, + }, + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(200); + expect(response.body.spaces).toStrictEqual(['default']); + expect(response.body.data).toStrictEqual({ + title, + }); + }); + + apiTest('can create a dashboard with a specific id', async ({ apiClient }) => { + const title = `foo-${Date.now()}-${Math.random()}`; + const id = `bar-${Date.now()}-${Math.random()}`; + + const response = await apiClient.post(DASHBOARD_API_PATH, { + headers: { + ...COMMON_HEADERS, + ...editorCredentials.apiKeyHeader, + }, + body: { + id, + data: { + title, + }, + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(200); + expect(response.body.id).toBe(id); + }); + + // TODO Maybe move this test to x-pack/platform/test/api_integration/dashboards + apiTest('can create a dashboard in a defined space', async ({ apiClient }) => { + const title = `foo-${Date.now()}-${Math.random()}`; + const spaceId = 'space-1'; + + const response = await apiClient.post(DASHBOARD_API_PATH, { + headers: { + ...COMMON_HEADERS, + ...editorCredentials.apiKeyHeader, + }, + body: { + data: { + title, + }, + spaces: [spaceId], + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(200); + expect(response.body.spaces).toStrictEqual([spaceId]); + }); + + apiTest('return error if provided id already exists', async ({ apiClient }) => { + const title = `foo-${Date.now()}-${Math.random()}`; + + const response = await apiClient.post(DASHBOARD_API_PATH, { + headers: { + ...COMMON_HEADERS, + ...editorCredentials.apiKeyHeader, + }, + body: { + id: TEST_DASHBOARD_ID, + data: { + title, + }, + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(409); + expect(response.body.message).toBe(`A dashboard with ID ${TEST_DASHBOARD_ID} already exists.`); + }); + + apiTest('validation - returns error when title is not provided', async ({ apiClient }) => { + const response = await apiClient.post(DASHBOARD_API_PATH, { + headers: { + ...COMMON_HEADERS, + ...editorCredentials.apiKeyHeader, + }, + body: { + data: {}, + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(400); + expect(response.body.statusCode).toBe(400); + expect(response.body.message).toBe( + '[request body.data.title]: expected value of type [string] but got [undefined]' + ); + }); + + apiTest('validation - returns error if panels is not an array', async ({ apiClient }) => { + const response = await apiClient.post(DASHBOARD_API_PATH, { + headers: { + ...COMMON_HEADERS, + ...editorCredentials.apiKeyHeader, + }, + body: { + data: { + title: 'foo', + panels: {}, + }, + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(400); + expect(response.body.statusCode).toBe(400); + expect(response.body.message).toBe( + '[request body.data.panels]: expected value of type [array] but got [Object]' + ); + }); +}); diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts new file mode 100644 index 0000000000000..a2bc02e89a7a5 --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { RoleApiCredentials } from '@kbn/scout'; +import { expect } from '@kbn/scout/api'; +import { tags } from '@kbn/scout'; +import { apiTest, DASHBOARD_API_PATH, KBN_ARCHIVES } from '../fixtures'; +import snapshot from '../fixtures/schema_snapshot.json'; + +apiTest.describe('dashboard REST schema', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { + let viewerCredentials: RoleApiCredentials; + + apiTest.beforeAll(async ({ kbnClient, requestAuth }) => { + viewerCredentials = await requestAuth.getApiKey('viewer'); + await kbnClient.importExport.load(KBN_ARCHIVES.BASIC); + await kbnClient.importExport.load(KBN_ARCHIVES.TAGS); + }); + + apiTest.afterAll(async ({ kbnClient }) => { + await kbnClient.savedObjects.cleanStandardList(); + }); + + /** + * Only additive changes are allowed to Dashboard REST schemas + * + * This test exists to ping #kibana-presentation of any embeddable schema changes + * since the dashboard schema includes embeddable schemas. + * + * If this test is failing, the changed embeddable schema needs to be be reviewed + * to ensure its ready for public distribution. + * + * Once an embeddable schema has been published, + * it can only be changed with additive changes. + */ + apiTest('Registered embeddable schemas have not changed', async ({ apiClient }) => { + // OAS paths are stored with leading slashes, so we need to use the full path here + const oasPath = `/${DASHBOARD_API_PATH}`; + const response = await apiClient.get( + `api/oas?pathStartsWith=${oasPath}&access=internal&version=1`, + { + headers: { + ...viewerCredentials.apiKeyHeader, + }, + responseType: 'json', + } + ); + + expect(response.statusCode).toBe(200); + + const createBodySchema = + response.body.paths[oasPath].post.requestBody.content[ + 'application/json; Elastic-Api-Version=1' + ].schema; + const panelsSchema = createBodySchema.properties.data.properties.panels; + const panelSchema = panelsSchema.items.anyOf.find( + (schema: { properties: Record }) => 'config' in schema.properties + ); + const configSchema = panelSchema.properties.config; + + expect(configSchema.anyOf).toHaveLength(2); + expect(configSchema.anyOf).toStrictEqual(snapshot); + }); +}); diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/delete_dashboard.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/delete_dashboard.spec.ts new file mode 100644 index 0000000000000..186c7214083ec --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/delete_dashboard.spec.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { RoleApiCredentials } from '@kbn/scout'; +import { expect } from '@kbn/scout/api'; +import { tags } from '@kbn/scout'; +import { + apiTest, + COMMON_HEADERS, + DASHBOARD_API_PATH, + KBN_ARCHIVES, + TEST_DASHBOARD_ID, +} from '../fixtures'; + +apiTest.describe('dashboards - delete', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { + let editorCredentials: RoleApiCredentials; + + apiTest.beforeAll(async ({ kbnClient, requestAuth }) => { + editorCredentials = await requestAuth.getApiKey('editor'); + await kbnClient.importExport.load(KBN_ARCHIVES.BASIC); + }); + + apiTest.afterAll(async ({ kbnClient }) => { + await kbnClient.savedObjects.cleanStandardList(); + }); + + apiTest('should return 404 for a non-existent dashboard', async ({ apiClient }) => { + const response = await apiClient.delete(`${DASHBOARD_API_PATH}/non-existent-dashboard`, { + headers: { + ...COMMON_HEADERS, + ...editorCredentials.apiKeyHeader, + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(404); + expect(response.body).toStrictEqual({ + statusCode: 404, + error: 'Not Found', + message: 'A dashboard with ID non-existent-dashboard was not found.', + }); + }); + + apiTest('should return 200 if the dashboard is deleted', async ({ apiClient }) => { + const response = await apiClient.delete(`${DASHBOARD_API_PATH}/${TEST_DASHBOARD_ID}`, { + headers: { + ...COMMON_HEADERS, + ...editorCredentials.apiKeyHeader, + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(200); + }); +}); diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/example.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/example.spec.ts deleted file mode 100644 index 78618ffe4b05c..0000000000000 --- a/src/platform/plugins/shared/dashboard/test/scout/api/tests/example.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { RoleApiCredentials } from '@kbn/scout'; -import { apiTest, expect, tags } from '@kbn/scout'; -import { testData } from '../fixtures'; - -apiTest.describe('Scout API test suite example', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { - let viewerApiCredentials: RoleApiCredentials; - - apiTest.beforeAll(async ({ requestAuth }) => { - viewerApiCredentials = await requestAuth.getApiKey('viewer'); - }); - - apiTest('should complete a basic API flow', async ({ apiClient }) => { - const response = await apiClient.post('kibana/api', { - headers: { - ...viewerApiCredentials.apiKeyHeader, - ...testData.COMMON_HEADERS, - }, - responseType: 'json', - body: {}, - }); - expect(response.statusCode).toBe(200); - }); -}); diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/get_dashboard.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/get_dashboard.spec.ts new file mode 100644 index 0000000000000..37af088f58982 --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/get_dashboard.spec.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { RoleApiCredentials } from '@kbn/scout'; +import { expect } from '@kbn/scout/api'; +import { tags } from '@kbn/scout'; +import { + apiTest, + COMMON_HEADERS, + DASHBOARD_API_PATH, + KBN_ARCHIVES, + TEST_DASHBOARD_ID, +} from '../fixtures'; + +apiTest.describe('dashboards - get', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { + let viewerCredentials: RoleApiCredentials; + + apiTest.beforeAll(async ({ kbnClient, requestAuth }) => { + viewerCredentials = await requestAuth.getApiKey('viewer'); + await kbnClient.importExport.load(KBN_ARCHIVES.BASIC); + await kbnClient.importExport.load(KBN_ARCHIVES.TAGS); + }); + + apiTest.afterAll(async ({ kbnClient }) => { + await kbnClient.savedObjects.cleanStandardList(); + }); + + apiTest('should return 200 with an existing dashboard', async ({ apiClient }) => { + const response = await apiClient.get(`${DASHBOARD_API_PATH}/${TEST_DASHBOARD_ID}`, { + headers: { + ...COMMON_HEADERS, + ...viewerCredentials.apiKeyHeader, + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(200); + expect(response.body.id).toBe(TEST_DASHBOARD_ID); + expect(response.body.data.title).toBe('Requests'); + + // Does not return unsupported options from the saved object + expect(response.body.data.options).toBeUndefined(); + expect(response.body.data.refresh_interval?.display).toBeUndefined(); + }); + + apiTest('should return 404 with a non-existing dashboard', async ({ apiClient }) => { + const response = await apiClient.get(`${DASHBOARD_API_PATH}/does-not-exist`, { + headers: { + ...COMMON_HEADERS, + ...viewerCredentials.apiKeyHeader, + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(404); + }); +}); diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/search_dashboards.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/search_dashboards.spec.ts new file mode 100644 index 0000000000000..1d92d95d51123 --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/search_dashboards.spec.ts @@ -0,0 +1,100 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { RoleApiCredentials } from '@kbn/scout'; +import { expect } from '@kbn/scout/api'; +import { tags } from '@kbn/scout'; +import { apiTest, COMMON_HEADERS, KBN_ARCHIVES } from '../fixtures'; + +const SEARCH_ENDPOINT = 'api/dashboards/search'; + +apiTest.describe('dashboards - search', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { + let viewerCredentials: RoleApiCredentials; + + apiTest.beforeAll(async ({ kbnClient, requestAuth }) => { + viewerCredentials = await requestAuth.getApiKey('viewer'); + await kbnClient.importExport.load(KBN_ARCHIVES.MANY_DASHBOARDS); + }); + + apiTest.afterAll(async ({ kbnClient }) => { + await kbnClient.savedObjects.cleanStandardList(); + }); + + apiTest('should retrieve a paginated list of dashboards', async ({ apiClient }) => { + const response = await apiClient.post(SEARCH_ENDPOINT, { + headers: { + ...COMMON_HEADERS, + ...viewerCredentials.apiKeyHeader, + }, + body: {}, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(200); + expect(response.body.total).toBe(100); + expect(response.body.dashboards[0].id).toBe('test-dashboard-00'); + expect(response.body.dashboards).toHaveLength(20); + }); + + apiTest('should narrow results by search', async ({ apiClient }) => { + const response = await apiClient.post(SEARCH_ENDPOINT, { + headers: { + ...COMMON_HEADERS, + ...viewerCredentials.apiKeyHeader, + }, + body: { + search: '0*', + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(200); + expect(response.body.total).toBe(1); + expect(response.body.dashboards).toHaveLength(1); + }); + + apiTest('should allow users to set a per page limit', async ({ apiClient }) => { + const response = await apiClient.post(SEARCH_ENDPOINT, { + headers: { + ...COMMON_HEADERS, + ...viewerCredentials.apiKeyHeader, + }, + body: { + per_page: 10, + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(200); + expect(response.body.total).toBe(100); + expect(response.body.dashboards).toHaveLength(10); + }); + + apiTest( + 'should allow users to paginate through the list of dashboards', + async ({ apiClient }) => { + const response = await apiClient.post(SEARCH_ENDPOINT, { + headers: { + ...COMMON_HEADERS, + ...viewerCredentials.apiKeyHeader, + }, + body: { + page: 5, + per_page: 10, + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(200); + expect(response.body.total).toBe(100); + expect(response.body.dashboards).toHaveLength(10); + expect(response.body.dashboards[0].id).toBe('test-dashboard-40'); + } + ); +}); diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/update_dashboard.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/update_dashboard.spec.ts new file mode 100644 index 0000000000000..cd5904c1fd1c1 --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/update_dashboard.spec.ts @@ -0,0 +1,115 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { RoleApiCredentials } from '@kbn/scout'; +import { expect } from '@kbn/scout/api'; +import { tags } from '@kbn/scout'; +import { + apiTest, + COMMON_HEADERS, + DASHBOARD_API_PATH, + KBN_ARCHIVES, + TEST_DASHBOARD_ID, +} from '../fixtures'; + +apiTest.describe('dashboards - update', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { + let editorCredentials: RoleApiCredentials; + + apiTest.beforeAll(async ({ kbnClient, requestAuth }) => { + editorCredentials = await requestAuth.getApiKey('editor'); + await kbnClient.importExport.load(KBN_ARCHIVES.BASIC); + await kbnClient.importExport.load(KBN_ARCHIVES.TAGS); + }); + + apiTest.afterAll(async ({ kbnClient }) => { + await kbnClient.savedObjects.cleanStandardList(); + }); + + apiTest('should return 200 with an updated dashboard', async ({ apiClient }) => { + const response = await apiClient.put(`${DASHBOARD_API_PATH}/${TEST_DASHBOARD_ID}`, { + headers: { + ...COMMON_HEADERS, + ...editorCredentials.apiKeyHeader, + }, + body: { + data: { + title: 'Refresh Requests (Updated)', + }, + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(200); + expect(response.body.id).toBe(TEST_DASHBOARD_ID); + expect(response.body.data.title).toBe('Refresh Requests (Updated)'); + }); + + apiTest('should return 404 when updating a non-existent dashboard', async ({ apiClient }) => { + const response = await apiClient.put(`${DASHBOARD_API_PATH}/not-an-id`, { + headers: { + ...COMMON_HEADERS, + ...editorCredentials.apiKeyHeader, + }, + body: { + data: { + title: 'Some other dashboard (updated)', + }, + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(404); + expect(response.body).toStrictEqual({ + statusCode: 404, + error: 'Not Found', + message: 'A dashboard with ID not-an-id was not found.', + }); + }); + + apiTest('validation - returns error when object is not provided', async ({ apiClient }) => { + const response = await apiClient.put(`${DASHBOARD_API_PATH}/${TEST_DASHBOARD_ID}`, { + headers: { + ...COMMON_HEADERS, + ...editorCredentials.apiKeyHeader, + }, + body: { + data: {}, + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(400); + expect(response.body.statusCode).toBe(400); + expect(response.body.message).toBe( + '[request body.data.title]: expected value of type [string] but got [undefined]' + ); + }); + + apiTest('validation - returns error if panels is not an array', async ({ apiClient }) => { + const response = await apiClient.put(`${DASHBOARD_API_PATH}/${TEST_DASHBOARD_ID}`, { + headers: { + ...COMMON_HEADERS, + ...editorCredentials.apiKeyHeader, + }, + body: { + data: { + title: 'foo', + panels: {}, + }, + }, + responseType: 'json', + }); + + expect(response).toHaveStatusCode(400); + expect(response.body.statusCode).toBe(400); + expect(response.body.message).toBe( + '[request body.data.panels]: expected value of type [array] but got [Object]' + ); + }); +}); From 2866bbc73e593a3e486f8ffc7710a4106b4cd016 Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Sat, 31 Jan 2026 11:17:59 +0200 Subject: [PATCH 03/23] Remove FTR tests and update CI configuration --- .buildkite/scout_ci_config.yml | 1 + .github/CODEOWNERS | 1 - .../apis/dashboards/create_dashboard/index.ts | 37 ------- .../apis/dashboards/create_dashboard/main.ts | 103 ------------------ .../dashboards/create_dashboard/schema.ts | 60 ---------- .../create_dashboard/schema_snapshot.json | 27 ----- .../dashboards/create_dashboard/validation.ts | 52 --------- .../apis/dashboards/delete_dashboard/index.ts | 29 ----- .../apis/dashboards/delete_dashboard/main.ts | 44 -------- .../apis/dashboards/get_dashboard/index.ts | 35 ------ .../apis/dashboards/get_dashboard/main.ts | 44 -------- .../api_integration/apis/dashboards/index.ts | 20 ---- .../dashboards/search_dashboards/index.ts | 29 ----- .../apis/dashboards/search_dashboards/main.ts | 73 ------------- .../apis/dashboards/update_dashboard/index.ts | 35 ------ .../apis/dashboards/update_dashboard/main.ts | 55 ---------- .../dashboards/update_dashboard/validation.ts | 52 --------- .../test/api_integration/apis/index.ts | 1 - 18 files changed, 1 insertion(+), 697 deletions(-) delete mode 100644 src/platform/test/api_integration/apis/dashboards/create_dashboard/index.ts delete mode 100644 src/platform/test/api_integration/apis/dashboards/create_dashboard/main.ts delete mode 100644 src/platform/test/api_integration/apis/dashboards/create_dashboard/schema.ts delete mode 100644 src/platform/test/api_integration/apis/dashboards/create_dashboard/schema_snapshot.json delete mode 100644 src/platform/test/api_integration/apis/dashboards/create_dashboard/validation.ts delete mode 100644 src/platform/test/api_integration/apis/dashboards/delete_dashboard/index.ts delete mode 100644 src/platform/test/api_integration/apis/dashboards/delete_dashboard/main.ts delete mode 100644 src/platform/test/api_integration/apis/dashboards/get_dashboard/index.ts delete mode 100644 src/platform/test/api_integration/apis/dashboards/get_dashboard/main.ts delete mode 100644 src/platform/test/api_integration/apis/dashboards/index.ts delete mode 100644 src/platform/test/api_integration/apis/dashboards/search_dashboards/index.ts delete mode 100644 src/platform/test/api_integration/apis/dashboards/search_dashboards/main.ts delete mode 100644 src/platform/test/api_integration/apis/dashboards/update_dashboard/index.ts delete mode 100644 src/platform/test/api_integration/apis/dashboards/update_dashboard/main.ts delete mode 100644 src/platform/test/api_integration/apis/dashboards/update_dashboard/validation.ts diff --git a/.buildkite/scout_ci_config.yml b/.buildkite/scout_ci_config.yml index 745d4bdf395a5..eab4cc4f972c1 100644 --- a/.buildkite/scout_ci_config.yml +++ b/.buildkite/scout_ci_config.yml @@ -3,6 +3,7 @@ plugins: enabled: - apm - console + - dashboard - discover_enhanced - index_management - infra diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e8d386acb0dde..d2f3f5be1e255 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1780,7 +1780,6 @@ x-pack/platform/plugins/shared/streams_app/public/components/data_management/str /x-pack/platform/test/fixtures/es_archives/dashboard/async_search @elastic/kibana-presentation /src/platform/test/functional/fixtures/kbn_archiver/dashboard @elastic/kibana-presentation /src/platform/test/functional/fixtures/kbn_archiver/canvas @elastic/kibana-presentation -/src/platform/test/api_integration/apis/dashboards @elastic/kibana-presentation /src/platform/test/interpreter_functional/snapshots @elastic/kibana-presentation # Assigned per https://github.com/elastic/kibana/pull/54342 /src/platform/test/functional/services/inspector.ts @elastic/kibana-presentation /x-pack/platform/test/functional/services/canvas_element.ts @elastic/kibana-presentation diff --git a/src/platform/test/api_integration/apis/dashboards/create_dashboard/index.ts b/src/platform/test/api_integration/apis/dashboards/create_dashboard/index.ts deleted file mode 100644 index 1af67018eb8ae..0000000000000 --- a/src/platform/test/api_integration/apis/dashboards/create_dashboard/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService, loadTestFile }: FtrProviderContext) { - const kibanaServer = getService('kibanaServer'); - describe('dashboards - create', () => { - before(async () => { - await kibanaServer.importExport.load( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/basic.json' - ); - await kibanaServer.importExport.load( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/tags.json' - ); - }); - - after(async () => { - await kibanaServer.savedObjects.cleanStandardList(); - await kibanaServer.importExport.unload( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/basic.json' - ); - await kibanaServer.importExport.unload( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/tags.json' - ); - }); - loadTestFile(require.resolve('./main')); - loadTestFile(require.resolve('./validation')); - loadTestFile(require.resolve('./schema')); - }); -} diff --git a/src/platform/test/api_integration/apis/dashboards/create_dashboard/main.ts b/src/platform/test/api_integration/apis/dashboards/create_dashboard/main.ts deleted file mode 100644 index 377dc06f4e249..0000000000000 --- a/src/platform/test/api_integration/apis/dashboards/create_dashboard/main.ts +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import expect from '@kbn/expect'; -import { DASHBOARD_API_PATH } from '@kbn/dashboard-plugin/server'; -import type { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - describe('main', () => { - it('should create a dashboard', async () => { - const title = 'Hello world dashboard'; - - const response = await supertest - .post(DASHBOARD_API_PATH) - .set('kbn-xsrf', 'true') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send({ - data: { - title, - }, - }); - - expect(response.status).to.be(200); - expect(response.body.spaces).to.eql(['default']); - expect(response.body.data).to.eql({ - title, - }); - }); - - it('can create a dashboard with a specific id', async () => { - const title = `foo-${Date.now()}-${Math.random()}`; - const id = `bar-${Date.now()}-${Math.random()}`; - - const response = await supertest - .post(DASHBOARD_API_PATH) - .set('kbn-xsrf', 'true') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send({ - id, - data: { - title, - }, - }); - - expect(response.status).to.be(200); - expect(response.body.id).to.be(id); - }); - - // TODO Maybe move this test to x-pack/platform/test/api_integration/dashboards - it('can create a dashboard in a defined space', async () => { - const title = `foo-${Date.now()}-${Math.random()}`; - - const spaceId = 'space-1'; - - const response = await supertest - .post(DASHBOARD_API_PATH) - .set('kbn-xsrf', 'true') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send({ - data: { - title, - }, - spaces: [spaceId], - }); - - expect(response.status).to.be(200); - expect(response.body.spaces).to.eql([spaceId]); - }); - - it('return error if provided id already exists', async () => { - const title = `foo-${Date.now()}-${Math.random()}`; - // id is a saved object loaded by the kbn_archiver - const id = 'be3733a0-9efe-11e7-acb3-3dab96693fab'; - - const response = await supertest - .post(DASHBOARD_API_PATH) - .set('kbn-xsrf', 'true') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send({ - id, - data: { - title, - }, - }); - - expect(response.status).to.be(409); - expect(response.body.message).to.be( - 'A dashboard with ID be3733a0-9efe-11e7-acb3-3dab96693fab already exists.' - ); - }); - }); -} diff --git a/src/platform/test/api_integration/apis/dashboards/create_dashboard/schema.ts b/src/platform/test/api_integration/apis/dashboards/create_dashboard/schema.ts deleted file mode 100644 index 8d21aaed9709d..0000000000000 --- a/src/platform/test/api_integration/apis/dashboards/create_dashboard/schema.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import expect from '@kbn/expect'; -import { DASHBOARD_API_PATH } from '@kbn/dashboard-plugin/server'; -import type { FtrProviderContext } from '../../../ftr_provider_context'; - -// eslint-disable-next-line @typescript-eslint/no-var-requires -const snapshot = require('./schema_snapshot.json'); - -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - describe('dashboard REST schema', () => { - /** - * Only additive changes are allowed to Dashboard REST schemas - * - * This test exists to ping #kibana-presentation of any embeddable schema changes - * since the dashboard schema includes embeddable schemas. - * - * If this test is failing, the changed embeddable schema needs to be be reviewed - * to ensure its ready for public distribution. - * - * Once an embeddable schema has been published, - * it can only be changed with additive changes. - */ - it('Registered embeddable schemas have not changed', async () => { - const response = await supertest - .get(`/api/oas?pathStartsWith=${DASHBOARD_API_PATH}&access=internal&version=1`) - .send(); - - expect(response.status).to.be(200); - const createBodySchema = - response.body.paths[DASHBOARD_API_PATH].post.requestBody.content[ - 'application/json; Elastic-Api-Version=1' - ].schema; - const panelsSchema = createBodySchema.properties.data.properties.panels; - const panelSchema = panelsSchema.items.anyOf.find( - (schema: any) => 'config' in schema.properties - ); - const configSchema = panelSchema.properties.config; - expect(configSchema.anyOf.length).to.be(2); - - // API integration tests do not support jest expect - // so we had to roll our own toMatchSnapshot - // To update snapshot: - // 1) uncomment console.log - // 2) run test - // 3) replace snapshot file contents with copy of consoled output - // console.log(JSON.stringify(configSchema.anyOf, null, ' ')); - - expect(configSchema.anyOf).eql(snapshot); - }); - }); -} diff --git a/src/platform/test/api_integration/apis/dashboards/create_dashboard/schema_snapshot.json b/src/platform/test/api_integration/apis/dashboards/create_dashboard/schema_snapshot.json deleted file mode 100644 index 3a669f02e3f0d..0000000000000 --- a/src/platform/test/api_integration/apis/dashboards/create_dashboard/schema_snapshot.json +++ /dev/null @@ -1,27 +0,0 @@ -[ - { - "type": "object", - "description": "Markdown embeddable schema", - "properties": { - "content": { - "type": "string" - }, - "description": { - "type": "string" - }, - "hide_title": { - "type": "boolean" - }, - "title": { - "type": "string" - } - }, - "additionalProperties": false, - "required": ["content"] - }, - { - "type": "object", - "properties": {}, - "additionalProperties": true - } -] diff --git a/src/platform/test/api_integration/apis/dashboards/create_dashboard/validation.ts b/src/platform/test/api_integration/apis/dashboards/create_dashboard/validation.ts deleted file mode 100644 index cb8815721c8af..0000000000000 --- a/src/platform/test/api_integration/apis/dashboards/create_dashboard/validation.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import expect from '@kbn/expect'; -import { DASHBOARD_API_PATH } from '@kbn/dashboard-plugin/server'; -import type { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - describe('validation', () => { - it('returns error when title is not provided', async () => { - const response = await supertest - .post(DASHBOARD_API_PATH) - .set('kbn-xsrf', 'true') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send({ - data: {}, - }); - expect(response.status).to.be(400); - expect(response.body.statusCode).to.be(400); - expect(response.body.message).to.be( - '[request body.data.title]: expected value of type [string] but got [undefined]' - ); - }); - - it('returns error if panels is not an array', async () => { - const response = await supertest - .post(DASHBOARD_API_PATH) - .set('kbn-xsrf', 'true') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send({ - data: { - title: 'foo', - panels: {}, - }, - }); - expect(response.status).to.be(400); - expect(response.body.statusCode).to.be(400); - expect(response.body.message).to.be( - '[request body.data.panels]: expected value of type [array] but got [Object]' - ); - }); - }); -} diff --git a/src/platform/test/api_integration/apis/dashboards/delete_dashboard/index.ts b/src/platform/test/api_integration/apis/dashboards/delete_dashboard/index.ts deleted file mode 100644 index 80d15de16ef6d..0000000000000 --- a/src/platform/test/api_integration/apis/dashboards/delete_dashboard/index.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService, loadTestFile }: FtrProviderContext) { - const kibanaServer = getService('kibanaServer'); - describe('dashboards - delete', () => { - before(async () => { - await kibanaServer.importExport.load( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/basic.json' - ); - }); - - after(async () => { - await kibanaServer.savedObjects.cleanStandardList(); - await kibanaServer.importExport.unload( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/basic.json' - ); - }); - loadTestFile(require.resolve('./main')); - }); -} diff --git a/src/platform/test/api_integration/apis/dashboards/delete_dashboard/main.ts b/src/platform/test/api_integration/apis/dashboards/delete_dashboard/main.ts deleted file mode 100644 index 920d076969f6e..0000000000000 --- a/src/platform/test/api_integration/apis/dashboards/delete_dashboard/main.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import expect from '@kbn/expect'; -import { DASHBOARD_API_PATH } from '@kbn/dashboard-plugin/server'; -import type { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - describe('main', () => { - it('should return 404 for a non-existent dashboard', async () => { - const response = await supertest - .delete(`${DASHBOARD_API_PATH}/non-existent-dashboard`) - .set('kbn-xsrf', 'true') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send(); - - expect(response.status).to.be(404); - expect(response.body).to.eql({ - statusCode: 404, - error: 'Not Found', - message: 'A dashboard with ID non-existent-dashboard was not found.', - }); - }); - - it('should return 200 if the dashboard is deleted', async () => { - const response = await supertest - .delete(`${DASHBOARD_API_PATH}/be3733a0-9efe-11e7-acb3-3dab96693fab`) - .set('kbn-xsrf', 'true') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send(); - - expect(response.status).to.be(200); - }); - }); -} diff --git a/src/platform/test/api_integration/apis/dashboards/get_dashboard/index.ts b/src/platform/test/api_integration/apis/dashboards/get_dashboard/index.ts deleted file mode 100644 index f6f542f5f4e57..0000000000000 --- a/src/platform/test/api_integration/apis/dashboards/get_dashboard/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService, loadTestFile }: FtrProviderContext) { - const kibanaServer = getService('kibanaServer'); - describe('dashboards - get', () => { - before(async () => { - await kibanaServer.importExport.load( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/basic.json' - ); - await kibanaServer.importExport.load( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/tags.json' - ); - }); - - after(async () => { - await kibanaServer.savedObjects.cleanStandardList(); - await kibanaServer.importExport.unload( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/basic.json' - ); - await kibanaServer.importExport.unload( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/tags.json' - ); - }); - loadTestFile(require.resolve('./main')); - }); -} diff --git a/src/platform/test/api_integration/apis/dashboards/get_dashboard/main.ts b/src/platform/test/api_integration/apis/dashboards/get_dashboard/main.ts deleted file mode 100644 index 85a40f9c0c1bc..0000000000000 --- a/src/platform/test/api_integration/apis/dashboards/get_dashboard/main.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import expect from '@kbn/expect'; -import { DASHBOARD_API_PATH } from '@kbn/dashboard-plugin/server'; -import type { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - describe('main', () => { - it('should return 200 with an existing dashboard', async () => { - const response = await supertest - .get(`${DASHBOARD_API_PATH}/be3733a0-9efe-11e7-acb3-3dab96693fab`) - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send(); - - expect(response.status).to.be(200); - - expect(response.body.id).to.be('be3733a0-9efe-11e7-acb3-3dab96693fab'); - expect(response.body.data.title).to.be('Requests'); - - // Does not return unsupported options from the saved object - expect(response.body.data.options).to.be(undefined); - expect(response.body.data.refresh_interval).to.not.have.keys(['display']); - }); - - it('should return 404 with a non-existing dashboard', async () => { - const response = await supertest - .get(`${DASHBOARD_API_PATH}/does-not-exist`) - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send(); - - expect(response.status).to.be(404); - }); - }); -} diff --git a/src/platform/test/api_integration/apis/dashboards/index.ts b/src/platform/test/api_integration/apis/dashboards/index.ts deleted file mode 100644 index 826991a611752..0000000000000 --- a/src/platform/test/api_integration/apis/dashboards/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { FtrProviderContext } from '../../ftr_provider_context'; - -export default function ({ loadTestFile }: FtrProviderContext) { - describe('dashboards', () => { - loadTestFile(require.resolve('./create_dashboard')); - loadTestFile(require.resolve('./delete_dashboard')); - loadTestFile(require.resolve('./get_dashboard')); - loadTestFile(require.resolve('./update_dashboard')); - loadTestFile(require.resolve('./search_dashboards')); - }); -} diff --git a/src/platform/test/api_integration/apis/dashboards/search_dashboards/index.ts b/src/platform/test/api_integration/apis/dashboards/search_dashboards/index.ts deleted file mode 100644 index fbcf6a34f6ddd..0000000000000 --- a/src/platform/test/api_integration/apis/dashboards/search_dashboards/index.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService, loadTestFile }: FtrProviderContext) { - const kibanaServer = getService('kibanaServer'); - describe('dashboards - search', () => { - before(async () => { - await kibanaServer.importExport.load( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/many-dashboards.json' - ); - }); - - after(async () => { - await kibanaServer.savedObjects.cleanStandardList(); - await kibanaServer.importExport.unload( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/many-dashboards.json' - ); - }); - loadTestFile(require.resolve('./main')); - }); -} diff --git a/src/platform/test/api_integration/apis/dashboards/search_dashboards/main.ts b/src/platform/test/api_integration/apis/dashboards/search_dashboards/main.ts deleted file mode 100644 index 2a2be7de60d5e..0000000000000 --- a/src/platform/test/api_integration/apis/dashboards/search_dashboards/main.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import expect from '@kbn/expect'; -import type { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - describe('main', () => { - it('should retrieve a paginated list of dashboards', async () => { - const response = await supertest - .post('/api/dashboards/search') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send({}); - - expect(response.status).to.be(200); - expect(response.body.total).to.be(100); - expect(response.body.dashboards[0].id).to.be('test-dashboard-00'); - expect(response.body.dashboards.length).to.be(20); - }); - - it('should narrow results by search', async () => { - const response = await supertest - .post('/api/dashboards/search') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send({ - search: '0*', - }); - - expect(response.status).to.be(200); - expect(response.body.total).to.be(1); - expect(response.body.dashboards.length).to.be(1); - }); - - it('should allow users to set a per page limit', async () => { - const response = await supertest - .post('/api/dashboards/search') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send({ - per_page: 10, - }); - - expect(response.status).to.be(200); - expect(response.body.total).to.be(100); - expect(response.body.dashboards.length).to.be(10); - }); - - it('should allow users to paginate through the list of dashboards', async () => { - const response = await supertest - .post('/api/dashboards/search') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send({ - page: 5, - per_page: 10, - }); - - expect(response.status).to.be(200); - expect(response.body.total).to.be(100); - expect(response.body.dashboards.length).to.be(10); - expect(response.body.dashboards[0].id).to.be('test-dashboard-40'); - }); - }); -} diff --git a/src/platform/test/api_integration/apis/dashboards/update_dashboard/index.ts b/src/platform/test/api_integration/apis/dashboards/update_dashboard/index.ts deleted file mode 100644 index ea72d62468015..0000000000000 --- a/src/platform/test/api_integration/apis/dashboards/update_dashboard/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import type { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService, loadTestFile }: FtrProviderContext) { - const kibanaServer = getService('kibanaServer'); - describe('dashboards - update', () => { - before(async () => { - await kibanaServer.importExport.load( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/basic.json' - ); - await kibanaServer.importExport.load( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/tags.json' - ); - }); - - after(async () => { - await kibanaServer.importExport.unload( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/basic.json' - ); - await kibanaServer.importExport.unload( - 'src/platform/test/api_integration/fixtures/kbn_archiver/saved_objects/tags.json' - ); - }); - loadTestFile(require.resolve('./main')); - loadTestFile(require.resolve('./validation')); - }); -} diff --git a/src/platform/test/api_integration/apis/dashboards/update_dashboard/main.ts b/src/platform/test/api_integration/apis/dashboards/update_dashboard/main.ts deleted file mode 100644 index b32f199ee511c..0000000000000 --- a/src/platform/test/api_integration/apis/dashboards/update_dashboard/main.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import expect from '@kbn/expect'; -import { DASHBOARD_API_PATH } from '@kbn/dashboard-plugin/server'; -import type { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - describe('main', () => { - it('should return 200 with an updated dashboard', async () => { - const response = await supertest - .put(`${DASHBOARD_API_PATH}/be3733a0-9efe-11e7-acb3-3dab96693fab`) - .set('kbn-xsrf', 'true') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send({ - data: { - title: 'Refresh Requests (Updated)', - }, - }); - - expect(response.status).to.be(200); - - expect(response.body.id).to.be('be3733a0-9efe-11e7-acb3-3dab96693fab'); - expect(response.body.data.title).to.be('Refresh Requests (Updated)'); - }); - - it('should return 404 when updating a non-existent dashboard', async () => { - const response = await supertest - .put(`${DASHBOARD_API_PATH}/not-an-id`) - .set('kbn-xsrf', 'true') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send({ - data: { - title: 'Some other dashboard (updated)', - }, - }); - - expect(response.status).to.be(404); - expect(response.body).to.eql({ - statusCode: 404, - error: 'Not Found', - message: 'A dashboard with ID not-an-id was not found.', - }); - }); - }); -} diff --git a/src/platform/test/api_integration/apis/dashboards/update_dashboard/validation.ts b/src/platform/test/api_integration/apis/dashboards/update_dashboard/validation.ts deleted file mode 100644 index af30ae16e7fa5..0000000000000 --- a/src/platform/test/api_integration/apis/dashboards/update_dashboard/validation.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import expect from '@kbn/expect'; -import { DASHBOARD_API_PATH } from '@kbn/dashboard-plugin/server'; -import type { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - describe('validation', () => { - it('returns error when object is not provided', async () => { - const response = await supertest - .put(`${DASHBOARD_API_PATH}/be3733a0-9efe-11e7-acb3-3dab96693fab`) - .set('kbn-xsrf', 'true') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send({ - data: {}, - }); - expect(response.status).to.be(400); - expect(response.body.statusCode).to.be(400); - expect(response.body.message).to.be( - '[request body.data.title]: expected value of type [string] but got [undefined]' - ); - }); - - it('returns error if panels is not an array', async () => { - const response = await supertest - .put(`${DASHBOARD_API_PATH}/be3733a0-9efe-11e7-acb3-3dab96693fab`) - .set('kbn-xsrf', 'true') - .set('ELASTIC_HTTP_VERSION_HEADER', '2023-10-31') - .set('elastic-api-version', '1') - .send({ - data: { - title: 'foo', - panels: {}, - }, - }); - expect(response.status).to.be(400); - expect(response.body.statusCode).to.be(400); - expect(response.body.message).to.be( - '[request body.data.panels]: expected value of type [array] but got [Object]' - ); - }); - }); -} diff --git a/src/platform/test/api_integration/apis/index.ts b/src/platform/test/api_integration/apis/index.ts index 57a6661974b40..d5c39269f3349 100644 --- a/src/platform/test/api_integration/apis/index.ts +++ b/src/platform/test/api_integration/apis/index.ts @@ -14,7 +14,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./console')); loadTestFile(require.resolve('./core')); loadTestFile(require.resolve('./custom_integration')); - loadTestFile(require.resolve('./dashboards')); loadTestFile(require.resolve('./general')); loadTestFile(require.resolve('./home')); loadTestFile(require.resolve('./data_view_field_editor')); From 715e4ed05f0b3cd8321ed745fcf1234b1c38db7b Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Sat, 31 Jan 2026 13:41:52 +0200 Subject: [PATCH 04/23] Update TypeScript configuration to include Scout test files and add Scout reference --- src/platform/plugins/shared/dashboard/tsconfig.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/platform/plugins/shared/dashboard/tsconfig.json b/src/platform/plugins/shared/dashboard/tsconfig.json index 1e83168757552..16ecce7390526 100644 --- a/src/platform/plugins/shared/dashboard/tsconfig.json +++ b/src/platform/plugins/shared/dashboard/tsconfig.json @@ -3,7 +3,7 @@ "compilerOptions": { "outDir": "target/types" }, - "include": ["*.ts", ".storybook/**/*.ts", "common/**/*", "public/**/*", "server/**/*"], + "include": ["*.ts", ".storybook/**/*.ts", "common/**/*", "public/**/*", "server/**/*", "test/scout/**/*"], "kbn_references": [ "@kbn/core", "@kbn/inspector-plugin", @@ -99,7 +99,8 @@ "@kbn/cps", "@kbn/core-chrome-app-menu-components", "@kbn/core-chrome-app-menu", - "@kbn/test-jest-helpers" + "@kbn/test-jest-helpers", + "@kbn/scout" ], "exclude": ["target/**/*"] } From 9e1e6fa4349d0d05514b1e0609c8ae2257b03322 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Sat, 31 Jan 2026 12:04:55 +0000 Subject: [PATCH 05/23] Changes from node scripts/regenerate_moon_projects.js --update --- src/platform/plugins/shared/dashboard/moon.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/platform/plugins/shared/dashboard/moon.yml b/src/platform/plugins/shared/dashboard/moon.yml index b3bde5b339d7f..690539f6c3b0b 100644 --- a/src/platform/plugins/shared/dashboard/moon.yml +++ b/src/platform/plugins/shared/dashboard/moon.yml @@ -113,6 +113,7 @@ dependsOn: - '@kbn/core-chrome-app-menu-components' - '@kbn/core-chrome-app-menu' - '@kbn/test-jest-helpers' + - '@kbn/scout' tags: - plugin - prod @@ -126,6 +127,7 @@ fileGroups: - common/**/* - public/**/* - server/**/* + - test/scout/**/* - '!target/**/*' tasks: jest: From b980b2ca5fbeadcc6dca6c117319a6ac82970ddc Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Sat, 31 Jan 2026 15:43:41 +0200 Subject: [PATCH 06/23] Update tsconfig to include JSON files in Scout test directory --- src/platform/plugins/shared/dashboard/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/plugins/shared/dashboard/tsconfig.json b/src/platform/plugins/shared/dashboard/tsconfig.json index 16ecce7390526..86915b515792e 100644 --- a/src/platform/plugins/shared/dashboard/tsconfig.json +++ b/src/platform/plugins/shared/dashboard/tsconfig.json @@ -3,7 +3,7 @@ "compilerOptions": { "outDir": "target/types" }, - "include": ["*.ts", ".storybook/**/*.ts", "common/**/*", "public/**/*", "server/**/*", "test/scout/**/*"], + "include": ["*.ts", ".storybook/**/*.ts", "common/**/*", "public/**/*", "server/**/*", "test/scout/**/*", "test/scout/**/*.json"], "kbn_references": [ "@kbn/core", "@kbn/inspector-plugin", From 9bc29ec20dad8d2246633c02d5e583407e7976b7 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Sat, 31 Jan 2026 14:10:21 +0000 Subject: [PATCH 07/23] Changes from node scripts/regenerate_moon_projects.js --update --- src/platform/plugins/shared/dashboard/moon.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platform/plugins/shared/dashboard/moon.yml b/src/platform/plugins/shared/dashboard/moon.yml index 690539f6c3b0b..c37b531ff8647 100644 --- a/src/platform/plugins/shared/dashboard/moon.yml +++ b/src/platform/plugins/shared/dashboard/moon.yml @@ -128,6 +128,7 @@ fileGroups: - public/**/* - server/**/* - test/scout/**/* + - test/scout/**/*.json - '!target/**/*' tasks: jest: From a5b0886440da91a1ee17b5d355144e4e66938fef Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Sat, 31 Jan 2026 19:12:33 +0200 Subject: [PATCH 08/23] Use ESS_ONLY tag for tests using editor role because editor role doesn't exist in serverless --- .../dashboard/test/scout/api/tests/create_dashboard.spec.ts | 2 +- .../dashboard/test/scout/api/tests/delete_dashboard.spec.ts | 2 +- .../dashboard/test/scout/api/tests/update_dashboard.spec.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard.spec.ts index c051488bb5fc7..7b38264bfbd95 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard.spec.ts @@ -18,7 +18,7 @@ import { TEST_DASHBOARD_ID, } from '../fixtures'; -apiTest.describe('dashboards - create', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { +apiTest.describe('dashboards - create', { tag: tags.ESS_ONLY }, () => { let editorCredentials: RoleApiCredentials; apiTest.beforeAll(async ({ kbnClient, requestAuth }) => { diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/delete_dashboard.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/delete_dashboard.spec.ts index 186c7214083ec..7c1417df58348 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/api/tests/delete_dashboard.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/delete_dashboard.spec.ts @@ -18,7 +18,7 @@ import { TEST_DASHBOARD_ID, } from '../fixtures'; -apiTest.describe('dashboards - delete', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { +apiTest.describe('dashboards - delete', { tag: tags.ESS_ONLY }, () => { let editorCredentials: RoleApiCredentials; apiTest.beforeAll(async ({ kbnClient, requestAuth }) => { diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/update_dashboard.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/update_dashboard.spec.ts index cd5904c1fd1c1..5deb81109abf2 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/api/tests/update_dashboard.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/update_dashboard.spec.ts @@ -18,7 +18,7 @@ import { TEST_DASHBOARD_ID, } from '../fixtures'; -apiTest.describe('dashboards - update', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { +apiTest.describe('dashboards - update', { tag: tags.ESS_ONLY }, () => { let editorCredentials: RoleApiCredentials; apiTest.beforeAll(async ({ kbnClient, requestAuth }) => { From cc3a93d1efdbc23155742392653f2292c95868b9 Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Sat, 31 Jan 2026 20:32:31 +0200 Subject: [PATCH 09/23] Tag schema test as ESS_ONLY The OAS endpoint (/api/oas) is only enabled in stateful config (server.oas.enabled=true), not serverless. Test returns 404 on serverless deployments. --- .../test/scout/api/tests/create_dashboard_schema.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts index a2bc02e89a7a5..c6690a81c2b85 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts @@ -13,7 +13,7 @@ import { tags } from '@kbn/scout'; import { apiTest, DASHBOARD_API_PATH, KBN_ARCHIVES } from '../fixtures'; import snapshot from '../fixtures/schema_snapshot.json'; -apiTest.describe('dashboard REST schema', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { +apiTest.describe('dashboard REST schema', { tag: tags.ESS_ONLY }, () => { let viewerCredentials: RoleApiCredentials; apiTest.beforeAll(async ({ kbnClient, requestAuth }) => { From cd15d5ab630caefa6a01ee94c31d49e38dbb9157 Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Mon, 2 Feb 2026 11:53:33 +0200 Subject: [PATCH 10/23] Enable OAS endpoint in Scout serverless config --- .../configs/default/serverless/serverless.base.config.ts | 2 ++ .../test/scout/api/tests/create_dashboard_schema.spec.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/platform/packages/shared/kbn-scout/src/servers/configs/default/serverless/serverless.base.config.ts b/src/platform/packages/shared/kbn-scout/src/servers/configs/default/serverless/serverless.base.config.ts index adb78ca011a2c..ccaee3ff0e727 100644 --- a/src/platform/packages/shared/kbn-scout/src/servers/configs/default/serverless/serverless.base.config.ts +++ b/src/platform/packages/shared/kbn-scout/src/servers/configs/default/serverless/serverless.base.config.ts @@ -102,6 +102,8 @@ export const defaultConfig: ScoutServerConfig = { sourceArgs: ['--no-base-path', '--env.name=development'], serverArgs: [ `--server.restrictInternalApis=true`, + // Enable OpenAPI specification endpoint for schema validation tests + '--server.oas.enabled=true', `--server.port=${servers.kibana.port}`, '--status.allowAnonymous=true', `--migrations.zdt.runOnRoles=${JSON.stringify(['ui'])}`, diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts index c6690a81c2b85..a2bc02e89a7a5 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts @@ -13,7 +13,7 @@ import { tags } from '@kbn/scout'; import { apiTest, DASHBOARD_API_PATH, KBN_ARCHIVES } from '../fixtures'; import snapshot from '../fixtures/schema_snapshot.json'; -apiTest.describe('dashboard REST schema', { tag: tags.ESS_ONLY }, () => { +apiTest.describe('dashboard REST schema', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { let viewerCredentials: RoleApiCredentials; apiTest.beforeAll(async ({ kbnClient, requestAuth }) => { From f092e529d51f6a321d3d75394b6765847faf4e31 Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Mon, 2 Feb 2026 14:47:27 +0200 Subject: [PATCH 11/23] Address feedback --- .../test/scout/api/tests/create_dashboard.spec.ts | 2 -- .../scout/api/tests/create_dashboard_schema.spec.ts | 10 ++-------- .../test/scout/api/tests/delete_dashboard.spec.ts | 1 - .../test/scout/api/tests/search_dashboards.spec.ts | 2 +- .../test/scout/api/tests/update_dashboard.spec.ts | 3 --- 5 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard.spec.ts index 7b38264bfbd95..a7a75a90550bb 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard.spec.ts @@ -133,7 +133,6 @@ apiTest.describe('dashboards - create', { tag: tags.ESS_ONLY }, () => { }); expect(response).toHaveStatusCode(400); - expect(response.body.statusCode).toBe(400); expect(response.body.message).toBe( '[request body.data.title]: expected value of type [string] but got [undefined]' ); @@ -155,7 +154,6 @@ apiTest.describe('dashboards - create', { tag: tags.ESS_ONLY }, () => { }); expect(response).toHaveStatusCode(400); - expect(response.body.statusCode).toBe(400); expect(response.body.message).toBe( '[request body.data.panels]: expected value of type [array] but got [Object]' ); diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts index a2bc02e89a7a5..909cc31daa169 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts @@ -10,20 +10,14 @@ import type { RoleApiCredentials } from '@kbn/scout'; import { expect } from '@kbn/scout/api'; import { tags } from '@kbn/scout'; -import { apiTest, DASHBOARD_API_PATH, KBN_ARCHIVES } from '../fixtures'; +import { apiTest, DASHBOARD_API_PATH } from '../fixtures'; import snapshot from '../fixtures/schema_snapshot.json'; apiTest.describe('dashboard REST schema', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { let viewerCredentials: RoleApiCredentials; - apiTest.beforeAll(async ({ kbnClient, requestAuth }) => { + apiTest.beforeAll(async ({ requestAuth }) => { viewerCredentials = await requestAuth.getApiKey('viewer'); - await kbnClient.importExport.load(KBN_ARCHIVES.BASIC); - await kbnClient.importExport.load(KBN_ARCHIVES.TAGS); - }); - - apiTest.afterAll(async ({ kbnClient }) => { - await kbnClient.savedObjects.cleanStandardList(); }); /** diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/delete_dashboard.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/delete_dashboard.spec.ts index 7c1417df58348..4f7643c6c917b 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/api/tests/delete_dashboard.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/delete_dashboard.spec.ts @@ -39,7 +39,6 @@ apiTest.describe('dashboards - delete', { tag: tags.ESS_ONLY }, () => { responseType: 'json', }); - expect(response).toHaveStatusCode(404); expect(response.body).toStrictEqual({ statusCode: 404, error: 'Not Found', diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/search_dashboards.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/search_dashboards.spec.ts index 1d92d95d51123..9e8711c923639 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/api/tests/search_dashboards.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/search_dashboards.spec.ts @@ -38,8 +38,8 @@ apiTest.describe('dashboards - search', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => expect(response).toHaveStatusCode(200); expect(response.body.total).toBe(100); - expect(response.body.dashboards[0].id).toBe('test-dashboard-00'); expect(response.body.dashboards).toHaveLength(20); + expect(response.body.dashboards[0].id).toBe('test-dashboard-00'); }); apiTest('should narrow results by search', async ({ apiClient }) => { diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/update_dashboard.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/update_dashboard.spec.ts index 5deb81109abf2..0ab7609ffcd59 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/api/tests/update_dashboard.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/update_dashboard.spec.ts @@ -64,7 +64,6 @@ apiTest.describe('dashboards - update', { tag: tags.ESS_ONLY }, () => { responseType: 'json', }); - expect(response).toHaveStatusCode(404); expect(response.body).toStrictEqual({ statusCode: 404, error: 'Not Found', @@ -85,7 +84,6 @@ apiTest.describe('dashboards - update', { tag: tags.ESS_ONLY }, () => { }); expect(response).toHaveStatusCode(400); - expect(response.body.statusCode).toBe(400); expect(response.body.message).toBe( '[request body.data.title]: expected value of type [string] but got [undefined]' ); @@ -107,7 +105,6 @@ apiTest.describe('dashboards - update', { tag: tags.ESS_ONLY }, () => { }); expect(response).toHaveStatusCode(400); - expect(response.body.statusCode).toBe(400); expect(response.body.message).toBe( '[request body.data.panels]: expected value of type [array] but got [Object]' ); From bbd4092388544aa1639cb3da6db94be8ad620716 Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Mon, 2 Feb 2026 14:56:50 +0200 Subject: [PATCH 12/23] Add validation for response body in dashboard REST schema tests --- .../test/scout/api/tests/create_dashboard_schema.spec.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts index 909cc31daa169..492b248a7fc8e 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts @@ -46,6 +46,7 @@ apiTest.describe('dashboard REST schema', { tag: tags.DEPLOYMENT_AGNOSTIC }, () ); expect(response.statusCode).toBe(200); + expect(response.body.paths?.[oasPath]).toBeDefined(); const createBodySchema = response.body.paths[oasPath].post.requestBody.content[ @@ -55,8 +56,9 @@ apiTest.describe('dashboard REST schema', { tag: tags.DEPLOYMENT_AGNOSTIC }, () const panelSchema = panelsSchema.items.anyOf.find( (schema: { properties: Record }) => 'config' in schema.properties ); - const configSchema = panelSchema.properties.config; + expect(panelSchema).toBeDefined(); + const configSchema = panelSchema.properties.config; expect(configSchema.anyOf).toHaveLength(2); expect(configSchema.anyOf).toStrictEqual(snapshot); }); From 7fec875a1be7d9b0142fcc963c1f2181998fd98d Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Tue, 3 Feb 2026 14:55:06 +0200 Subject: [PATCH 13/23] Move Dashboard OAS schema tests to custom server config --- .../serverless/es.serverless.config.ts | 33 +++++++++++++++++ .../serverless/oblt.serverless.config.ts | 33 +++++++++++++++++ .../serverless/security.serverless.config.ts | 33 +++++++++++++++++ .../oas_schema/stateful/stateful.config.ts | 33 +++++++++++++++++ .../serverless/serverless.base.config.ts | 2 - .../configs/default/stateful/base.config.ts | 2 - .../dashboard/test/scout_oas_schema/README.md | 37 +++++++++++++++++++ .../scout_oas_schema/api/fixtures/index.ts | 16 ++++++++ .../api/fixtures/schema_snapshot.json | 0 .../api/parallel.playwright.config.ts | 23 ++++++++++++ .../api/parallel_tests/schema.spec.ts} | 9 +++++ 11 files changed, 217 insertions(+), 4 deletions(-) create mode 100644 src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/serverless/es.serverless.config.ts create mode 100644 src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/serverless/oblt.serverless.config.ts create mode 100644 src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/serverless/security.serverless.config.ts create mode 100644 src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/stateful/stateful.config.ts create mode 100644 src/platform/plugins/shared/dashboard/test/scout_oas_schema/README.md create mode 100644 src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/fixtures/index.ts rename src/platform/plugins/shared/dashboard/test/{scout => scout_oas_schema}/api/fixtures/schema_snapshot.json (100%) create mode 100644 src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel.playwright.config.ts rename src/platform/plugins/shared/dashboard/test/{scout/api/tests/create_dashboard_schema.spec.ts => scout_oas_schema/api/parallel_tests/schema.spec.ts} (89%) diff --git a/src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/serverless/es.serverless.config.ts b/src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/serverless/es.serverless.config.ts new file mode 100644 index 0000000000000..305a94fbf3cc6 --- /dev/null +++ b/src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/serverless/es.serverless.config.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { servers as defaultConfig } from '../../../default/serverless/es.serverless.config'; +import type { ScoutServerConfig } from '../../../../../types'; + +/** + * Custom Scout server configuration for OAS (OpenAPI Specification) schema validation tests. + * Enables the OAS endpoint which is required for schema validation. + * + * This config is automatically used when running tests from: + * dashboard/test/scout_oas_schema/ + * + * Usage: + * node scripts/scout.js start-server --serverless=es --config-dir oas_schema + */ +export const servers: ScoutServerConfig = { + ...defaultConfig, + kbnTestServer: { + ...defaultConfig.kbnTestServer, + serverArgs: [ + ...defaultConfig.kbnTestServer.serverArgs, + // Enable OpenAPI specification endpoint for schema validation tests + '--server.oas.enabled=true', + ], + }, +}; diff --git a/src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/serverless/oblt.serverless.config.ts b/src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/serverless/oblt.serverless.config.ts new file mode 100644 index 0000000000000..884a99f305e52 --- /dev/null +++ b/src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/serverless/oblt.serverless.config.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { servers as defaultConfig } from '../../../default/serverless/oblt.serverless.config'; +import type { ScoutServerConfig } from '../../../../../types'; + +/** + * Custom Scout server configuration for OAS (OpenAPI Specification) schema validation tests. + * Enables the OAS endpoint which is required for schema validation. + * + * This config is automatically used when running tests from: + * dashboard/test/scout_oas_schema/ + * + * Usage: + * node scripts/scout.js start-server --serverless=oblt --config-dir oas_schema + */ +export const servers: ScoutServerConfig = { + ...defaultConfig, + kbnTestServer: { + ...defaultConfig.kbnTestServer, + serverArgs: [ + ...defaultConfig.kbnTestServer.serverArgs, + // Enable OpenAPI specification endpoint for schema validation tests + '--server.oas.enabled=true', + ], + }, +}; diff --git a/src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/serverless/security.serverless.config.ts b/src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/serverless/security.serverless.config.ts new file mode 100644 index 0000000000000..2b1aad686ff12 --- /dev/null +++ b/src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/serverless/security.serverless.config.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { servers as defaultConfig } from '../../../default/serverless/security.serverless.config'; +import type { ScoutServerConfig } from '../../../../../types'; + +/** + * Custom Scout server configuration for OAS (OpenAPI Specification) schema validation tests. + * Enables the OAS endpoint which is required for schema validation. + * + * This config is automatically used when running tests from: + * dashboard/test/scout_oas_schema/ + * + * Usage: + * node scripts/scout.js start-server --serverless=security --config-dir oas_schema + */ +export const servers: ScoutServerConfig = { + ...defaultConfig, + kbnTestServer: { + ...defaultConfig.kbnTestServer, + serverArgs: [ + ...defaultConfig.kbnTestServer.serverArgs, + // Enable OpenAPI specification endpoint for schema validation tests + '--server.oas.enabled=true', + ], + }, +}; diff --git a/src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/stateful/stateful.config.ts b/src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/stateful/stateful.config.ts new file mode 100644 index 0000000000000..aa1bc0e051b14 --- /dev/null +++ b/src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/stateful/stateful.config.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { ScoutServerConfig } from '../../../../../types'; +import { defaultConfig } from '../../../default/stateful/base.config'; + +/** + * Custom Scout server configuration for OAS (OpenAPI Specification) schema validation tests. + * Enables the OAS endpoint which is required for schema validation. + * + * This config is automatically used when running tests from: + * dashboard/test/scout_oas_schema/ + * + * Usage: + * node scripts/scout.js start-server --stateful --config-dir oas_schema + */ +export const servers: ScoutServerConfig = { + ...defaultConfig, + kbnTestServer: { + ...defaultConfig.kbnTestServer, + serverArgs: [ + ...defaultConfig.kbnTestServer.serverArgs, + // Enable OpenAPI specification endpoint for schema validation tests + '--server.oas.enabled=true', + ], + }, +}; diff --git a/src/platform/packages/shared/kbn-scout/src/servers/configs/default/serverless/serverless.base.config.ts b/src/platform/packages/shared/kbn-scout/src/servers/configs/default/serverless/serverless.base.config.ts index ccaee3ff0e727..adb78ca011a2c 100644 --- a/src/platform/packages/shared/kbn-scout/src/servers/configs/default/serverless/serverless.base.config.ts +++ b/src/platform/packages/shared/kbn-scout/src/servers/configs/default/serverless/serverless.base.config.ts @@ -102,8 +102,6 @@ export const defaultConfig: ScoutServerConfig = { sourceArgs: ['--no-base-path', '--env.name=development'], serverArgs: [ `--server.restrictInternalApis=true`, - // Enable OpenAPI specification endpoint for schema validation tests - '--server.oas.enabled=true', `--server.port=${servers.kibana.port}`, '--status.allowAnonymous=true', `--migrations.zdt.runOnRoles=${JSON.stringify(['ui'])}`, diff --git a/src/platform/packages/shared/kbn-scout/src/servers/configs/default/stateful/base.config.ts b/src/platform/packages/shared/kbn-scout/src/servers/configs/default/stateful/base.config.ts index 57be897254e6d..2c900a1e42b8a 100644 --- a/src/platform/packages/shared/kbn-scout/src/servers/configs/default/stateful/base.config.ts +++ b/src/platform/packages/shared/kbn-scout/src/servers/configs/default/stateful/base.config.ts @@ -170,8 +170,6 @@ export const defaultConfig: ScoutServerConfig = { '--savedObjects.allowHttpApiAccess=false', // override default to not allow hiddenFromHttpApis saved objects access to the http APIs see https://github.com/elastic/dev/issues/2200 // explicitly disable internal API restriction. See https://github.com/elastic/kibana/issues/163654 '--server.restrictInternalApis=false', - // Enable OpenAPI specification endpoint for schema validation tests - '--server.oas.enabled=true', // disable fleet task that writes to metrics.fleet_server.* data streams, impacting functional tests `--xpack.task_manager.unsafe.exclude_task_types=${JSON.stringify(['Fleet-Metrics-Task'])}`, // x-pack/platform/test/api_integration/config.ts diff --git a/src/platform/plugins/shared/dashboard/test/scout_oas_schema/README.md b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/README.md new file mode 100644 index 0000000000000..581802b896764 --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/README.md @@ -0,0 +1,37 @@ +## Dashboard OAS Schema Validation Tests + +This directory contains Scout tests for validating the Dashboard REST API OpenAPI (OAS) schema. + +These tests use a **custom server configuration** that enables the OAS endpoint (`--server.oas.enabled=true`). + +### How to run tests + +First start the servers with the custom config: + +```bash +// ESS (stateful) +node scripts/scout.js start-server --stateful --config-dir oas_schema + +// Serverless +node scripts/scout.js start-server --serverless=es --config-dir oas_schema +``` + +Then run the tests in another terminal: + +```bash +// ESS (stateful) +npx playwright test --config=src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel.playwright.config.ts --grep=@ess --project=local + +// Serverless +npx playwright test --config=src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel.playwright.config.ts --grep=@svlSearch --project=local +``` + +### Server Configuration + +The custom server config is located at: +`src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/` + +It extends the default config and adds: +``` +--server.oas.enabled=true +``` diff --git a/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/fixtures/index.ts b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/fixtures/index.ts new file mode 100644 index 0000000000000..2744113c17a85 --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/fixtures/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { ScoutTestFixtures, ScoutWorkerFixtures } from '@kbn/scout'; +import { apiTest as baseApiTest } from '@kbn/scout'; + +export const apiTest = baseApiTest.extend({}); + +/** The base API path for dashboard endpoints (no leading slash for apiClient). */ +export const DASHBOARD_API_PATH = 'api/dashboards'; diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/schema_snapshot.json b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/fixtures/schema_snapshot.json similarity index 100% rename from src/platform/plugins/shared/dashboard/test/scout/api/fixtures/schema_snapshot.json rename to src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/fixtures/schema_snapshot.json diff --git a/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel.playwright.config.ts b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel.playwright.config.ts new file mode 100644 index 0000000000000..aebfeb510af49 --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel.playwright.config.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { createPlaywrightConfig } from '@kbn/scout'; + +/** + * Playwright config for OAS schema validation tests. + * + * These tests use a custom server configuration that enables the OAS endpoint. + * The custom config is located at: + * src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/ + * + * See README.md for usage instructions. + */ +export default createPlaywrightConfig({ + testDir: './parallel_tests', +}); diff --git a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel_tests/schema.spec.ts similarity index 89% rename from src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts rename to src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel_tests/schema.spec.ts index 492b248a7fc8e..bc13afe0dde56 100644 --- a/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard_schema.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel_tests/schema.spec.ts @@ -13,6 +13,15 @@ import { tags } from '@kbn/scout'; import { apiTest, DASHBOARD_API_PATH } from '../fixtures'; import snapshot from '../fixtures/schema_snapshot.json'; +/** + * Dashboard REST schema validation tests. + * + * These tests require the OAS (OpenAPI Specification) endpoint to be enabled, + * which is configured in the custom server config at: + * src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/ + * + * See README.md for usage instructions. + */ apiTest.describe('dashboard REST schema', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { let viewerCredentials: RoleApiCredentials; From 4d560ef7645df3e69d08881c683bac1999a92fac Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Tue, 3 Feb 2026 17:20:14 +0200 Subject: [PATCH 14/23] hotfix --- src/platform/plugins/shared/dashboard/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/plugins/shared/dashboard/tsconfig.json b/src/platform/plugins/shared/dashboard/tsconfig.json index 86915b515792e..75ddaf972164e 100644 --- a/src/platform/plugins/shared/dashboard/tsconfig.json +++ b/src/platform/plugins/shared/dashboard/tsconfig.json @@ -3,7 +3,7 @@ "compilerOptions": { "outDir": "target/types" }, - "include": ["*.ts", ".storybook/**/*.ts", "common/**/*", "public/**/*", "server/**/*", "test/scout/**/*", "test/scout/**/*.json"], + "include": ["*.ts", ".storybook/**/*.ts", "common/**/*", "public/**/*", "server/**/*", "test/scout/**/*", "test/scout/**/*.json", "test/scout_oas_schema/**/*"], "kbn_references": [ "@kbn/core", "@kbn/inspector-plugin", From 2173b54550c5a7f85e51f713f6c0ae68c74f04ba Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 3 Feb 2026 15:50:19 +0000 Subject: [PATCH 15/23] Changes from node scripts/regenerate_moon_projects.js --update --- src/platform/plugins/shared/dashboard/moon.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platform/plugins/shared/dashboard/moon.yml b/src/platform/plugins/shared/dashboard/moon.yml index c37b531ff8647..be07cd3a49371 100644 --- a/src/platform/plugins/shared/dashboard/moon.yml +++ b/src/platform/plugins/shared/dashboard/moon.yml @@ -129,6 +129,7 @@ fileGroups: - server/**/* - test/scout/**/* - test/scout/**/*.json + - test/scout_oas_schema/**/* - '!target/**/*' tasks: jest: From 7138b5827e48216aca51326f4a421b358e331cd6 Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Wed, 4 Feb 2026 12:19:51 +0200 Subject: [PATCH 16/23] hotfix --- src/platform/plugins/shared/dashboard/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/plugins/shared/dashboard/tsconfig.json b/src/platform/plugins/shared/dashboard/tsconfig.json index 75ddaf972164e..0cd4a51a04386 100644 --- a/src/platform/plugins/shared/dashboard/tsconfig.json +++ b/src/platform/plugins/shared/dashboard/tsconfig.json @@ -3,7 +3,7 @@ "compilerOptions": { "outDir": "target/types" }, - "include": ["*.ts", ".storybook/**/*.ts", "common/**/*", "public/**/*", "server/**/*", "test/scout/**/*", "test/scout/**/*.json", "test/scout_oas_schema/**/*"], + "include": ["*.ts", ".storybook/**/*.ts", "common/**/*", "public/**/*", "server/**/*", "test/scout/**/*", "test/scout/**/*.json", "test/scout_oas_schema/**/*", "test/scout_oas_schema/**/*.json"], "kbn_references": [ "@kbn/core", "@kbn/inspector-plugin", From e11cee1a23774380671153bdc6b829a24968e2d1 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 4 Feb 2026 10:48:32 +0000 Subject: [PATCH 17/23] Changes from node scripts/regenerate_moon_projects.js --update --- src/platform/plugins/shared/dashboard/moon.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platform/plugins/shared/dashboard/moon.yml b/src/platform/plugins/shared/dashboard/moon.yml index be07cd3a49371..71d471c6e6b94 100644 --- a/src/platform/plugins/shared/dashboard/moon.yml +++ b/src/platform/plugins/shared/dashboard/moon.yml @@ -130,6 +130,7 @@ fileGroups: - test/scout/**/* - test/scout/**/*.json - test/scout_oas_schema/**/* + - test/scout_oas_schema/**/*.json - '!target/**/*' tasks: jest: From c8572591935713fb11cadc840667e4eb4799bfcf Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Wed, 4 Feb 2026 15:55:35 +0200 Subject: [PATCH 18/23] Remove parallel api tests --- .../plugins/shared/dashboard/test/scout_oas_schema/README.md | 5 +++-- .../{parallel.playwright.config.ts => playwright.config.ts} | 2 +- .../api/{parallel_tests => tests}/schema.spec.ts | 0 3 files changed, 4 insertions(+), 3 deletions(-) rename src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/{parallel.playwright.config.ts => playwright.config.ts} (96%) rename src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/{parallel_tests => tests}/schema.spec.ts (100%) diff --git a/src/platform/plugins/shared/dashboard/test/scout_oas_schema/README.md b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/README.md index 581802b896764..18715fd0bfee7 100644 --- a/src/platform/plugins/shared/dashboard/test/scout_oas_schema/README.md +++ b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/README.md @@ -20,10 +20,10 @@ Then run the tests in another terminal: ```bash // ESS (stateful) -npx playwright test --config=src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel.playwright.config.ts --grep=@ess --project=local +npx playwright test --config=src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/playwright.config.ts --grep=@ess --project=local // Serverless -npx playwright test --config=src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel.playwright.config.ts --grep=@svlSearch --project=local +npx playwright test --config=src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/playwright.config.ts --grep=@svlSearch --project=local ``` ### Server Configuration @@ -32,6 +32,7 @@ The custom server config is located at: `src/platform/packages/shared/kbn-scout/src/servers/configs/custom/oas_schema/` It extends the default config and adds: + ``` --server.oas.enabled=true ``` diff --git a/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel.playwright.config.ts b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/playwright.config.ts similarity index 96% rename from src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel.playwright.config.ts rename to src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/playwright.config.ts index aebfeb510af49..5175ba4c743f0 100644 --- a/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel.playwright.config.ts +++ b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/playwright.config.ts @@ -19,5 +19,5 @@ import { createPlaywrightConfig } from '@kbn/scout'; * See README.md for usage instructions. */ export default createPlaywrightConfig({ - testDir: './parallel_tests', + testDir: './tests', }); diff --git a/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel_tests/schema.spec.ts b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/tests/schema.spec.ts similarity index 100% rename from src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/parallel_tests/schema.spec.ts rename to src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/tests/schema.spec.ts From a8fb2ae35ec0e5837cdc71ca4ec9baf22fe356e8 Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Wed, 4 Feb 2026 18:26:28 +0200 Subject: [PATCH 19/23] Add missing comma --- src/platform/plugins/shared/dashboard/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/plugins/shared/dashboard/tsconfig.json b/src/platform/plugins/shared/dashboard/tsconfig.json index 4b46eaecafb3d..2497e520b09c3 100644 --- a/src/platform/plugins/shared/dashboard/tsconfig.json +++ b/src/platform/plugins/shared/dashboard/tsconfig.json @@ -100,7 +100,7 @@ "@kbn/core-chrome-app-menu-components", "@kbn/core-chrome-app-menu", "@kbn/test-jest-helpers", - "@kbn/scout" + "@kbn/scout", "@kbn/image-embeddable-plugin", ], "exclude": ["target/**/*"] From dd4a406db2e4cb51672789edf37d9530b75cf136 Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Wed, 4 Feb 2026 19:17:17 +0200 Subject: [PATCH 20/23] Remove final comma that caused 1 test to fail among 25 others in Flaky Test Runner --- src/platform/plugins/shared/dashboard/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/plugins/shared/dashboard/tsconfig.json b/src/platform/plugins/shared/dashboard/tsconfig.json index 2497e520b09c3..d1ee1194720cf 100644 --- a/src/platform/plugins/shared/dashboard/tsconfig.json +++ b/src/platform/plugins/shared/dashboard/tsconfig.json @@ -101,7 +101,7 @@ "@kbn/core-chrome-app-menu", "@kbn/test-jest-helpers", "@kbn/scout", - "@kbn/image-embeddable-plugin", + "@kbn/image-embeddable-plugin" ], "exclude": ["target/**/*"] } From aff266ae80b6577422409dbb8b1a17a2d5912c8d Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Fri, 6 Feb 2026 09:00:19 +0200 Subject: [PATCH 21/23] Small fix after merging main --- src/platform/plugins/shared/dashboard/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/plugins/shared/dashboard/tsconfig.json b/src/platform/plugins/shared/dashboard/tsconfig.json index 1da0b506cf90e..672f4b3ea3baa 100644 --- a/src/platform/plugins/shared/dashboard/tsconfig.json +++ b/src/platform/plugins/shared/dashboard/tsconfig.json @@ -3,7 +3,7 @@ "compilerOptions": { "outDir": "target/types" }, - "include": ["*.ts", ".storybook/**/*.ts", "common/**/*", "public/**/*", "server/**/*", "test/scout/**/*", "test/scout/**/*.json", "test/scout_oas_schema/**/*", "test/scout_oas_schema/**/*.json"], + "include": ["*.ts", ".storybook/**/*.ts", "common/**/*", "public/**/*", "server/**/*", "test/scout/**/*", "test/scout_oas_schema/**/*", "test/scout_oas_schema/**/*.json"], "kbn_references": [ "@kbn/core", "@kbn/inspector-plugin", From 24c17ebd4fa18465955ee3b7e0652580a3763d4f Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 6 Feb 2026 07:30:08 +0000 Subject: [PATCH 22/23] Changes from node scripts/regenerate_moon_projects.js --update --- src/platform/plugins/shared/dashboard/moon.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/platform/plugins/shared/dashboard/moon.yml b/src/platform/plugins/shared/dashboard/moon.yml index 0d5e106950acd..1dd772c09c2b3 100644 --- a/src/platform/plugins/shared/dashboard/moon.yml +++ b/src/platform/plugins/shared/dashboard/moon.yml @@ -131,7 +131,6 @@ fileGroups: - public/**/* - server/**/* - test/scout/**/* - - test/scout/**/*.json - test/scout_oas_schema/**/* - test/scout_oas_schema/**/*.json - '!target/**/*' From 4f37808fa77aba19f5b0fe0f95fc56bd2914564c Mon Sep 17 00:00:00 2001 From: Stelios Mavro Date: Fri, 6 Feb 2026 13:41:52 +0200 Subject: [PATCH 23/23] Enhanced oas schema validation with extra assertion --- .../dashboard/test/scout_oas_schema/api/tests/schema.spec.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/tests/schema.spec.ts b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/tests/schema.spec.ts index bc13afe0dde56..a216f6a292543 100644 --- a/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/tests/schema.spec.ts +++ b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/tests/schema.spec.ts @@ -62,6 +62,9 @@ apiTest.describe('dashboard REST schema', { tag: tags.DEPLOYMENT_AGNOSTIC }, () 'application/json; Elastic-Api-Version=1' ].schema; const panelsSchema = createBodySchema.properties.data.properties.panels; + expect(panelsSchema).toBeDefined(); + expect(panelsSchema.items?.anyOf?.length).toBeGreaterThan(0); + const panelSchema = panelsSchema.items.anyOf.find( (schema: { properties: Record }) => 'config' in schema.properties );