[9.0] [scout] add 'apiServices' fixture to group Kibana API helpers (#214470) (#215123)

# Backport

This will backport the following commits from `main` to `9.0`:
- [[scout] add 'apiServices' fixture to group Kibana API helpers
(#214470)](https://github.com/elastic/kibana/pull/214470)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Dzmitry
Lemechko","email":"dzmitry.lemechko@elastic.co"},"sourceCommit":{"committedDate":"2025-03-18T11:34:25Z","message":"[scout]
add 'apiServices' fixture to group Kibana API helpers (#214470)\n\n##
Summary\n\nWe decided to group `Kibana API helpers` under a single
fixture:\n`apiServices` instead of individual fixtures. It should
simplify the\nsearch of existing helpers and reduce a risk for Teams to
create the\nsame helper like we see today with FTR.\nAdding just
`apiServices` in test context and adding dot will expand a\nlist of all
available API helpers + it can be extended for individual\nsolution
(e.g. @kbn/scout-oblt) and directly in plugin (if there is no\nchance to
re-use it in other plugins)\n\n<img width=\"699\"
alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/34a76659-04af-48c4-ab69-abda0c950206\"\n/>\n\n\nBefore:\n\n```\ntest('should
create something', async ({\n fleetApi,\n onboardingApi,\n
alertingApi,\n }) => {\n await
fleetApi.integration.install(integrationName);\n await
onboardingApi.updateInstallationStepStatus(\n onboardingId,\n
'ea-download',\n 'complete'\n );\n await
alertingApi.waitForAlert(alertId);\n```\n\nAfter:\n\n```\ntest('should
create something', async ({\n apiServices,\n }) => {\n await
apiServices.fleet.integration.install(integrationName);\n await
apiServices.onboarding.updateInstallationStepStatus(\n onboardingId,\n
'ea-download',\n 'complete'\n );\n await
apiServices.alerting.waitForAlert(alertId);\n```","sha":"48cd2075f75386b515e19567095c03a8ca73fe20","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","backport:version","test:scout","v9.1.0","v8.19.0"],"title":"[scout]
add 'apiServices' fixture to group Kibana API
helpers","number":214470,"url":"https://github.com/elastic/kibana/pull/214470","mergeCommit":{"message":"[scout]
add 'apiServices' fixture to group Kibana API helpers (#214470)\n\n##
Summary\n\nWe decided to group `Kibana API helpers` under a single
fixture:\n`apiServices` instead of individual fixtures. It should
simplify the\nsearch of existing helpers and reduce a risk for Teams to
create the\nsame helper like we see today with FTR.\nAdding just
`apiServices` in test context and adding dot will expand a\nlist of all
available API helpers + it can be extended for individual\nsolution
(e.g. @kbn/scout-oblt) and directly in plugin (if there is no\nchance to
re-use it in other plugins)\n\n<img width=\"699\"
alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/34a76659-04af-48c4-ab69-abda0c950206\"\n/>\n\n\nBefore:\n\n```\ntest('should
create something', async ({\n fleetApi,\n onboardingApi,\n
alertingApi,\n }) => {\n await
fleetApi.integration.install(integrationName);\n await
onboardingApi.updateInstallationStepStatus(\n onboardingId,\n
'ea-download',\n 'complete'\n );\n await
alertingApi.waitForAlert(alertId);\n```\n\nAfter:\n\n```\ntest('should
create something', async ({\n apiServices,\n }) => {\n await
apiServices.fleet.integration.install(integrationName);\n await
apiServices.onboarding.updateInstallationStepStatus(\n onboardingId,\n
'ea-download',\n 'complete'\n );\n await
apiServices.alerting.waitForAlert(alertId);\n```","sha":"48cd2075f75386b515e19567095c03a8ca73fe20"}},"sourceBranch":"main","suggestedTargetBranches":["9.0","8.x"],"targetPullRequestStates":[{"branch":"9.0","label":"v9.0.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/214470","number":214470,"mergeCommit":{"message":"[scout]
add 'apiServices' fixture to group Kibana API helpers (#214470)\n\n##
Summary\n\nWe decided to group `Kibana API helpers` under a single
fixture:\n`apiServices` instead of individual fixtures. It should
simplify the\nsearch of existing helpers and reduce a risk for Teams to
create the\nsame helper like we see today with FTR.\nAdding just
`apiServices` in test context and adding dot will expand a\nlist of all
available API helpers + it can be extended for individual\nsolution
(e.g. @kbn/scout-oblt) and directly in plugin (if there is no\nchance to
re-use it in other plugins)\n\n<img width=\"699\"
alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/34a76659-04af-48c4-ab69-abda0c950206\"\n/>\n\n\nBefore:\n\n```\ntest('should
create something', async ({\n fleetApi,\n onboardingApi,\n
alertingApi,\n }) => {\n await
fleetApi.integration.install(integrationName);\n await
onboardingApi.updateInstallationStepStatus(\n onboardingId,\n
'ea-download',\n 'complete'\n );\n await
alertingApi.waitForAlert(alertId);\n```\n\nAfter:\n\n```\ntest('should
create something', async ({\n apiServices,\n }) => {\n await
apiServices.fleet.integration.install(integrationName);\n await
apiServices.onboarding.updateInstallationStepStatus(\n onboardingId,\n
'ea-download',\n 'complete'\n );\n await
apiServices.alerting.waitForAlert(alertId);\n```","sha":"48cd2075f75386b515e19567095c03a8ca73fe20"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Dzmitry Lemechko <dzmitry.lemechko@elastic.co>
This commit is contained in:
Kibana Machine 2025-03-19 13:13:13 +01:00 committed by GitHub
parent 882c4cd297
commit 35100fdb73
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 344 additions and 186 deletions

View file

@ -211,20 +211,17 @@ Install dependencies by running the following commands:
Move to the `src/platform/packages/shared/kbn-scout` directory to begin development.
#### Adding or Modifying Features
### Adding or Modifying Components
Contributions to sharable fixtures and page objects are highly encouraged to promote reusability, stability, and ease of adoption. Follow these steps:
Create a New Page Object: Add your Page Object to the `src/playwright/page_objects` directory. For instance:
Contributions to sharable `Fixtures`, `API services` and `Page Objects` are highly encouraged to promote reusability, stability, and ease of adoption. Follow these steps:
#### Adding Page Objects
1. **Create a New Page Object:** Add your Page Object to the src/playwright/page_objects directory. For instance:
1. **Create a New Page Object:** Add a new file to the `src/playwright/page_objects` directory. For instance:
```ts
export class NewPage {
constructor(private readonly page: ScoutPage) {}
// implementation
}
```
@ -237,7 +234,48 @@ export function createCorePageObjects(page: ScoutPage): PageObjects {
};
}
```
#### Adding Fixtures
#### Adding API service
1. **Create a New API service:** Add your service to the `src/playwright/fixtures/worker/apis` directory. For instance:
```ts
export interface FleetApiService {
integration: {
install: (name: string) => Promise<void>;
delete: (name: string) => Promise<void>;
};
}
export const getFleetApiHelper = (log: ScoutLogger, kbnClient: KbnClient): FleetApiService => {
return {
integration: {
install: async (name: string) => {
// implementation
},
delete: async (name: string) => {
// implementation
},
},
};
};
```
2. **Register the API service:** Update the index file to include the new service:
```ts
export const apiServicesFixture = coreWorkerFixtures.extend<
{},
{ apiServices: ApiServicesFixture }
>({
apiServices: [
async ({ kbnClient, log }, use) => {
const services = {
// add new service
fleet: getFleetApiHelper(log, kbnClient),
};
...
],
});
```
#### Adding Fixture
1. **Determine Fixture Scope:** Decide if your fixture should apply to the `test` (per-test) or `worker` (per-worker) scope.
2. **Implement the Fixture:** Add the implementation to `src/playwright/fixtures/test` or `src/playwright/fixtures/worker`.
@ -260,7 +298,11 @@ export const scoutTestFixtures = mergeTests(
```
#### Best Practices
- **Reusable Code:** When creating Page Objects or Fixtures that apply to more than one plugin, ensure they are added to the kbn-scout package.
- **Reusable Code:** When creating Page Objects, API services or Fixtures that apply to more than one plugin, ensure they are added to the `kbn-scout` package.
- **Adhere to Existing Structure:** Maintain consistency with the project's architecture.
- **Keep the Scope of Components Clear** When designing test components, keep in naming conventions, scope, maintainability and performance.
- `Page Objects` should focus exclusively on UI interactions (clicking buttons, filling forms, navigating page). They should not make API calls directly.
- `API Services` should handle server interactions, such as sending API requests and processing responses.
- `Fixtures` can combine browser interactions with API requests, but they should be used wisely, especially with the `test` scope: a new instance of the fixture is created for **every test block**. If a fixture performs expensive operations (API setup, data ingestion), excessive usage can **slow down** the test suite runtime. Consider using `worker` scope when appropriate to reuse instances across tests within a worker.
- **Add Unit Tests:** Include tests for new logic where applicable, ensuring it works as expected.
- **Playwright documentation:** [Official best practices](https://playwright.dev/docs/best-practices)

View file

@ -23,6 +23,7 @@ export type {
ScoutTestOptions,
ScoutPage,
PageObjects,
ApiServicesFixture,
ScoutTestFixtures,
ScoutWorkerFixtures,
ScoutParallelTestFixtures,

View file

@ -9,14 +9,14 @@
import { mergeTests } from 'playwright/test';
import {
apiFixtures,
apiServicesFixture,
coreWorkerFixtures,
esArchiverFixture,
scoutSpaceParallelFixture,
synthtraceFixture,
} from './worker';
import type {
ApiParallelWorkerFixtures,
ApiServicesFixture,
EsClient,
KbnClient,
KibanaUrl,
@ -36,7 +36,7 @@ export const scoutParallelFixtures = mergeTests(
// worker scope fixtures
coreWorkerFixtures,
scoutSpaceParallelFixture,
apiFixtures,
apiServicesFixture,
// test scope fixtures
browserAuthFixture,
scoutPageParallelFixture,
@ -50,18 +50,19 @@ export interface ScoutParallelTestFixtures {
pageObjects: PageObjects;
}
export interface ScoutParallelWorkerFixtures extends ApiParallelWorkerFixtures {
export interface ScoutParallelWorkerFixtures {
log: ScoutLogger;
config: ScoutTestConfig;
kbnUrl: KibanaUrl;
kbnClient: KbnClient;
esClient: EsClient;
scoutSpace: ScoutSpaceParallelFixture;
apiServices: ApiServicesFixture;
}
export const globalSetup = mergeTests(
coreWorkerFixtures,
esArchiverFixture,
synthtraceFixture,
apiFixtures
apiServicesFixture
);

View file

@ -9,8 +9,7 @@
import { mergeTests } from 'playwright/test';
import {
ApiFixtures,
apiFixtures,
apiServicesFixture,
coreWorkerFixtures,
esArchiverFixture,
uiSettingsFixture,
@ -18,6 +17,7 @@ import {
lighthouseFixture,
} from './worker';
import type {
ApiServicesFixture,
EsArchiverFixture,
EsClient,
KbnClient,
@ -37,7 +37,7 @@ import {
} from './test';
import type { BrowserAuthFixture, ScoutPage, PageObjects, PerfTrackerFixture } from './test';
export type { ScoutPage, PageObjects } from './test';
export type { LighthouseAuditOptions } from './worker';
export type { ApiServicesFixture, LighthouseAuditOptions } from './worker';
export const scoutFixtures = mergeTests(
// worker scope fixtures
@ -46,7 +46,7 @@ export const scoutFixtures = mergeTests(
uiSettingsFixture,
synthtraceFixture,
// api fixtures
apiFixtures,
apiServicesFixture,
// test scope fixtures
browserAuthFixture,
scoutPageFixture,
@ -63,7 +63,7 @@ export interface ScoutTestFixtures {
perfTracker: PerfTrackerFixture;
}
export interface ScoutWorkerFixtures extends ApiFixtures {
export interface ScoutWorkerFixtures extends ApiServicesFixture {
log: ScoutLogger;
config: ScoutTestConfig;
kbnUrl: KibanaUrl;
@ -71,6 +71,7 @@ export interface ScoutWorkerFixtures extends ApiFixtures {
esClient: EsClient;
esArchiver: EsArchiverFixture;
uiSettings: UiSettingsFixture;
apiServices: ApiServicesFixture;
apmSynthtraceEsClient: SynthtraceFixture['apmSynthtraceEsClient'];
infraSynthtraceEsClient: SynthtraceFixture['infraSynthtraceEsClient'];
otelSynthtraceEsClient: SynthtraceFixture['otelSynthtraceEsClient'];

View file

@ -7,65 +7,45 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { measurePerformanceAsync } from '../../../../../common';
import { coreWorkerFixtures } from '../../core_fixtures';
import { KbnClient, ScoutLogger, measurePerformanceAsync } from '../../../../../common';
export interface FleetApiFixture {
export interface FleetApiService {
integration: {
install: (name: string) => Promise<void>;
delete: (name: string) => Promise<void>;
};
}
/**
* This fixture provides a helper to interact with the Fleet API.
*/
export const fleetApiFixture = coreWorkerFixtures.extend<{}, { fleetApi: FleetApiFixture }>({
fleetApi: [
async ({ kbnClient, log }, use) => {
const fleetApiHelper = {
integration: {
install: async (name: string) => {
await measurePerformanceAsync(
log,
`fleetApi.integration.install [${name}]`,
async () => {
await kbnClient.request({
method: 'POST',
path: `/api/fleet/epm/custom_integrations`,
body: {
force: true,
integrationName: name,
datasets: [
{ name: `${name}.access`, type: 'logs' },
{ name: `${name}.error`, type: 'metrics' },
{ name: `${name}.warning`, type: 'logs' },
],
},
});
}
);
},
export const getFleetApiHelper = (log: ScoutLogger, kbnClient: KbnClient): FleetApiService => {
return {
integration: {
install: async (name: string) => {
await measurePerformanceAsync(log, `fleetApi.integration.install [${name}]`, async () => {
await kbnClient.request({
method: 'POST',
path: `/api/fleet/epm/custom_integrations`,
body: {
force: true,
integrationName: name,
datasets: [
{ name: `${name}.access`, type: 'logs' },
{ name: `${name}.error`, type: 'metrics' },
{ name: `${name}.warning`, type: 'logs' },
],
},
});
});
},
delete: async (name: string) => {
await measurePerformanceAsync(
log,
`fleetApi.integration.delete [${name}]`,
async () => {
await kbnClient.request({
method: 'DELETE',
path: `/api/fleet/epm/packages/${name}`,
ignoreErrors: [400],
});
}
);
},
},
};
log.serviceLoaded('fleetApi');
await use(fleetApiHelper);
delete: async (name: string) => {
await measurePerformanceAsync(log, `fleetApi.integration.delete [${name}]`, async () => {
await kbnClient.request({
method: 'DELETE',
path: `/api/fleet/epm/packages/${name}`,
ignoreErrors: [400],
});
});
},
},
{ scope: 'worker' },
],
});
};
};

View file

@ -7,15 +7,30 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { mergeTests } from 'playwright/test';
import { FleetApiFixture, fleetApiFixture } from './fleet';
import { coreWorkerFixtures } from '../core_fixtures';
import { FleetApiService, getFleetApiHelper } from './fleet';
export const apiFixtures = mergeTests(fleetApiFixture);
export interface ApiFixtures {
fleetApi: FleetApiFixture;
export interface ApiServicesFixture {
fleet: FleetApiService;
// add more services here
}
export interface ApiParallelWorkerFixtures {
fleetApi: FleetApiFixture;
}
/**
* This fixture provides a helper to interact with the Kibana APIs like Fleet, Spaces, Alerting, etc.
*/
export const apiServicesFixture = coreWorkerFixtures.extend<
{},
{ apiServices: ApiServicesFixture }
>({
apiServices: [
async ({ kbnClient, log }, use) => {
const services = {
fleet: getFleetApiHelper(log, kbnClient),
};
log.serviceLoaded('apiServices');
await use(services);
},
{ scope: 'worker' },
],
});

View file

@ -26,8 +26,8 @@ export type { UiSettingsFixture } from './ui_settings';
export { scoutSpaceParallelFixture } from './scout_space';
export type { ScoutSpaceParallelFixture } from './scout_space';
export { apiFixtures } from './apis';
export type { ApiFixtures, ApiParallelWorkerFixtures } from './apis';
export { apiServicesFixture } from './apis';
export type { ApiServicesFixture } from './apis';
export { synthtraceFixture } from './synthtrace';
export type { SynthtraceFixture } from './synthtrace';

View file

@ -25,15 +25,17 @@ export { expect } from './expect';
export type { ScoutPlaywrightOptions, ScoutTestOptions } from './types';
export type {
ScoutPage,
// can be extended with solution specific fixtures
ScoutTestFixtures,
ScoutWorkerFixtures,
ScoutParallelTestFixtures,
ScoutParallelWorkerFixtures,
ScoutPage,
// can be extended with solution specific API services
ApiServicesFixture,
// can be extended with solution specific Page Objects
PageObjects,
} from './fixtures';
// use to tag tests
export { tags } from './tags';
export { ingestTestDataHook, ingestSynthtraceDataHook } from './global_hooks';

View file

@ -7,6 +7,7 @@
export { test, spaceTest } from './src/playwright';
export type {
ObltApiServicesFixture,
ObltPageObjects,
ObltTestFixtures,
ObltWorkerFixtures,

View file

@ -6,9 +6,14 @@
*/
import { spaceTest as spaceBase } from '@kbn/scout';
import type { ApiServicesFixture, KbnClient } from '@kbn/scout';
import { extendPageObjects } from '../page_objects';
import { ObltParallelTestFixtures, ObltParallelWorkerFixtures } from './types';
import {
ObltApiServicesFixture,
ObltParallelTestFixtures,
ObltParallelWorkerFixtures,
} from './types';
/**
* Should be used test spec files, running in parallel in isolated spaces agaist the same Kibana instance.
@ -27,4 +32,17 @@ export const spaceTest = spaceBase.extend<ObltParallelTestFixtures, ObltParallel
const extendedPageObjects = extendPageObjects(pageObjects, page);
await use(extendedPageObjects);
},
apiServices: [
async (
{ apiServices, kbnClient }: { apiServices: ApiServicesFixture; kbnClient: KbnClient },
use: (extendedApiServices: ObltApiServicesFixture) => Promise<void>
) => {
const extendedApiServices = apiServices as ObltApiServicesFixture;
// extend with Observability specific API services
// extendedApiServices.<service_name> = getServiceApiHelper(kbnClient);
await use(extendedApiServices);
},
{ scope: 'worker' },
],
});

View file

@ -6,9 +6,10 @@
*/
import { test as base } from '@kbn/scout';
import type { ApiServicesFixture, KbnClient } from '@kbn/scout';
import { extendPageObjects } from '../page_objects';
import { ObltTestFixtures, ObltWorkerFixtures } from './types';
import { ObltApiServicesFixture, ObltTestFixtures, ObltWorkerFixtures } from './types';
/**
* Should be used for the test spec files executed seqentially.
@ -27,4 +28,17 @@ export const test = base.extend<ObltTestFixtures, ObltWorkerFixtures>({
const extendedPageObjects = extendPageObjects(pageObjects, page);
await use(extendedPageObjects);
},
apiServices: [
async (
{ apiServices, kbnClient }: { apiServices: ApiServicesFixture; kbnClient: KbnClient },
use: (extendedApiServices: ObltApiServicesFixture) => Promise<void>
) => {
const extendedApiServices = apiServices as ObltApiServicesFixture;
// extend with Observability specific API services
// extendedApiServices.<service_name> = getServiceApiHelper(kbnClient);
await use(extendedApiServices);
},
{ scope: 'worker' },
],
});

View file

@ -5,7 +5,8 @@
* 2.0.
*/
import {
import type {
ApiServicesFixture,
ScoutParallelTestFixtures,
ScoutParallelWorkerFixtures,
ScoutTestFixtures,
@ -17,10 +18,16 @@ export interface ObltTestFixtures extends ScoutTestFixtures {
pageObjects: ObltPageObjects;
}
export type ObltWorkerFixtures = ScoutWorkerFixtures;
export type ObltApiServicesFixture = ApiServicesFixture;
export interface ObltWorkerFixtures extends ScoutWorkerFixtures {
apiServices: ObltApiServicesFixture;
}
export interface ObltParallelTestFixtures extends ScoutParallelTestFixtures {
pageObjects: ObltPageObjects;
}
export type ObltParallelWorkerFixtures = ScoutParallelWorkerFixtures;
export interface ObltParallelWorkerFixtures extends ScoutParallelWorkerFixtures {
apiServices: ObltApiServicesFixture;
}

View file

@ -0,0 +1,37 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { KbnClient } from '@kbn/scout-oblt';
export interface OnboardingApiService {
updateInstallationStepStatus: (
onboardingId: string,
step: string,
status: string,
payload?: object
) => Promise<void>;
}
export const getOnboardingApiHelper = (kbnClient: KbnClient) => {
return {
updateInstallationStepStatus: async (
onboardingId: string,
step: string,
status: string,
payload?: object
) => {
await kbnClient.request({
method: 'POST',
path: `/internal/observability_onboarding/flow/${onboardingId}/step/${step}`,
body: {
status,
payload,
},
});
},
};
};

View file

@ -6,18 +6,25 @@
*/
import { v4 as uuidv4 } from 'uuid';
import { test as base, ObltTestFixtures, ObltWorkerFixtures } from '@kbn/scout-oblt';
import { mergeTests } from 'playwright/test';
import { onboardingApiFixture, OnboardingApiFixture } from './onboarding_api';
import { test as base } from '@kbn/scout-oblt';
import type {
KbnClient,
ObltApiServicesFixture,
ObltTestFixtures,
ObltWorkerFixtures,
} from '@kbn/scout-oblt';
import { getOnboardingApiHelper, OnboardingApiService } from './apis/onboarding';
export type ExtendedScoutTestFixtures = ObltTestFixtures;
export interface ExtendedApiServicesFixture extends ObltApiServicesFixture {
onboarding: OnboardingApiService;
}
export interface ExtendedScoutWorkerFixtures extends ObltWorkerFixtures {
onboardingApi: OnboardingApiFixture;
apiServices: ExtendedApiServicesFixture;
}
const testFixtures = mergeTests(base, onboardingApiFixture);
export const test = testFixtures.extend<ExtendedScoutTestFixtures, ExtendedScoutWorkerFixtures>({
export const test = base.extend<ExtendedScoutTestFixtures, ExtendedScoutWorkerFixtures>({
pageObjects: async (
{
pageObjects,
@ -32,6 +39,18 @@ export const test = testFixtures.extend<ExtendedScoutTestFixtures, ExtendedScout
await use(extendedPageObjects);
},
apiServices: [
async (
{ apiServices, kbnClient }: { apiServices: ObltApiServicesFixture; kbnClient: KbnClient },
use: (extendedApiServices: ExtendedApiServicesFixture) => Promise<void>
) => {
const extendedApiServices = apiServices as ExtendedApiServicesFixture;
extendedApiServices.onboarding = getOnboardingApiHelper(kbnClient);
await use(extendedApiServices);
},
{ scope: 'worker' },
],
});
export const generateIntegrationName = (name: string) => `${name}_${uuidv4().slice(0, 5)}`;

View file

@ -1,48 +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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { test as base } from '@kbn/scout-oblt';
export interface OnboardingApiFixture {
updateInstallationStepStatus: (
onboardingId: string,
step: string,
status: string,
payload?: object
) => Promise<void>;
}
/**
* This fixture provides a helper to interact with the Observability Onboarding API.
*/
export const onboardingApiFixture = base.extend<{}, { onboardingApi: OnboardingApiFixture }>({
onboardingApi: [
async ({ kbnClient, log }, use) => {
const onboardingApiHelper: OnboardingApiFixture = {
updateInstallationStepStatus: async (
onboardingId: string,
step: string,
status: string,
payload?: object
) => {
await kbnClient.request({
method: 'POST',
path: `/internal/observability_onboarding/flow/${onboardingId}/step/${step}`,
body: {
status,
payload,
},
});
},
};
log.serviceLoaded('onboardingApi');
await use(onboardingApiHelper);
},
{ scope: 'worker' },
],
});

View file

@ -20,8 +20,8 @@ test.describe(
await customLogs.goto();
});
test.afterEach(async ({ fleetApi }) => {
await fleetApi.integration.delete(integrationName);
test.afterEach(async ({ apiServices }) => {
await apiServices.fleet.integration.delete(integrationName);
});
test('should be installed, show API Key and correct instructions', async ({

View file

@ -15,8 +15,8 @@ test.describe(
const integrationName = generateIntegrationName('mylogs');
const logsFilePath = `${integrationName}.log`;
test.afterEach(async ({ fleetApi }) => {
await fleetApi.integration.delete(integrationName);
test.afterEach(async ({ apiServices }) => {
await apiServices.fleet.integration.delete(integrationName);
});
test('should be displayed when user has no previleges', async ({
@ -92,10 +92,10 @@ test.describe(
test('should be displayed when integration with the same name exists', async ({
browserAuth,
pageObjects: { customLogs },
fleetApi,
apiServices,
page,
}) => {
await fleetApi.integration.install(integrationName);
await apiServices.fleet.integration.install(integrationName);
await browserAuth.loginAsAdmin();
await customLogs.goto();

View file

@ -34,58 +34,79 @@ test.describe('Observability Onboarding - Elastic Agent', { tag: ['@ess', '@svlO
await pageObjects.customLogs.apiKeyCreatedCallout.waitFor({ state: 'visible' });
});
test.afterEach(async ({ fleetApi }) => {
await fleetApi.integration.delete(integrationName);
test.afterEach(async ({ apiServices }) => {
await apiServices.fleet.integration.delete(integrationName);
});
test('should be installed sucessfully', async ({
pageObjects: { customLogs },
onboardingApi,
}) => {
test('should be installed sucessfully', async ({ pageObjects: { customLogs }, apiServices }) => {
// downloading agent
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-download', 'loading');
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-download',
'loading'
);
await checkAgentStatusUpdated(
customLogs.getStepStatusLocator('loading'),
'Downloading Elastic Agent'
);
// downloading agent failed
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-download', 'danger');
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-download',
'danger'
);
await expect(customLogs.getStepStatusLocator('danger'), 'Download Elastic Agent').toBeVisible();
// downloading agent completed
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete');
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-download',
'complete'
);
await checkAgentStatusUpdated(
customLogs.getStepStatusLocator('complete'),
'Elastic Agent downloaded'
);
// extracting agent
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-extract', 'loading');
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-extract',
'loading'
);
await checkAgentStatusUpdated(
customLogs.getStepStatusLocator('loading'),
'Extracting Elastic Agent'
);
// extracting agent completed
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete');
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-extract',
'complete'
);
await checkAgentStatusUpdated(
customLogs.getStepStatusLocator('complete'),
'Elastic Agent extracted'
);
// installing agent failed
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-install', 'danger');
await apiServices.onboarding.updateInstallationStepStatus(onboardingId, 'ea-install', 'danger');
await checkAgentStatusUpdated(
customLogs.getStepStatusLocator('danger'),
'Install Elastic Agent'
);
// installing agent completed
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete');
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-install',
'complete'
);
await checkAgentStatusUpdated(
customLogs.getStepStatusLocator('complete'),
'Elastic Agent installed'
);
// agent connecting
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-status', 'loading');
await apiServices.onboarding.updateInstallationStepStatus(onboardingId, 'ea-status', 'loading');
await checkAgentStatusUpdated(
customLogs.getStepStatusLocator('loading'),
'Connecting to the Elastic Agent'
@ -93,9 +114,14 @@ test.describe('Observability Onboarding - Elastic Agent', { tag: ['@ess', '@svlO
await expect(customLogs.getCheckLogsStepLocator('incomplete')).toBeVisible();
await expect(customLogs.checkLogsStepMessage).toHaveText('Ship logs to Elastic Observability');
// agent connected
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', {
agentId: 'test-agent-id',
});
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-status',
'complete',
{
agentId: 'test-agent-id',
}
);
await checkAgentStatusUpdated(
customLogs.getStepStatusLocator('complete'),
'Connected to the Elastic Agent'
@ -104,24 +130,45 @@ test.describe('Observability Onboarding - Elastic Agent', { tag: ['@ess', '@svlO
test('should be configured sucessfully for Linux and wait for logs', async ({
pageObjects: { customLogs },
onboardingApi,
apiServices,
}) => {
// install and connect agent for linux
await customLogs.autoDownloadConfigurationToggle.click();
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete');
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete');
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete');
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', {
agentId: 'test-agent-id',
});
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-download',
'complete'
);
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-extract',
'complete'
);
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-install',
'complete'
);
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-status',
'complete',
{
agentId: 'test-agent-id',
}
);
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-config', 'loading');
await apiServices.onboarding.updateInstallationStepStatus(onboardingId, 'ea-config', 'loading');
await checkAgentStatusUpdated(
customLogs.getStepStatusLocator('loading'),
'Downloading Elastic Agent config'
);
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-config', 'complete');
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-config',
'complete'
);
await checkAgentStatusUpdated(
customLogs.getStepStatusLocator('complete'),
'Elastic Agent config written to /opt/Elastic/Agent/elastic-agent.yml'
@ -133,19 +180,40 @@ test.describe('Observability Onboarding - Elastic Agent', { tag: ['@ess', '@svlO
test('should be configured sucessfully for MacOS and wait for logs', async ({
pageObjects: { customLogs },
onboardingApi,
apiServices,
}) => {
// install and connect agent for macos
await customLogs.selectPlatform('macos');
await customLogs.autoDownloadConfigurationToggle.click();
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete');
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete');
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete');
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', {
agentId: 'test-agent-id',
});
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-download',
'complete'
);
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-extract',
'complete'
);
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-install',
'complete'
);
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-status',
'complete',
{
agentId: 'test-agent-id',
}
);
await onboardingApi.updateInstallationStepStatus(onboardingId, 'ea-config', 'complete');
await apiServices.onboarding.updateInstallationStepStatus(
onboardingId,
'ea-config',
'complete'
);
await checkAgentStatusUpdated(
customLogs.getStepStatusLocator('complete'),
'Elastic Agent config written to /Library/Elastic/Agent/elastic-agent.yml'