diff --git a/.buildkite/scout_ci_config.yml b/.buildkite/scout_ci_config.yml index d2b11bfd28809..51dcd7a4694bb 100644 --- a/.buildkite/scout_ci_config.yml +++ b/.buildkite/scout_ci_config.yml @@ -3,6 +3,7 @@ plugins: enabled: - apm - console + - dashboard - cloud_security_posture - discover_enhanced - entity_store diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9ee12479c2805..67839100d8bbc 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1847,7 +1847,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/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/plugins/shared/dashboard/moon.yml b/src/platform/plugins/shared/dashboard/moon.yml index 8ce3c66962da0..1dd772c09c2b3 100644 --- a/src/platform/plugins/shared/dashboard/moon.yml +++ b/src/platform/plugins/shared/dashboard/moon.yml @@ -115,6 +115,7 @@ dependsOn: - '@kbn/core-chrome-app-menu-components' - '@kbn/core-chrome-app-menu' - '@kbn/test-jest-helpers' + - '@kbn/scout' - '@kbn/image-embeddable-plugin' tags: - plugin @@ -130,6 +131,8 @@ fileGroups: - public/**/* - server/**/* - test/scout/**/* + - test/scout_oas_schema/**/* + - test/scout_oas_schema/**/*.json - '!target/**/*' tasks: jest: 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..106f3181d5906 --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/constants.ts @@ -0,0 +1,29 @@ +/* + * 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". + */ + +/** 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', + '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/test/api_integration/apis/dashboards/index.ts b/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/index.ts similarity index 50% rename from src/platform/test/api_integration/apis/dashboards/index.ts rename to src/platform/plugins/shared/dashboard/test/scout/api/fixtures/index.ts index 826991a611752..358d1df816071 100644 --- a/src/platform/test/api_integration/apis/dashboards/index.ts +++ b/src/platform/plugins/shared/dashboard/test/scout/api/fixtures/index.ts @@ -7,14 +7,9 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import type { FtrProviderContext } from '../../ftr_provider_context'; +import type { ScoutTestFixtures, ScoutWorkerFixtures } from '@kbn/scout'; +import { apiTest as baseApiTest } from '@kbn/scout'; -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')); - }); -} +export const apiTest = baseApiTest.extend({}); + +export { COMMON_HEADERS, DASHBOARD_API_PATH, KBN_ARCHIVES, TEST_DASHBOARD_ID } 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/create_dashboard.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard.spec.ts new file mode 100644 index 0000000000000..a7a75a90550bb --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/create_dashboard.spec.ts @@ -0,0 +1,161 @@ +/* + * 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.ESS_ONLY }, () => { + 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.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.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/delete_dashboard.spec.ts b/src/platform/plugins/shared/dashboard/test/scout/api/tests/delete_dashboard.spec.ts new file mode 100644 index 0000000000000..4f7643c6c917b --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/delete_dashboard.spec.ts @@ -0,0 +1,60 @@ +/* + * 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.ESS_ONLY }, () => { + 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.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/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..9e8711c923639 --- /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).toHaveLength(20); + expect(response.body.dashboards[0].id).toBe('test-dashboard-00'); + }); + + 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..0ab7609ffcd59 --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout/api/tests/update_dashboard.spec.ts @@ -0,0 +1,112 @@ +/* + * 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.ESS_ONLY }, () => { + 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.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.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.message).toBe( + '[request body.data.panels]: expected value of type [array] but got [Object]' + ); + }); +}); 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..18715fd0bfee7 --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/README.md @@ -0,0 +1,38 @@ +## 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/playwright.config.ts --grep=@ess --project=local + +// Serverless +npx playwright test --config=src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/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/test/api_integration/apis/dashboards/create_dashboard/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/test/api_integration/apis/dashboards/create_dashboard/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/playwright.config.ts b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/playwright.config.ts new file mode 100644 index 0000000000000..5175ba4c743f0 --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/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: './tests', +}); 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 new file mode 100644 index 0000000000000..a216f6a292543 --- /dev/null +++ b/src/platform/plugins/shared/dashboard/test/scout_oas_schema/api/tests/schema.spec.ts @@ -0,0 +1,77 @@ +/* + * 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 } 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; + + apiTest.beforeAll(async ({ requestAuth }) => { + viewerCredentials = await requestAuth.getApiKey('viewer'); + }); + + /** + * 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); + expect(response.body.paths?.[oasPath]).toBeDefined(); + + const createBodySchema = + response.body.paths[oasPath].post.requestBody.content[ + '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 + ); + expect(panelSchema).toBeDefined(); + + const configSchema = panelSchema.properties.config; + expect(configSchema.anyOf).toHaveLength(2); + expect(configSchema.anyOf).toStrictEqual(snapshot); + }); +}); diff --git a/src/platform/plugins/shared/dashboard/tsconfig.json b/src/platform/plugins/shared/dashboard/tsconfig.json index 4996e1072fa2f..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/**/*"], + "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", @@ -102,7 +102,8 @@ "@kbn/core-chrome-app-menu-components", "@kbn/core-chrome-app-menu", "@kbn/test-jest-helpers", - "@kbn/image-embeddable-plugin", + "@kbn/scout", + "@kbn/image-embeddable-plugin" ], "exclude": ["target/**/*"] } 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/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/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'));