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 `8.x`: - [initial @kbn/scout-security plugin (#210433)](https://github.com/elastic/kibana/pull/210433) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Gloria Hornero","email":"gloria.hornero@elastic.co"},"sourceCommit":{"committedDate":"2025-03-21T10:59:30Z","message":"initial @kbn/scout-security plugin (#210433)\n\n## Summary\n\nCloses https://github.com/elastic/kibana/issues/210298\n\nIn this PR we are adding the initial structure for the\n@kibana/scout-security package, note that this is not ready to be used\nand any new test using this package, is not going to be executed as part\nof the regular pipelines, meaning, you are not going to add coverage to\nthe application. \n\n@kibana/scout-security package is a test package that extends @kbn/scout\nwith test helpers specifically designed to test Security Solution\nfunctionalities in Kibana. All tests under Security plugins should only\nimport from @kbn/scout-security, not from @kbn/scout. \n\nThis PR is a POC to start testing development by providing custom\nPlaywright fixtures, page objects, and utilities tailored for\nSecurity-related testing scenarios.\n\nThings to follow-up: \n\n- CustomQueryRule interface is already declared in\n`x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts`\nas `QueryRuleCreateProps` \n- DETECTION_ENGINE_RULES_URL and DETECTION_ENGINE_RULES_BULK_ACTION are\nalready declared in `@kbn/security-solution-plugin/common/constants`\n\nIt would be great if all of that is extracted from the plugin to a\npackage so it can be reused instead of having to duplicate the code.\n\nUntil the package is not ready to be used and has not been introduced to\nthe different teams, appex-qa and myself will be the owners of it to\nmake sure that best practices are followed\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by: Dzmitry Lemechko <dzmitry.lemechko@elastic.co>","sha":"d5a0501fb8148b4274a00921a6061d850b142f28","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team: SecuritySolution","backport:version","Team: Sec Eng Productivity","test:scout","v9.1.0","v8.19.0"],"title":"initial @kbn/scout-security plugin","number":210433,"url":"https://github.com/elastic/kibana/pull/210433","mergeCommit":{"message":"initial @kbn/scout-security plugin (#210433)\n\n## Summary\n\nCloses https://github.com/elastic/kibana/issues/210298\n\nIn this PR we are adding the initial structure for the\n@kibana/scout-security package, note that this is not ready to be used\nand any new test using this package, is not going to be executed as part\nof the regular pipelines, meaning, you are not going to add coverage to\nthe application. \n\n@kibana/scout-security package is a test package that extends @kbn/scout\nwith test helpers specifically designed to test Security Solution\nfunctionalities in Kibana. All tests under Security plugins should only\nimport from @kbn/scout-security, not from @kbn/scout. \n\nThis PR is a POC to start testing development by providing custom\nPlaywright fixtures, page objects, and utilities tailored for\nSecurity-related testing scenarios.\n\nThings to follow-up: \n\n- CustomQueryRule interface is already declared in\n`x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts`\nas `QueryRuleCreateProps` \n- DETECTION_ENGINE_RULES_URL and DETECTION_ENGINE_RULES_BULK_ACTION are\nalready declared in `@kbn/security-solution-plugin/common/constants`\n\nIt would be great if all of that is extracted from the plugin to a\npackage so it can be reused instead of having to duplicate the code.\n\nUntil the package is not ready to be used and has not been introduced to\nthe different teams, appex-qa and myself will be the owners of it to\nmake sure that best practices are followed\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by: Dzmitry Lemechko <dzmitry.lemechko@elastic.co>","sha":"d5a0501fb8148b4274a00921a6061d850b142f28"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/210433","number":210433,"mergeCommit":{"message":"initial @kbn/scout-security plugin (#210433)\n\n## Summary\n\nCloses https://github.com/elastic/kibana/issues/210298\n\nIn this PR we are adding the initial structure for the\n@kibana/scout-security package, note that this is not ready to be used\nand any new test using this package, is not going to be executed as part\nof the regular pipelines, meaning, you are not going to add coverage to\nthe application. \n\n@kibana/scout-security package is a test package that extends @kbn/scout\nwith test helpers specifically designed to test Security Solution\nfunctionalities in Kibana. All tests under Security plugins should only\nimport from @kbn/scout-security, not from @kbn/scout. \n\nThis PR is a POC to start testing development by providing custom\nPlaywright fixtures, page objects, and utilities tailored for\nSecurity-related testing scenarios.\n\nThings to follow-up: \n\n- CustomQueryRule interface is already declared in\n`x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts`\nas `QueryRuleCreateProps` \n- DETECTION_ENGINE_RULES_URL and DETECTION_ENGINE_RULES_BULK_ACTION are\nalready declared in `@kbn/security-solution-plugin/common/constants`\n\nIt would be great if all of that is extracted from the plugin to a\npackage so it can be reused instead of having to duplicate the code.\n\nUntil the package is not ready to be used and has not been introduced to\nthe different teams, appex-qa and myself will be the owners of it to\nmake sure that best practices are followed\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by: Dzmitry Lemechko <dzmitry.lemechko@elastic.co>","sha":"d5a0501fb8148b4274a00921a6061d850b142f28"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Dzmitry Lemechko <dzmitry.lemechko@elastic.co>
This commit is contained in:
parent
b866dc9159
commit
4d53520eea
39 changed files with 944 additions and 5 deletions
|
@ -4,4 +4,5 @@ ui_tests:
|
|||
- discover_enhanced
|
||||
- maps
|
||||
- observability_onboarding
|
||||
- security_solution
|
||||
disabled:
|
||||
|
|
|
@ -403,6 +403,8 @@ const getPipeline = (filename: string, removeSteps = true) => {
|
|||
/^x-pack\/solutions\/observability\/packages\/kbn-scout-oblt/,
|
||||
/^x-pack\/solutions\/observability\/plugins\/apm/,
|
||||
/^x-pack\/solutions\/observability\/plugins\/observability_onboarding/,
|
||||
/^x-pack\/solutions\/security\/packages\/kbn-scout-security/,
|
||||
/^x-pack\/solutions\/security\/plugins\/security_solution/,
|
||||
])) ||
|
||||
GITHUB_PR_LABELS.includes('ci:scout-ui-tests')
|
||||
) {
|
||||
|
|
|
@ -1452,6 +1452,7 @@ module.exports = {
|
|||
files: [
|
||||
'packages/kbn-scout/src/playwright/**/*.ts',
|
||||
'x-pack/solutions/observability/packages/kbn-scout-oblt/src/playwright/**/*.ts',
|
||||
'x-pack/solutions/security/packages/kbn-scout-security/src/playwright/**/*.ts',
|
||||
'src/platform/plugins/**/ui_tests/**/*.ts',
|
||||
'x-pack/platform/plugins/**/ui_tests/**/*.ts',
|
||||
'x-pack/solutions/**/plugins/**/ui_tests/**/*.ts',
|
||||
|
|
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
|
@ -797,6 +797,7 @@ src/platform/packages/shared/kbn-scout @elastic/appex-qa
|
|||
src/platform/packages/private/kbn-scout-info @elastic/appex-qa
|
||||
x-pack/solutions/observability/packages/kbn-scout-oblt @elastic/appex-qa
|
||||
src/platform/packages/private/kbn-scout-reporting @elastic/appex-qa
|
||||
x-pack/solutions/security/packages/kbn-scout-security @elastic/appex-qa
|
||||
examples/screenshot_mode_example @elastic/appex-sharedux
|
||||
src/platform/plugins/shared/screenshot_mode @elastic/appex-sharedux
|
||||
x-pack/examples/screenshotting_example @elastic/appex-sharedux
|
||||
|
|
|
@ -1506,6 +1506,7 @@
|
|||
"@kbn/scout-info": "link:src/platform/packages/private/kbn-scout-info",
|
||||
"@kbn/scout-oblt": "link:x-pack/solutions/observability/packages/kbn-scout-oblt",
|
||||
"@kbn/scout-reporting": "link:src/platform/packages/private/kbn-scout-reporting",
|
||||
"@kbn/scout-security": "link:x-pack/solutions/security/packages/kbn-scout-security",
|
||||
"@kbn/security-api-integration-helpers": "link:x-pack/test/security_api_integration/packages/helpers",
|
||||
"@kbn/serverless-storybook-config": "link:src/platform/packages/shared/serverless/storybook/config",
|
||||
"@kbn/set-map": "link:packages/kbn-set-map",
|
||||
|
|
|
@ -127,4 +127,4 @@ system_indices_superuser:
|
|||
- application: '*'
|
||||
privileges: ['*']
|
||||
resources: ['*']
|
||||
run_as: ['*']
|
||||
run_as: ['*']
|
|
@ -15,6 +15,7 @@ export {
|
|||
lighthouseTest,
|
||||
globalSetupHook,
|
||||
tags,
|
||||
browserAuthFixture,
|
||||
createPlaywrightConfig,
|
||||
createLazyPageObject,
|
||||
} from './src/playwright';
|
||||
|
@ -24,6 +25,8 @@ export type {
|
|||
ScoutPage,
|
||||
PageObjects,
|
||||
ApiServicesFixture,
|
||||
BrowserAuthFixture,
|
||||
SamlAuth,
|
||||
ScoutTestFixtures,
|
||||
ScoutWorkerFixtures,
|
||||
ScoutParallelTestFixtures,
|
||||
|
@ -43,5 +46,6 @@ export type {
|
|||
|
||||
// re-export from Playwright
|
||||
export type { Locator, CDPSession } from 'playwright/test';
|
||||
export { mergeTests, test as playwrightTest } from 'playwright/test';
|
||||
|
||||
export { measurePerformance, measurePerformanceAsync } from './src/common';
|
||||
|
|
|
@ -36,7 +36,7 @@ import {
|
|||
perfTrackerFixture,
|
||||
} from './test';
|
||||
import type { BrowserAuthFixture, ScoutPage, PageObjects, PerfTrackerFixture } from './test';
|
||||
export type { ScoutPage, PageObjects } from './test';
|
||||
export type { ScoutPage, PageObjects, BrowserAuthFixture } from './test';
|
||||
export type { ApiServicesFixture, LighthouseAuditOptions } from './worker';
|
||||
|
||||
export const scoutFixtures = mergeTests(
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { ElasticsearchRoleDescriptor, KibanaRole, PROJECT_DEFAULT_ROLES } from '../../../../common';
|
||||
import { KibanaRole, PROJECT_DEFAULT_ROLES } from '../../../../common';
|
||||
import { coreWorkerFixtures } from '../../worker';
|
||||
|
||||
export type LoginFunction = (role: string) => Promise<void>;
|
||||
|
@ -28,6 +28,12 @@ export interface BrowserAuthFixture {
|
|||
* @returns A Promise that resolves once the cookie in browser is set.
|
||||
*/
|
||||
loginAsPrivilegedUser: () => Promise<void>;
|
||||
/**
|
||||
* Logs in as a user with a role.
|
||||
* @param role - A role object that defines the Kibana and ES previleges.
|
||||
* @returns A Promise that resolves once the cookie in browser is set.
|
||||
*/
|
||||
loginAs: (role: string) => Promise<void>;
|
||||
/**
|
||||
* Logs in as a user with a custom role.
|
||||
* @param role - A role object that defines the Kibana and ES previleges. Role will re-created if it doesn't exist.
|
||||
|
@ -62,7 +68,7 @@ export const browserAuthFixture = coreWorkerFixtures.extend<{ browserAuth: Brows
|
|||
await setSessionCookie(cookie);
|
||||
};
|
||||
|
||||
const loginWithCustomRole = async (role: KibanaRole | ElasticsearchRoleDescriptor) => {
|
||||
const loginWithCustomRole = async (role: KibanaRole) => {
|
||||
await samlAuth.setCustomRole(role);
|
||||
isCustomRoleCreated = true;
|
||||
return loginAs(samlAuth.customRoleName);
|
||||
|
@ -82,6 +88,7 @@ export const browserAuthFixture = coreWorkerFixtures.extend<{ browserAuth: Brows
|
|||
loginAsAdmin,
|
||||
loginAsViewer,
|
||||
loginAsPrivilegedUser,
|
||||
loginAs,
|
||||
loginWithCustomRole,
|
||||
});
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ export { expect } from './expect';
|
|||
|
||||
export type { ScoutPlaywrightOptions, ScoutTestOptions } from './types';
|
||||
export type {
|
||||
BrowserAuthFixture,
|
||||
ScoutPage,
|
||||
// can be extended with solution specific fixtures
|
||||
ScoutTestFixtures,
|
||||
|
@ -37,5 +38,10 @@ export type {
|
|||
PageObjects,
|
||||
} from './fixtures';
|
||||
|
||||
// can be extended with solution specific logic
|
||||
export { browserAuthFixture } from './fixtures/test';
|
||||
|
||||
export type { SamlAuth } from './fixtures/worker';
|
||||
|
||||
// use to tag tests
|
||||
export { tags } from './tags';
|
||||
|
|
|
@ -1588,6 +1588,8 @@
|
|||
"@kbn/scout-oblt/*": ["x-pack/solutions/observability/packages/kbn-scout-oblt/*"],
|
||||
"@kbn/scout-reporting": ["src/platform/packages/private/kbn-scout-reporting"],
|
||||
"@kbn/scout-reporting/*": ["src/platform/packages/private/kbn-scout-reporting/*"],
|
||||
"@kbn/scout-security": ["x-pack/solutions/security/packages/kbn-scout-security"],
|
||||
"@kbn/scout-security/*": ["x-pack/solutions/security/packages/kbn-scout-security/*"],
|
||||
"@kbn/screenshot-mode-example-plugin": ["examples/screenshot_mode_example"],
|
||||
"@kbn/screenshot-mode-example-plugin/*": ["examples/screenshot_mode_example/*"],
|
||||
"@kbn/screenshot-mode-plugin": ["src/platform/plugins/shared/screenshot_mode"],
|
||||
|
|
201
x-pack/solutions/security/packages/kbn-scout-security/README.md
Normal file
201
x-pack/solutions/security/packages/kbn-scout-security/README.md
Normal file
|
@ -0,0 +1,201 @@
|
|||
# ⚠️ @kbn/scout-security IS NOT PRODUCTION READY, SO PLEASE DON'T USE YET
|
||||
|
||||
`kbn/scout-security` is a test library that extends [`kbn/scout`](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-scout/README.md) with test helpers specifically designed for `Security Solution` features in Kibana.
|
||||
|
||||
Its primary goal is to simplify the test development experience for teams working on `Security Solution` plugins by providing custom Playwright fixtures, page objects, and utilities tailored for Security Solution related testing scenarios.
|
||||
|
||||
### Table of Contents
|
||||
1. Overview
|
||||
2. Folder Structure
|
||||
3. Config
|
||||
4. Fixtures
|
||||
5. Page Objects
|
||||
6. Starting Servers Onlu
|
||||
7. Running Servers and Tests
|
||||
8. Running Tests Separately
|
||||
9. Adding A New Test
|
||||
10. Adding Page Objects
|
||||
11. Adding Fixtures
|
||||
12. Best Practices
|
||||
|
||||
|
||||
### Overview
|
||||
|
||||
`kbn-scout-security` extends from `kbn-scout` framework providing the same advantages:
|
||||
|
||||
- **Ease of integration:** a simplified mechanism to write and run tests closer to plugins.
|
||||
- **Deployment-agnostic tests:** enables the testing of Kibana features across different environments (e.g., Stateful, Serverless).
|
||||
- **Fixture-based design:** built on Playwright's fixture model to modularize and standardize test setup.
|
||||
- **Focus on Developer Productivity:** faster test execution and minimal boilerplate for writing tests.
|
||||
|
||||
### Folder Structure
|
||||
|
||||
The `@kbn/scout-security` structure includes the following key directories and files:
|
||||
|
||||
```
|
||||
x-pack/solutions/security/packages/kbn-scout-security/
|
||||
├── src/
|
||||
│ ├── playwright/
|
||||
│ │ └── constants/
|
||||
│ │ └── fixtures/
|
||||
│ │ │ └── test/
|
||||
│ │ │ │ └── // Security Solution test-scope fixtures
|
||||
| | | | └── page_objects/
|
||||
| | | | └── // Security Solution pages that can be reused through the different plugins
|
||||
│ │ │ └── worker/
|
||||
│ │ │ │ └── // Security Solution worker-scope fixtures
|
||||
│ │ │ └── single_thread_fixtures.ts
|
||||
│ │ │ └── parallel_run_fixtures.ts
|
||||
│ │ │ └── index.ts
|
||||
| | | └── types.ts
|
||||
│ └── index.ts
|
||||
├── README.mk
|
||||
├── index.ts
|
||||
├── jest.config.js
|
||||
├── kibana.jsonc
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
```
|
||||
|
||||
### Config
|
||||
|
||||
`playwright` directory manages the default Playwright configuration. It exports the `createPlaywrightConfig` function, which is used by Kibana plugins to define Scout playwright configurations and serves as the entry point to run tests.
|
||||
|
||||
```ts
|
||||
import { createPlaywrightConfig } from '@kbn/scout';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default createPlaywrightConfig({
|
||||
testDir: './tests',
|
||||
workers: 2,
|
||||
});
|
||||
```
|
||||
|
||||
Scout relies on configuration to determine the test files and opt-in [parallel test execution](https://playwright.dev/docs/test-parallel) against the single Elastic cluster.
|
||||
|
||||
The Playwright configuration should only be created this way to ensure compatibility with Scout functionality. Note that config files should be used inside the plugin we want to test.
|
||||
|
||||
### Fixtures
|
||||
|
||||
The `fixtures` directory contains core Security Scout capabilities required for testing the majority of Security Solution functionalities. [Fixtures](https://playwright.dev/docs/test-fixtures) can be scoped to either `test` or `worker`. Scope decides when to init a new fixture instance: once per worker or for every test function. It is important to choose the correct scope to keep test execution optimally fast: if **a new instance is not needed for every test**, the fixture should be scoped to **worker**. Otherwise, it should be scoped to **test**.
|
||||
|
||||
**Security Solution `worker` scoped fixtures:**
|
||||
- `detectionRuleApi`
|
||||
|
||||
```ts
|
||||
test.beforeAll(async ({ detectionRuleApi }) => {
|
||||
await detectionRuleApi.createCustomQueryRule(CUSTOM_QUERY_RULE);
|
||||
});
|
||||
```
|
||||
|
||||
**Security Solution `test` scoped fixtures:**
|
||||
- `browserAuth`
|
||||
- `pageObjects`
|
||||
|
||||
```ts
|
||||
test.beforeEach(async ({ browserAuth }) => {
|
||||
await browserAuth.loginAsPlatformEngineer();
|
||||
});
|
||||
```
|
||||
|
||||
If a new fixture depends on a fixture with a `test` scope, it must also be `test` scoped.
|
||||
|
||||
### Page Objects
|
||||
|
||||
The `page_objects` directory contains all the Page Objects that represent Security Solution core functionality that can be reused through different Security Solution plugins.
|
||||
|
||||
If a Page Object is likely to be used in more than one plugin, it should be added here. This allows other teams to reuse it, improving collaboration across teams, reducing code duplication, and simplifying support and adoption.
|
||||
|
||||
If a Page Object can be used outside Security Solution, it should be created in `@kbn-scout`.
|
||||
|
||||
Page Objects must be registered with the `createLazyPageObject` function, which guarantees its instance is lazy-initialized. This way, we can have all the page objects available in the test context, but only the ones that are called will be actually initialized:
|
||||
|
||||
```ts
|
||||
export function extendPageObjects(pageObjects: PageObjects, page: ScoutPage): SecurityPageObjects {
|
||||
return {
|
||||
...pageObjects,
|
||||
alertsTablePage: createLazyPageObject(AlertsTablePage, page),
|
||||
alertDetailsRightPanelPage: createLazyPageObject(AlertDetailsRightPanelPage, page),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
All registered Page Objects are available via the `pageObjects` fixture:
|
||||
|
||||
```ts
|
||||
test.beforeEach(async ({ pageObjects }) => {
|
||||
await pageObjects.alertsTablePage.navigate();
|
||||
});
|
||||
```
|
||||
|
||||
### Starting Servers Only
|
||||
|
||||
To start the servers without running tests, use the following command:
|
||||
|
||||
```bash
|
||||
node scripts/scout.js start-server [--stateful|--serverless=security]
|
||||
```
|
||||
|
||||
This is useful for manual testing or running tests via an IDE.
|
||||
|
||||
### Running Servers and Tests
|
||||
|
||||
To start the servers and run tests, use:
|
||||
|
||||
```bash
|
||||
node scripts/scout.js run-tests [--stateful|--serverless=security] --config <plugin-path>/ui_tests/[playwright.config.ts|parallel.playwright.config.ts]
|
||||
```
|
||||
|
||||
This command starts the required servers and then automatically executes the tests using Playwright.
|
||||
|
||||
### Running Tests Separately
|
||||
|
||||
If the servers are already running, you can execute tests independently using either:
|
||||
|
||||
- Playwright Plugin in IDE: Run tests directly within your IDE using Playwright's integration.
|
||||
- Command Line: Use the following command to run tests:
|
||||
|
||||
```bash
|
||||
npx playwright test --config <plugin-path>/ui_tests/[playwright.config.ts|parallel.playwright.config.ts] --project local
|
||||
```
|
||||
|
||||
We use `project` flag to define test target, where tests to be run: local servers or Elastic Cloud. Currently we only support local servers.
|
||||
|
||||
### Adding A New Test
|
||||
Any new test should be added in the `x-pack/solutions/security/plugins/security_solution/ui_tests` folder.
|
||||
|
||||
You have an example in: `x-pack/solutions/security/plugins/security_solution/ui_tests/parallel_tests/flyout/alert_details_url_sync.spec.ts`
|
||||
|
||||
### Adding Page Objects
|
||||
1. **Create a New Page Object:** Add your Page Object to the src/playwright/fixtures/test/page_objects directory. For instance:
|
||||
|
||||
```ts
|
||||
export class NewPage {
|
||||
constructor(private readonly page: ScoutPage) {}
|
||||
|
||||
// implementation
|
||||
}
|
||||
```
|
||||
2. **Register the Page Object:** Update the index file to include the new Page Object:
|
||||
```ts
|
||||
export function createCorePageObjects(page: ScoutPage): PageObjects {
|
||||
return {
|
||||
...
|
||||
newPage: createLazyPageObject(NewPage, page),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Adding Fixtures
|
||||
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`.
|
||||
|
||||
You can use the existing fixtures as a guide.
|
||||
|
||||
3. **Register the Fixture:** Add the fixture to the appropriate scope in `src/playwright/fixtures/parallel_run_fixtures.ts` and/or ``src/playwright/fixtures/single_thread_fixture.ts``
|
||||
|
||||
### 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.
|
||||
- **Adhere to Existing Structure:** Maintain consistency with the project's architecture.
|
||||
- **Playwright documentation:** [Official best practices](https://playwright.dev/docs/best-practices)
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { test, spaceTest } from './src/playwright';
|
||||
|
||||
// re-export from @kbn/scout
|
||||
export {
|
||||
expect,
|
||||
tags,
|
||||
createPlaywrightConfig,
|
||||
createLazyPageObject,
|
||||
globalSetupHook,
|
||||
} from '@kbn/scout';
|
||||
|
||||
export type {
|
||||
EsClient,
|
||||
KbnClient,
|
||||
KibanaUrl,
|
||||
ScoutLogger,
|
||||
ScoutPage,
|
||||
PageObjects,
|
||||
ScoutServerConfig,
|
||||
ScoutTestConfig,
|
||||
ScoutPlaywrightOptions,
|
||||
ScoutTestOptions,
|
||||
Locator,
|
||||
} from '@kbn/scout';
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
preset: '@kbn/test/jest_node',
|
||||
rootDir: '../../../../..',
|
||||
roots: ['<rootDir>/x-pack/solutions/security/packages/kbn-scout-security'],
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"type": "test-helper",
|
||||
"id": "@kbn/scout-security",
|
||||
"owner": "@elastic/appex-qa",
|
||||
"devOnly": true
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "@kbn/scout-security",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"license": "Elastic License 2.0"
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export const ES = {
|
||||
AUDITBEAT: 'x-pack/test/security_solution_cypress/es_archives/auditbeat_single',
|
||||
};
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export interface CustomQueryRule {
|
||||
index: string[];
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
description: string;
|
||||
risk_score: number;
|
||||
rule_id: string;
|
||||
severity: 'low' | 'medium' | 'high' | 'critical';
|
||||
type: 'query';
|
||||
query: string;
|
||||
from: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_SECURITY_SOLUTION_INDEXES = [
|
||||
'apm-*-transaction*',
|
||||
'auditbeat-*',
|
||||
'endgame-*',
|
||||
'filebeat-*',
|
||||
'logs-*',
|
||||
'packetbeat-*',
|
||||
'traces-apm*',
|
||||
'winlogbeat-*',
|
||||
'-*elastic-cloud-logs-*',
|
||||
];
|
||||
|
||||
export const CUSTOM_QUERY_RULE: CustomQueryRule = {
|
||||
index: DEFAULT_SECURITY_SOLUTION_INDEXES,
|
||||
enabled: true,
|
||||
name: 'Alert Testing Query',
|
||||
description: 'Tests a simple query',
|
||||
risk_score: 1,
|
||||
rule_id: 'rule-1',
|
||||
severity: 'high',
|
||||
type: 'query',
|
||||
query: '*:*',
|
||||
from: '2019-01-01T00:00:00.000Z',
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * as archives from './archives';
|
||||
export * as detection_rules from './detection_rules';
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { test } from './single_thread_fixtures';
|
||||
export { spaceTest } from './parallel_run_fixtures';
|
||||
export * from './types';
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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 { spaceTest as baseTest, mergeTests, ApiServicesFixture } from '@kbn/scout';
|
||||
import {
|
||||
SecurityApiServicesFixture,
|
||||
SecurityParallelTestFixtures,
|
||||
SecurityParallelWorkerFixtures,
|
||||
} from './types';
|
||||
import { getDetectionRuleApiService } from './worker';
|
||||
import { extendPageObjects, securityBrowserAuthFixture } from './test';
|
||||
|
||||
const securityParallelFixtures = mergeTests(baseTest, securityBrowserAuthFixture);
|
||||
|
||||
/**
|
||||
* Should be used test spec files, running in parallel in isolated spaces agaist the same Kibana instance.
|
||||
*/
|
||||
export const spaceTest = securityParallelFixtures.extend<
|
||||
SecurityParallelTestFixtures,
|
||||
SecurityParallelWorkerFixtures
|
||||
>({
|
||||
pageObjects: async (
|
||||
{
|
||||
pageObjects,
|
||||
page,
|
||||
}: {
|
||||
pageObjects: SecurityParallelTestFixtures['pageObjects'];
|
||||
page: SecurityParallelTestFixtures['page'];
|
||||
},
|
||||
use: (pageObjects: SecurityParallelTestFixtures['pageObjects']) => Promise<void>
|
||||
) => {
|
||||
const extendedPageObjects = extendPageObjects(pageObjects, page);
|
||||
await use(extendedPageObjects);
|
||||
},
|
||||
apiServices: [
|
||||
async (
|
||||
{
|
||||
apiServices,
|
||||
kbnClient,
|
||||
log,
|
||||
scoutSpace,
|
||||
}: {
|
||||
apiServices: ApiServicesFixture;
|
||||
kbnClient: SecurityParallelWorkerFixtures['kbnClient'];
|
||||
log: SecurityParallelWorkerFixtures['log'];
|
||||
scoutSpace: SecurityParallelWorkerFixtures['scoutSpace'];
|
||||
},
|
||||
use: (extendedApiServices: SecurityApiServicesFixture) => Promise<void>
|
||||
) => {
|
||||
const extendedApiServices = apiServices as SecurityApiServicesFixture;
|
||||
extendedApiServices.detectionRule = getDetectionRuleApiService({
|
||||
kbnClient,
|
||||
log,
|
||||
scoutSpace,
|
||||
});
|
||||
|
||||
await use(extendedApiServices);
|
||||
},
|
||||
{ scope: 'worker' },
|
||||
],
|
||||
});
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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 baseTest, mergeTests, ApiServicesFixture } from '@kbn/scout';
|
||||
import { SecurityApiServicesFixture, SecurityTestFixtures, SecurityWorkerFixtures } from './types';
|
||||
import { getDetectionRuleApiService } from './worker';
|
||||
import { extendPageObjects, securityBrowserAuthFixture } from './test';
|
||||
|
||||
const securityFixtures = mergeTests(baseTest, securityBrowserAuthFixture);
|
||||
|
||||
export const test = securityFixtures.extend<SecurityTestFixtures, SecurityWorkerFixtures>({
|
||||
pageObjects: async (
|
||||
{
|
||||
pageObjects,
|
||||
page,
|
||||
}: { pageObjects: SecurityTestFixtures['pageObjects']; page: SecurityTestFixtures['page'] },
|
||||
use: (pageObjects: SecurityTestFixtures['pageObjects']) => Promise<void>
|
||||
) => {
|
||||
const extendedPageObjects = extendPageObjects(pageObjects, page);
|
||||
await use(extendedPageObjects);
|
||||
},
|
||||
apiServices: [
|
||||
async (
|
||||
{
|
||||
apiServices,
|
||||
kbnClient,
|
||||
log,
|
||||
}: {
|
||||
apiServices: ApiServicesFixture;
|
||||
kbnClient: SecurityWorkerFixtures['kbnClient'];
|
||||
log: SecurityWorkerFixtures['log'];
|
||||
},
|
||||
use: (extendedApiServices: SecurityApiServicesFixture) => Promise<void>
|
||||
) => {
|
||||
const extendedApiServices = apiServices as SecurityApiServicesFixture;
|
||||
extendedApiServices.detectionRule = getDetectionRuleApiService({
|
||||
kbnClient,
|
||||
log,
|
||||
});
|
||||
|
||||
await use(extendedApiServices);
|
||||
},
|
||||
{ scope: 'worker' },
|
||||
],
|
||||
});
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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 { browserAuthFixture, mergeTests } from '@kbn/scout';
|
||||
import type {
|
||||
ElasticsearchRoleDescriptor,
|
||||
KibanaRole,
|
||||
ScoutTestConfig,
|
||||
BrowserAuthFixture,
|
||||
SamlAuth,
|
||||
ScoutLogger,
|
||||
EsClient,
|
||||
} from '@kbn/scout';
|
||||
import { roleDescriptorsFixture, RoleDescriptorsFixture } from '../../worker';
|
||||
|
||||
export interface SecurityBrowserAuthFixture extends BrowserAuthFixture {
|
||||
loginAsPlatformEngineer: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const securityBrowserAuthFixture = mergeTests(
|
||||
browserAuthFixture,
|
||||
roleDescriptorsFixture
|
||||
).extend<{
|
||||
browserAuth: SecurityBrowserAuthFixture;
|
||||
}>({
|
||||
browserAuth: async (
|
||||
{
|
||||
browserAuth,
|
||||
config,
|
||||
esClient,
|
||||
roleDescriptors,
|
||||
samlAuth,
|
||||
log,
|
||||
}: {
|
||||
browserAuth: BrowserAuthFixture;
|
||||
config: ScoutTestConfig;
|
||||
esClient: EsClient;
|
||||
roleDescriptors: RoleDescriptorsFixture;
|
||||
samlAuth: SamlAuth;
|
||||
log: ScoutLogger;
|
||||
},
|
||||
use: (extendedBrowserAuth: SecurityBrowserAuthFixture) => Promise<void>
|
||||
) => {
|
||||
let isCustomRoleCreated = false;
|
||||
|
||||
// explicitly overriding to update 'isCustomRoleCreated' flag and pass descriptor to the login method
|
||||
const loginWithCustomRole = async (role: KibanaRole | ElasticsearchRoleDescriptor) => {
|
||||
await samlAuth.setCustomRole(role);
|
||||
isCustomRoleCreated = true;
|
||||
return browserAuth.loginAs(samlAuth.customRoleName);
|
||||
};
|
||||
|
||||
const loginAsPlatformEngineer = async () => {
|
||||
const roleName = 'platform_engineer';
|
||||
if (!config.serverless) {
|
||||
const roleDesciptor = roleDescriptors.serverless?.get(
|
||||
roleName
|
||||
) as ElasticsearchRoleDescriptor;
|
||||
if (!roleDesciptor) {
|
||||
throw new Error(`No role descriptors found for ${roleName}`);
|
||||
}
|
||||
log.debug(`Using "${roleName}" role to execute the test`);
|
||||
return loginWithCustomRole(roleDesciptor);
|
||||
} else {
|
||||
return browserAuth.loginAs(roleName);
|
||||
}
|
||||
};
|
||||
|
||||
await use({
|
||||
...browserAuth,
|
||||
loginWithCustomRole,
|
||||
loginAsPlatformEngineer,
|
||||
});
|
||||
|
||||
if (isCustomRoleCreated) {
|
||||
log.debug(`Deleting custom role with name ${samlAuth.customRoleName}`);
|
||||
await esClient.security.deleteRole({ name: samlAuth.customRoleName });
|
||||
}
|
||||
},
|
||||
});
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { securityBrowserAuthFixture } from './browser_auth';
|
||||
export type { SecurityBrowserAuthFixture } from './browser_auth';
|
||||
|
||||
export { extendPageObjects } from './page_objects';
|
||||
export type { SecurityPageObjects } from './page_objects';
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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 { ScoutPage, Locator } from '@kbn/scout';
|
||||
|
||||
export class AlertDetailsRightPanelPage {
|
||||
public detailsFlyoutCloseIcon: Locator;
|
||||
public detailsFlyoutHeaderTitle: Locator;
|
||||
|
||||
constructor(private readonly page: ScoutPage) {
|
||||
this.detailsFlyoutHeaderTitle = this.page.testSubj.locator(
|
||||
'securitySolutionFlyoutAlertTitleText'
|
||||
);
|
||||
this.detailsFlyoutCloseIcon = this.page.testSubj.locator('euiFlyoutCloseButton');
|
||||
}
|
||||
|
||||
async closeFlyout() {
|
||||
await this.detailsFlyoutCloseIcon.click();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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 { ScoutPage, Locator } from '@kbn/scout';
|
||||
|
||||
const PAGE_URL = 'security/alerts';
|
||||
const EXPAND_EVENT = 'expand-event';
|
||||
|
||||
export class AlertsTablePage {
|
||||
public expandAlertBtn: Locator;
|
||||
|
||||
constructor(private readonly page: ScoutPage) {
|
||||
this.expandAlertBtn = this.page.testSubj.locator(EXPAND_EVENT);
|
||||
}
|
||||
|
||||
async navigate() {
|
||||
await this.page.gotoApp(PAGE_URL);
|
||||
}
|
||||
|
||||
async expandFirstAlertDetailsFlyout() {
|
||||
const maxAttempts = 100;
|
||||
let attempts = 0;
|
||||
|
||||
while ((await this.expandAlertBtn.count()) === 0) {
|
||||
if (attempts >= maxAttempts) {
|
||||
throw new Error('Timed out waiting for alert buttons to appear');
|
||||
}
|
||||
await this.page.waitForTimeout(100);
|
||||
attempts++;
|
||||
}
|
||||
const buttons = await this.expandAlertBtn.all();
|
||||
|
||||
if (buttons.length > 0) {
|
||||
await buttons[0].click();
|
||||
} else {
|
||||
throw new Error('No expand alert details buttons found');
|
||||
}
|
||||
}
|
||||
|
||||
async getCurrentUrl() {
|
||||
const url = this.page.url();
|
||||
return url;
|
||||
}
|
||||
|
||||
async reload() {
|
||||
return this.page.reload();
|
||||
}
|
||||
}
|
|
@ -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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { PageObjects, ScoutPage, createLazyPageObject } from '@kbn/scout';
|
||||
import { AlertsTablePage } from './alerts_table';
|
||||
import { AlertDetailsRightPanelPage } from './alert_details_right_panel';
|
||||
|
||||
export interface SecurityPageObjects extends PageObjects {
|
||||
alertsTablePage: AlertsTablePage;
|
||||
alertDetailsRightPanelPage: AlertDetailsRightPanelPage;
|
||||
}
|
||||
|
||||
export function extendPageObjects(pageObjects: PageObjects, page: ScoutPage): SecurityPageObjects {
|
||||
return {
|
||||
...pageObjects,
|
||||
alertsTablePage: createLazyPageObject(AlertsTablePage, page),
|
||||
alertDetailsRightPanelPage: createLazyPageObject(AlertDetailsRightPanelPage, page),
|
||||
};
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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 {
|
||||
ApiServicesFixture,
|
||||
ScoutParallelTestFixtures,
|
||||
ScoutParallelWorkerFixtures,
|
||||
ScoutTestFixtures,
|
||||
ScoutWorkerFixtures,
|
||||
} from '@kbn/scout';
|
||||
import { SecurityPageObjects, SecurityBrowserAuthFixture } from './test';
|
||||
import { DetectionRuleApiService } from './worker';
|
||||
|
||||
export interface SecurityApiServicesFixture extends ApiServicesFixture {
|
||||
detectionRule: DetectionRuleApiService;
|
||||
}
|
||||
|
||||
export interface SecurityTestFixtures extends ScoutTestFixtures {
|
||||
browserAuth: SecurityBrowserAuthFixture;
|
||||
pageObjects: SecurityPageObjects;
|
||||
}
|
||||
|
||||
export interface SecurityWorkerFixtures extends ScoutWorkerFixtures {
|
||||
apiServices: SecurityApiServicesFixture;
|
||||
}
|
||||
|
||||
export interface SecurityParallelTestFixtures extends ScoutParallelTestFixtures {
|
||||
browserAuth: SecurityBrowserAuthFixture;
|
||||
pageObjects: SecurityPageObjects;
|
||||
}
|
||||
|
||||
export interface SecurityParallelApiServicesFixture extends ApiServicesFixture {
|
||||
detectionRule: DetectionRuleApiService;
|
||||
}
|
||||
|
||||
export interface SecurityParallelWorkerFixtures extends ScoutParallelWorkerFixtures {
|
||||
apiServices: SecurityApiServicesFixture;
|
||||
}
|
|
@ -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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import {
|
||||
KbnClient,
|
||||
measurePerformanceAsync,
|
||||
ScoutLogger,
|
||||
ScoutParallelWorkerFixtures,
|
||||
} from '@kbn/scout';
|
||||
import { CUSTOM_QUERY_RULE, CustomQueryRule } from '../../../constants/detection_rules';
|
||||
|
||||
const DETECTION_ENGINE_RULES_URL = '/api/detection_engine/rules';
|
||||
const DETECTION_ENGINE_RULES_BULK_ACTION = '/api/detection_engine/rules/_bulk_action';
|
||||
|
||||
export interface DetectionRuleApiService {
|
||||
createCustomQueryRule: (body: CustomQueryRule) => Promise<void>;
|
||||
deleteAll: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const getDetectionRuleApiService = ({
|
||||
kbnClient,
|
||||
log,
|
||||
scoutSpace,
|
||||
}: {
|
||||
kbnClient: KbnClient;
|
||||
log: ScoutLogger;
|
||||
scoutSpace?: ScoutParallelWorkerFixtures['scoutSpace'];
|
||||
}): DetectionRuleApiService => {
|
||||
const basePath = scoutSpace?.id ? `/s/${scoutSpace?.id}` : '';
|
||||
|
||||
return {
|
||||
createCustomQueryRule: async (body = CUSTOM_QUERY_RULE) => {
|
||||
await measurePerformanceAsync(
|
||||
log,
|
||||
'security.detectionRule.createCustomQueryRule',
|
||||
async () => {
|
||||
await kbnClient.request({
|
||||
method: 'POST',
|
||||
path: `${basePath}${DETECTION_ENGINE_RULES_URL}`,
|
||||
body,
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
deleteAll: async () => {
|
||||
await measurePerformanceAsync(log, 'security.detectionRule.deleteAll', async () => {
|
||||
await kbnClient.request({
|
||||
method: 'POST',
|
||||
path: `${basePath}${DETECTION_ENGINE_RULES_BULK_ACTION}`,
|
||||
body: {
|
||||
query: '',
|
||||
action: 'delete',
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { getDetectionRuleApiService } from './detection_rule';
|
||||
export type { DetectionRuleApiService } from './detection_rule';
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { roleDescriptorsFixture } from './roles_descriptors';
|
||||
export type { RoleDescriptorsFixture } from './roles_descriptors';
|
||||
|
||||
export { getDetectionRuleApiService } from './apis';
|
||||
export type { DetectionRuleApiService } from './apis';
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 { readRolesDescriptorsFromResource, SERVERLESS_ROLES_ROOT_PATH } from '@kbn/es';
|
||||
import { ElasticsearchRoleDescriptor, ScoutLogger, playwrightTest as base } from '@kbn/scout';
|
||||
|
||||
export interface RoleDescriptorsFixture {
|
||||
serverless: Map<string, ElasticsearchRoleDescriptor>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixture that provides the role descriptors for the serverless prebuilt roles.
|
||||
* Using worker scope to avoid reading the file for each test.
|
||||
*/
|
||||
export const roleDescriptorsFixture = base.extend<
|
||||
{},
|
||||
{ roleDescriptors: RoleDescriptorsFixture; log: ScoutLogger }
|
||||
>({
|
||||
roleDescriptors: [
|
||||
({ log }, use) => {
|
||||
const resourcePath = `${SERVERLESS_ROLES_ROOT_PATH}/security/roles.yml`;
|
||||
const serverless = new Map<string, ElasticsearchRoleDescriptor>(
|
||||
Object.entries(
|
||||
readRolesDescriptorsFromResource(resourcePath) as Record<
|
||||
string,
|
||||
ElasticsearchRoleDescriptor
|
||||
>
|
||||
)
|
||||
);
|
||||
log.serviceLoaded('roleDescriptors');
|
||||
use({ serverless });
|
||||
},
|
||||
{ scope: 'worker' },
|
||||
],
|
||||
});
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './fixtures';
|
||||
export type { SecurityPageObjects } from './fixtures/test/page_objects';
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"extends": "../../../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "target/types",
|
||||
"types": [
|
||||
"jest",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
],
|
||||
"kbn_references": [
|
||||
"@kbn/scout",
|
||||
"@kbn/es",
|
||||
]
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
"public/**/*",
|
||||
"server/**/*",
|
||||
"scripts/**/*",
|
||||
"ui_tests/**/*",
|
||||
// have to declare *.json explicitly due to https://github.com/microsoft/TypeScript/issues/25636
|
||||
"common/**/*.json",
|
||||
"server/**/*.json",
|
||||
|
@ -242,6 +243,7 @@
|
|||
"@kbn/product-doc-base-plugin",
|
||||
"@kbn/shared-ux-error-boundary",
|
||||
"@kbn/security-ai-prompts",
|
||||
"@kbn/deeplinks-analytics"
|
||||
"@kbn/deeplinks-analytics",
|
||||
"@kbn/scout-security",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { createPlaywrightConfig } from '@kbn/scout-security';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default createPlaywrightConfig({
|
||||
testDir: './parallel_tests/',
|
||||
workers: 2,
|
||||
});
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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 { expect, spaceTest } from '@kbn/scout-security';
|
||||
import { CUSTOM_QUERY_RULE } from '@kbn/scout-security/src/playwright/constants/detection_rules';
|
||||
|
||||
const RIGHT = 'right';
|
||||
|
||||
spaceTest.describe('Expandable flyout state sync', { tag: ['@ess', '@svlSecurity '] }, () => {
|
||||
spaceTest.beforeEach(async ({ browserAuth, apiServices }) => {
|
||||
await apiServices.detectionRule.deleteAll();
|
||||
await apiServices.detectionRule.createCustomQueryRule(CUSTOM_QUERY_RULE);
|
||||
await browserAuth.loginAsPlatformEngineer();
|
||||
});
|
||||
|
||||
spaceTest('should test flyout url sync', async ({ pageObjects }) => {
|
||||
await pageObjects.alertsTablePage.navigate();
|
||||
|
||||
const urlBeforeAlertDetails = await pageObjects.alertsTablePage.getCurrentUrl();
|
||||
expect(urlBeforeAlertDetails).not.toContain(RIGHT);
|
||||
|
||||
await pageObjects.alertsTablePage.expandFirstAlertDetailsFlyout();
|
||||
|
||||
const urlAfterAlertDetails = await pageObjects.alertsTablePage.getCurrentUrl();
|
||||
expect(urlAfterAlertDetails).toContain(RIGHT);
|
||||
|
||||
const headerTitle = pageObjects.alertDetailsRightPanelPage.detailsFlyoutHeaderTitle;
|
||||
await expect(headerTitle).toHaveText(CUSTOM_QUERY_RULE.name);
|
||||
|
||||
await pageObjects.alertsTablePage.reload();
|
||||
|
||||
const urlAfterReload = await pageObjects.alertsTablePage.getCurrentUrl();
|
||||
expect(urlAfterReload).toContain(RIGHT);
|
||||
|
||||
await pageObjects.alertDetailsRightPanelPage.closeFlyout();
|
||||
|
||||
const urlAfterClosingFlyout = await pageObjects.alertsTablePage.getCurrentUrl();
|
||||
expect(urlAfterClosingFlyout).not.toContain(RIGHT);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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 { globalSetupHook } from '@kbn/scout-security';
|
||||
import { archives } from '@kbn/scout-security/src/playwright/constants';
|
||||
|
||||
globalSetupHook('Ingest archives to Elasticsearch', async ({ esArchiver, log }) => {
|
||||
const archivesToIngest = [archives.ES.AUDITBEAT];
|
||||
|
||||
log.debug('[setup] loading archives test data (only if indexes do not exist)...');
|
||||
for (const archive of archivesToIngest) {
|
||||
await esArchiver.loadIfNeeded(archive);
|
||||
}
|
||||
});
|
|
@ -6801,6 +6801,10 @@
|
|||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@kbn/scout-security@link:x-pack/solutions/security/packages/kbn-scout-security":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@kbn/scout@link:src/platform/packages/shared/kbn-scout":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue