mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
# 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:
parent
882c4cd297
commit
35100fdb73
18 changed files with 344 additions and 186 deletions
|
@ -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)
|
||||
|
|
|
@ -23,6 +23,7 @@ export type {
|
|||
ScoutTestOptions,
|
||||
ScoutPage,
|
||||
PageObjects,
|
||||
ApiServicesFixture,
|
||||
ScoutTestFixtures,
|
||||
ScoutWorkerFixtures,
|
||||
ScoutParallelTestFixtures,
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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'];
|
||||
|
|
|
@ -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' },
|
||||
],
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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' },
|
||||
],
|
||||
});
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
export { test, spaceTest } from './src/playwright';
|
||||
export type {
|
||||
ObltApiServicesFixture,
|
||||
ObltPageObjects,
|
||||
ObltTestFixtures,
|
||||
ObltWorkerFixtures,
|
||||
|
|
|
@ -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' },
|
||||
],
|
||||
});
|
||||
|
|
|
@ -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' },
|
||||
],
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
|
@ -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)}`;
|
||||
|
|
|
@ -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' },
|
||||
],
|
||||
});
|
|
@ -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 ({
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue