From c188f73b853be16a3a7849c28fa29089fbe8da3e Mon Sep 17 00:00:00 2001
From: Mykola Harmash <mykola.harmash@elastic.co>
Date: Thu, 2 Jan 2025 14:45:36 +0100
Subject: [PATCH] Convert Cypress onboarding tests to Scout

---
 .../pipelines/pull_request/pipeline.ts        |  13 +-
 .github/CODEOWNERS                            |   1 -
 package.json                                  |   1 -
 tsconfig.base.json                            |   2 -
 .../observability_onboarding/e2e/README.md    |  51 --
 .../e2e/cypress.config.ts                     |  32 -
 .../e2e/cypress/e2e/home.cy.ts                |  36 -
 .../e2e/logs/custom_logs/configure.cy.ts      | 280 -------
 .../custom_logs/install_elastic_agent.cy.ts   | 494 -------------
 .../e2e/cypress/e2e/logs/feedback.cy.ts       |  23 -
 .../e2e/cypress/e2e/navigation.cy.ts          |  54 --
 .../e2e/cypress/support/commands.ts           | 182 -----
 .../e2e/cypress/support/types.d.ts            |  29 -
 .../e2e/cypress_test_runner.ts                |  92 ---
 .../e2e/ftr_config.ts                         |  58 --
 .../e2e/ftr_config_open.ts                    |  29 -
 .../e2e/ftr_config_runner.ts                  |  38 -
 .../e2e/ftr_kibana.yml                        |   1 -
 .../observability_onboarding/e2e/kibana.jsonc |   8 -
 .../e2e/tsconfig.json                         |  20 -
 .../observability_onboarding/tsconfig.json    |   6 +-
 .../ui_tests/README.md                        |  23 +
 .../ui_tests/fixtures/index.ts                |  50 ++
 .../fixtures/page_objects/custom_logs.ts      | 195 +++++
 .../fixtures/page_objects/index.ts}           |   6 +-
 .../fixtures/page_objects/onboarding_home.ts  |  16 +
 .../playwright.config.ts}                     |   7 +-
 .../tests/custom_logs/configuration.spec.ts   | 256 +++++++
 .../custom_logs/install_elastic_agent.spec.ts | 696 ++++++++++++++++++
 .../ui_tests/tsconfig.json                    |  15 +
 yarn.lock                                     |   4 -
 31 files changed, 1262 insertions(+), 1456 deletions(-)
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/README.md
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress.config.ts
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/home.cy.ts
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/logs/custom_logs/configure.cy.ts
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/logs/custom_logs/install_elastic_agent.cy.ts
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/logs/feedback.cy.ts
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/navigation.cy.ts
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/support/commands.ts
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/support/types.d.ts
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress_test_runner.ts
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_config.ts
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_config_open.ts
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_config_runner.ts
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_kibana.yml
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/kibana.jsonc
 delete mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/e2e/tsconfig.json
 create mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/README.md
 create mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/fixtures/index.ts
 create mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/fixtures/page_objects/custom_logs.ts
 rename x-pack/solutions/observability/plugins/observability_onboarding/{e2e/cypress/support/e2e.ts => ui_tests/fixtures/page_objects/index.ts} (72%)
 create mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/fixtures/page_objects/onboarding_home.ts
 rename x-pack/solutions/observability/plugins/observability_onboarding/{e2e/ftr_provider_context.d.ts => ui_tests/playwright.config.ts} (59%)
 create mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/tests/custom_logs/configuration.spec.ts
 create mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/tests/custom_logs/install_elastic_agent.spec.ts
 create mode 100644 x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/tsconfig.json

diff --git a/.buildkite/scripts/pipelines/pull_request/pipeline.ts b/.buildkite/scripts/pipelines/pull_request/pipeline.ts
index 272823dd84fe3..91b9a8b37075a 100644
--- a/.buildkite/scripts/pipelines/pull_request/pipeline.ts
+++ b/.buildkite/scripts/pipelines/pull_request/pipeline.ts
@@ -96,18 +96,6 @@ const getPipeline = (filename: string, removeSteps = true) => {
       pipeline.push(getPipeline('.buildkite/pipelines/pull_request/inventory_cypress.yml'));
     }
 
-    if (
-      (await doAnyChangesMatch([
-        /^x-pack\/solutions\/observability\/plugins\/observability_onboarding/,
-        /^x-pack\/platform\/plugins\/shared\/fleet/,
-      ])) ||
-      GITHUB_PR_LABELS.includes('ci:all-cypress-suites')
-    ) {
-      pipeline.push(
-        getPipeline('.buildkite/pipelines/pull_request/observability_onboarding_cypress.yml')
-      );
-    }
-
     if (
       (await doAnyChangesMatch([/^x-pack\/solutions\/observability\/plugins\/profiling/])) ||
       GITHUB_PR_LABELS.includes('ci:all-cypress-suites')
@@ -392,6 +380,7 @@ const getPipeline = (filename: string, removeSteps = true) => {
     if (
       (await doAnyChangesMatch([
         /^x-pack\/platform\/plugins\/private\/discover_enhanced\/ui_tests/,
+        /^x-pack\/solutions\/observability\/plugins\/observability_onboarding\/ui_tests/,
         /^packages\/kbn-scout/,
       ])) ||
       GITHUB_PR_LABELS.includes('ci:scout-ui-tests')
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 1eba14ec39735..321f14baf648d 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -935,7 +935,6 @@ x-pack/solutions/observability/plugins/observability_ai_assistant_app @elastic/o
 x-pack/solutions/observability/plugins/observability_ai_assistant_management @elastic/obs-ai-assistant
 x-pack/solutions/observability/plugins/observability_logs_explorer @elastic/obs-ux-logs-team
 x-pack/solutions/observability/plugins/observability_onboarding @elastic/obs-ux-logs-team
-x-pack/solutions/observability/plugins/observability_onboarding/e2e @elastic/obs-ux-logs-team
 x-pack/solutions/observability/plugins/observability_shared @elastic/observability-ui
 x-pack/solutions/observability/plugins/observability_solution/entities_data_access @elastic/obs-entities
 x-pack/solutions/observability/plugins/observability_solution/entity_manager_app @elastic/obs-entities
diff --git a/package.json b/package.json
index b42f080ba4a85..bf28f61eeff1e 100644
--- a/package.json
+++ b/package.json
@@ -1481,7 +1481,6 @@
     "@kbn/manifest": "link:packages/kbn-manifest",
     "@kbn/mock-idp-plugin": "link:packages/kbn-mock-idp-plugin",
     "@kbn/mock-idp-utils": "link:packages/kbn-mock-idp-utils",
-    "@kbn/observability-onboarding-e2e": "link:x-pack/solutions/observability/plugins/observability_onboarding/e2e",
     "@kbn/openapi-bundler": "link:packages/kbn-openapi-bundler",
     "@kbn/openapi-generator": "link:packages/kbn-openapi-generator",
     "@kbn/optimizer": "link:packages/kbn-optimizer",
diff --git a/tsconfig.base.json b/tsconfig.base.json
index ed28741173ce0..b9b4524cc9ec7 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -1342,8 +1342,6 @@
       "@kbn/observability-logs-explorer-plugin/*": ["x-pack/solutions/observability/plugins/observability_logs_explorer/*"],
       "@kbn/observability-logs-overview": ["x-pack/platform/packages/shared/observability/logs_overview"],
       "@kbn/observability-logs-overview/*": ["x-pack/platform/packages/shared/observability/logs_overview/*"],
-      "@kbn/observability-onboarding-e2e": ["x-pack/solutions/observability/plugins/observability_onboarding/e2e"],
-      "@kbn/observability-onboarding-e2e/*": ["x-pack/solutions/observability/plugins/observability_onboarding/e2e/*"],
       "@kbn/observability-onboarding-plugin": ["x-pack/solutions/observability/plugins/observability_onboarding"],
       "@kbn/observability-onboarding-plugin/*": ["x-pack/solutions/observability/plugins/observability_onboarding/*"],
       "@kbn/observability-plugin": ["x-pack/solutions/observability/plugins/observability"],
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/README.md b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/README.md
deleted file mode 100644
index 2c35d48fb5207..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/README.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# Observability onboarding E2E tests
-
-Observability onboarding uses [FTR](../../../../../packages/kbn-test/README.mdx) (functional test runner) and [Cypress](https://www.cypress.io/) to run the e2e tests. The tests are located at `kibana/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e`.
-
-## E2E Tests (Cypress)
-
-The E2E tests are located in [`x-pack/solutions/observability/plugins/observability_onboarding/e2e`](./cypress/e2e).
-
-Tests run on buildkite PR pipeline are parallelized (2 parallel jobs) and are orchestrated by the Cypress dashboard service. It can be configured in [.buildkite/pipelines/pull_request/observability_onboarding_cypress.yml](https://github.com/elastic/kibana/blob/main/.buildkite/pipelines/pull_request/observability_onboarding_cypress.yml) with the property `parallelism`.
-
-```yml
-    ...
-    depends_on: build
-    parallelism: 2
-    ...
-```
-
-## Running it locally
-
-### Start test server
-
-```
-node x-pack/solutions/observability/plugins/observability_onboarding/scripts/test/e2e --server
-```
-
-### Run tests
-Runs all tests in the terminal
-
-```
-node x-pack/solutions/observability/plugins/observability_onboarding/scripts/test/e2e --runner
-```
-
-### Open cypress dashboard
-Opens cypress dashboard, there it's possible to select what test you want to run.
-
-```
-node x-pack/solutions/observability/plugins/observability_onboarding/scripts/test/e2e --open
-```
-### Arguments
-
-| Option       | Description                                     |
-| ------------ | ----------------------------------------------- |
-| --server     | Only start ES and Kibana                        |
-| --runner     | Only run tests                                  |
-| --spec       | Specify the specs to run                        |
-| --times      | Repeat the test n number of times               |
-| --bail       | stop tests after the first failure              |
-
-```
-node x-pack/solutions/observability/plugins/observability_onboarding/scripts/test/e2e.js --runner --spec cypress/e2e/home.cy.ts --times 2
-```
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress.config.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress.config.ts
deleted file mode 100644
index afbad0bac67d0..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress.config.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { defineCypressConfig } from '@kbn/cypress-config';
-
-export default defineCypressConfig({
-  fileServerFolder: './cypress',
-  fixturesFolder: './cypress/fixtures',
-  screenshotsFolder: './cypress/screenshots',
-  videosFolder: './cypress/videos',
-  requestTimeout: 10000,
-  responseTimeout: 40000,
-  defaultCommandTimeout: 30000,
-  execTimeout: 120000,
-  pageLoadTimeout: 120000,
-  viewportHeight: 1800,
-  viewportWidth: 1440,
-  video: false,
-  screenshotOnRunFailure: false,
-  retries: {
-    runMode: 1,
-  },
-  e2e: {
-    baseUrl: 'http://localhost:5601',
-    supportFile: './cypress/support/e2e.ts',
-    specPattern: './cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',
-  },
-});
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/home.cy.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/home.cy.ts
deleted file mode 100644
index 27392c65e9dc7..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/home.cy.ts
+++ /dev/null
@@ -1,36 +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.
- */
-
-// Failing: See https://github.com/elastic/kibana/issues/183341
-describe.skip('[Observability onboarding] Landing page', () => {
-  beforeEach(() => {
-    cy.loginAsElastic();
-  });
-
-  describe('Entry point', () => {
-    it('when clicking on the logs card the user is navigated to the observability onboarding page', () => {
-      cy.getByTestSubj('guideButtonRedirect').click();
-      cy.getByTestSubj('guide-filter-observability').click();
-      cy.getByTestSubj('onboarding--observability--logs').click();
-
-      cy.url().should('include', '/app/observabilityOnboarding');
-    });
-
-    it('when clicking on observability overview callout the user is navigated to the observability onboarding page', () => {
-      cy.visitKibana('/app/observability');
-      cy.getByTestSubj('observability-onboarding-callout').should('exist');
-      cy.getByTestSubj('o11yObservabilityOnboardingGetStartedButton').click();
-
-      cy.url().should('include', '/app/observabilityOnboarding');
-    });
-  });
-
-  it('when user navigates to observability onboarding landing page is showed', () => {
-    cy.visitKibana('/app/observabilityOnboarding');
-    cy.contains('Onboard Observability data');
-  });
-});
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/logs/custom_logs/configure.cy.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/logs/custom_logs/configure.cy.ts
deleted file mode 100644
index 3a4ceba04f706..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/logs/custom_logs/configure.cy.ts
+++ /dev/null
@@ -1,280 +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.
- */
-
-describe('[Logs onboarding] Custom logs - configure step', () => {
-  describe('logFilePaths', () => {
-    beforeEach(() => {
-      cy.loginAsViewerUser();
-      cy.visitKibana('/app/observabilityOnboarding/customLogs');
-    });
-
-    describe('when user clicks on back button', () => {
-      beforeEach(() => {
-        cy.loginAsViewerUser();
-        cy.visitKibana('/app/observabilityOnboarding/customLogs');
-      });
-
-      it('navigates to observability logs onboarding page', () => {
-        cy.getByTestSubj('observabilityOnboardingFlowBackToSelectionButton').click();
-
-        cy.url().should('include', '/app/observabilityOnboarding');
-      });
-    });
-
-    it('Users shouldnt be able to continue if logFilePaths is empty', () => {
-      cy.getByTestSubj('obltOnboardingLogFilePath-0').find('input').should('not.have.text');
-      cy.getByTestSubj('obltOnboardingCustomLogsContinue').should('be.disabled');
-    });
-
-    it('Users should be able to continue if logFilePaths is not empty', () => {
-      cy.getByTestSubj('obltOnboardingLogFilePath-0').find('input').type('myLogs.log');
-      cy.getByTestSubj('obltOnboardingCustomLogsContinue').should('not.be.disabled');
-    });
-
-    it('Users can add multiple logFilePaths', () => {
-      cy.getByTestSubj('obltOnboardingCustomLogsAddFilePath').click();
-      cy.getByTestSubj('obltOnboardingLogFilePath-0').should('exist');
-      cy.getByTestSubj('obltOnboardingLogFilePath-1').should('exist');
-    });
-
-    it('Users can delete logFilePaths', () => {
-      cy.getByTestSubj('obltOnboardingCustomLogsAddFilePath').click();
-      cy.get('*[data-test-subj^="obltOnboardingLogFilePath-"]').should('have.length', 2);
-
-      cy.getByTestSubj('obltOnboardingLogFilePathDelete-1').click();
-      cy.get('*[data-test-subj^="obltOnboardingLogFilePath-"]').should('have.length', 1);
-    });
-
-    describe('when users fill logFilePaths', () => {
-      it('datasetname and integration name are auto generated if it is the first path', () => {
-        cy.getByTestSubj('obltOnboardingLogFilePath-0').find('input').type('myLogs.log');
-        cy.getByTestSubj('obltOnboardingCustomLogsIntegrationsName').should('have.value', 'mylogs');
-        cy.getByTestSubj('obltOnboardingCustomLogsDatasetName').should('have.value', 'mylogs');
-      });
-
-      it('datasetname and integration name are not generated if it is not the first path', () => {
-        cy.getByTestSubj('obltOnboardingCustomLogsAddFilePath').click();
-        cy.getByTestSubj('obltOnboardingLogFilePath-1').find('input').type('myLogs.log');
-        cy.getByTestSubj('obltOnboardingCustomLogsIntegrationsName').should('be.empty');
-        cy.getByTestSubj('obltOnboardingCustomLogsDatasetName').should('be.empty');
-      });
-    });
-  });
-
-  describe('serviceName', () => {
-    beforeEach(() => {
-      cy.loginAsViewerUser();
-      cy.visitKibana('/app/observabilityOnboarding/customLogs');
-
-      cy.getByTestSubj('obltOnboardingLogFilePath-0').find('input').type('myLogs.log');
-    });
-
-    it('should be optional allowing user to continue if it is empty', () => {
-      cy.getByTestSubj('obltOnboardingCustomLogsServiceName').should('not.have.text');
-      cy.getByTestSubj('obltOnboardingCustomLogsContinue').should('be.enabled');
-    });
-  });
-
-  describe('advancedSettings', () => {
-    beforeEach(() => {
-      cy.loginAsViewerUser();
-      cy.visitKibana('/app/observabilityOnboarding/customLogs');
-
-      cy.getByTestSubj('obltOnboardingLogFilePath-0').find('input').type('myLogs.log');
-    });
-
-    it('Users should expand the content when clicking it', () => {
-      cy.getByTestSubj('obltOnboardingCustomLogsAdvancedSettings').click();
-
-      cy.getByTestSubj('obltOnboardingCustomLogsNamespace').should('be.visible');
-      cy.getByTestSubj('obltOnboardingCustomLogsCustomConfig').should('be.visible');
-    });
-
-    it('Users should hide the content when clicking it', () => {
-      cy.getByTestSubj('obltOnboardingCustomLogsAdvancedSettings').click();
-
-      cy.getByTestSubj('obltOnboardingCustomLogsNamespace').should('not.be.visible');
-      cy.getByTestSubj('obltOnboardingCustomLogsCustomConfig').should('not.be.visible');
-    });
-
-    describe('Namespace', () => {
-      beforeEach(() => {
-        cy.getByTestSubj('obltOnboardingCustomLogsAdvancedSettings').click();
-      });
-
-      afterEach(() => {
-        cy.getByTestSubj('obltOnboardingCustomLogsAdvancedSettings').click();
-      });
-
-      it('Users should see a default namespace', () => {
-        cy.getByTestSubj('obltOnboardingCustomLogsNamespace').should('have.value', 'default');
-      });
-
-      it('Users should not be able to continue if they do not specify a namespace', () => {
-        cy.getByTestSubj('obltOnboardingCustomLogsNamespace').clear();
-
-        cy.getByTestSubj('obltOnboardingCustomLogsContinue').should('be.disabled');
-      });
-    });
-
-    describe('customConfig', () => {
-      beforeEach(() => {
-        cy.getByTestSubj('obltOnboardingCustomLogsAdvancedSettings').click();
-      });
-
-      afterEach(() => {
-        cy.getByTestSubj('obltOnboardingCustomLogsAdvancedSettings').click();
-      });
-
-      it('should be optional allowing user to continue if it is empty', () => {
-        cy.getByTestSubj('obltOnboardingCustomLogsCustomConfig').should('not.have.text');
-        cy.getByTestSubj('obltOnboardingCustomLogsContinue').should('be.enabled');
-      });
-    });
-  });
-
-  describe('integrationName', () => {
-    beforeEach(() => {
-      cy.loginAsViewerUser();
-      cy.visitKibana('/app/observabilityOnboarding/customLogs');
-
-      cy.getByTestSubj('obltOnboardingLogFilePath-0').find('input').type('myLogs.log');
-    });
-
-    it('Users should not be able to continue if they do not specify an integrationName', () => {
-      cy.getByTestSubj('obltOnboardingCustomLogsIntegrationsName').clear();
-
-      cy.getByTestSubj('obltOnboardingCustomLogsContinue').should('be.disabled');
-    });
-
-    it('value will contain _ instead of special chars', () => {
-      cy.getByTestSubj('obltOnboardingCustomLogsIntegrationsName').clear().type('hello$world');
-
-      cy.getByTestSubj('obltOnboardingCustomLogsIntegrationsName').should(
-        'have.value',
-        'hello_world'
-      );
-    });
-
-    it('value will be invalid if it is not lowercase', () => {
-      cy.getByTestSubj('obltOnboardingCustomLogsIntegrationsName').clear().type('H3llowOrld');
-
-      cy.contains('An integration name should be lowercase.');
-    });
-  });
-
-  describe('datasetName', () => {
-    beforeEach(() => {
-      cy.loginAsViewerUser();
-      cy.visitKibana('/app/observabilityOnboarding/customLogs');
-
-      cy.getByTestSubj('obltOnboardingLogFilePath-0').find('input').type('myLogs.log');
-    });
-
-    it('Users should not be able to continue if they do not specify a datasetName', () => {
-      cy.getByTestSubj('obltOnboardingCustomLogsDatasetName').clear();
-
-      cy.getByTestSubj('obltOnboardingCustomLogsContinue').should('be.disabled');
-    });
-
-    it('value will contain _ instead of special chars', () => {
-      cy.getByTestSubj('obltOnboardingCustomLogsDatasetName').clear().type('hello$world');
-
-      cy.getByTestSubj('obltOnboardingCustomLogsDatasetName').should('have.value', 'hello_world');
-    });
-
-    it('value will be invalid if it is not lowercase', () => {
-      cy.getByTestSubj('obltOnboardingCustomLogsDatasetName').clear().type('H3llowOrld');
-
-      cy.contains('A dataset name should be lowercase.');
-    });
-  });
-
-  describe('custom integration', () => {
-    const CUSTOM_INTEGRATION_NAME = 'mylogs';
-
-    beforeEach(() => {
-      cy.deleteIntegration(CUSTOM_INTEGRATION_NAME);
-    });
-
-    describe('when user is missing privileges', () => {
-      beforeEach(() => {
-        cy.loginAsViewerUser();
-        cy.visitKibana('/app/observabilityOnboarding/customLogs');
-
-        cy.getByTestSubj('obltOnboardingLogFilePath-0')
-          .find('input')
-          .type(`${CUSTOM_INTEGRATION_NAME}.log`);
-
-        cy.getByTestSubj('obltOnboardingCustomLogsContinue').click();
-      });
-
-      it('installation fails', () => {
-        cy.getByTestSubj('obltOnboardingCustomIntegrationErrorCallout').should('exist');
-      });
-    });
-
-    describe('when user has proper privileges', () => {
-      beforeEach(() => {
-        cy.loginAsEditorUser();
-        cy.visitKibana('/app/observabilityOnboarding/customLogs');
-
-        cy.getByTestSubj('obltOnboardingLogFilePath-0')
-          .find('input')
-          .type(`${CUSTOM_INTEGRATION_NAME}.log`);
-
-        cy.getByTestSubj('obltOnboardingCustomLogsContinue').click();
-      });
-
-      afterEach(() => {
-        cy.deleteIntegration(CUSTOM_INTEGRATION_NAME);
-      });
-
-      it('installation succeed and user is redirected install elastic agent step', () => {
-        cy.url().should('include', '/app/observabilityOnboarding/customLogs/installElasticAgent');
-      });
-    });
-
-    it('installation fails if integration already exists', () => {
-      cy.loginAsEditorUser();
-      cy.visitKibana('/app/observabilityOnboarding/customLogs');
-
-      cy.installCustomIntegration(CUSTOM_INTEGRATION_NAME);
-      cy.getByTestSubj('obltOnboardingLogFilePath-0')
-        .find('input')
-        .type(`${CUSTOM_INTEGRATION_NAME}.log`);
-      cy.getByTestSubj('obltOnboardingCustomLogsContinue').click();
-
-      cy.contains(
-        'Failed to create the integration as an installation with the name mylogs already exists.'
-      );
-    });
-
-    describe('when an error occurred on creation', () => {
-      before(() => {
-        cy.intercept('/api/fleet/epm/custom_integrations', {
-          statusCode: 500,
-          body: {
-            message: 'Internal error',
-          },
-        });
-
-        cy.loginAsEditorUser();
-        cy.visitKibana('/app/observabilityOnboarding/customLogs');
-
-        cy.getByTestSubj('obltOnboardingLogFilePath-0')
-          .find('input')
-          .type(`${CUSTOM_INTEGRATION_NAME}.log`);
-        cy.getByTestSubj('obltOnboardingCustomLogsContinue').click();
-      });
-
-      it('user should see the error displayed', () => {
-        cy.getByTestSubj('obltOnboardingCustomIntegrationErrorCallout').should('exist');
-      });
-    });
-  });
-});
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/logs/custom_logs/install_elastic_agent.cy.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/logs/custom_logs/install_elastic_agent.cy.ts
deleted file mode 100644
index 3b9248dc3c9e0..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/logs/custom_logs/install_elastic_agent.cy.ts
+++ /dev/null
@@ -1,494 +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.
- */
-
-describe('[Logs onboarding] Custom logs - install elastic agent', () => {
-  const CUSTOM_INTEGRATION_NAME = 'mylogs';
-
-  const configureCustomLogs = (loginFn = () => cy.loginAsLogMonitoringUser()) => {
-    loginFn();
-    cy.visitKibana('/app/observabilityOnboarding/customLogs');
-
-    cy.deleteIntegration(CUSTOM_INTEGRATION_NAME);
-
-    cy.getByTestSubj('obltOnboardingLogFilePath-0').find('input').type('mylogs.log');
-
-    cy.getByTestSubj('obltOnboardingCustomLogsContinue').click();
-  };
-
-  describe('custom integration', () => {
-    beforeEach(() => {
-      configureCustomLogs(() => cy.loginAsEditorUser());
-    });
-
-    it('Users should be able to see the custom integration success callout', () => {
-      cy.getByTestSubj('obltOnboardingCustomIntegrationInstalled').should('be.visible');
-    });
-  });
-
-  describe('ApiKey generation', () => {
-    describe('when user is missing privileges', () => {
-      beforeEach(() => {
-        configureCustomLogs(() => cy.loginAsEditorUser());
-      });
-
-      it('apiKey is not generated', () => {
-        cy.getByTestSubj('obltOnboardingLogsApiKeyCreationNoPrivileges').should('exist');
-      });
-    });
-
-    describe('when user has proper privileges', () => {
-      beforeEach(() => {
-        configureCustomLogs();
-      });
-
-      it('apiKey is generated', () => {
-        cy.getByTestSubj('obltOnboardingLogsApiKeyCreated').should('exist');
-      });
-    });
-
-    describe('when an error occurred on creation', () => {
-      before(() => {
-        cy.intercept('/internal/observability_onboarding/logs/flow', {
-          statusCode: 500,
-          body: {
-            message: 'Internal error',
-          },
-        });
-
-        configureCustomLogs();
-      });
-
-      it('apiKey is not generated', () => {
-        cy.getByTestSubj('obltOnboardingLogsApiKeyCreationFailed').should('exist');
-      });
-    });
-  });
-
-  describe('Install the Elastic Agent step', () => {
-    beforeEach(() => {
-      cy.intercept('POST', '/internal/observability_onboarding/logs/flow').as(
-        'createOnboardingFlow'
-      );
-      configureCustomLogs();
-    });
-
-    describe('When user select Linux OS', () => {
-      it('Auto download config to host is disabled by default', () => {
-        cy.get('.euiButtonGroup').contains('Linux').click();
-        cy.getByTestSubj('obltOnboardingInstallElasticAgentAutoDownloadConfig')
-          .should('be.enabled')
-          .should('not.be.checked');
-      });
-
-      it('Installation script is shown', () => {
-        cy.getByTestSubj('obltOnboardingInstallElasticAgentStep')
-          .get('.euiCodeBlock')
-          .should('exist');
-      });
-    });
-
-    describe('When user select Mac OS', () => {
-      beforeEach(() => {
-        cy.get('.euiButtonGroup').contains('MacOS').click();
-      });
-
-      it('Auto download config to host is disabled by default', () => {
-        cy.getByTestSubj('obltOnboardingInstallElasticAgentAutoDownloadConfig')
-          .should('be.enabled')
-          .should('not.be.checked');
-      });
-
-      it('Installation script is shown', () => {
-        cy.getByTestSubj('obltOnboardingInstallElasticAgentStep')
-          .get('.euiCodeBlock')
-          .should('exist');
-      });
-    });
-
-    describe('When user select Windows OS', () => {
-      beforeEach(() => {
-        cy.get('.euiButtonGroup').contains('Windows').click();
-      });
-
-      it('Auto download config to host is disabled by default', () => {
-        cy.getByTestSubj('obltOnboardingInstallElasticAgentAutoDownloadConfig')
-          .should('be.disabled')
-          .should('not.be.checked');
-      });
-
-      it('A link to the documentation is shown instead of installation script', () => {
-        cy.getByTestSubj('obltOnboardingInstallElasticAgentWindowsDocsLink').should('exist');
-
-        cy.getByTestSubj('obltOnboardingInstallElasticAgentStep')
-          .get('.euiCodeBlock')
-          .should('not.exist');
-      });
-    });
-
-    describe('When Auto download config', () => {
-      describe('is selected', () => {
-        it('autoDownloadConfig flag is added to installation script', () => {
-          cy.getByTestSubj('obltOnboardingInstallElasticAgentAutoDownloadConfig').click();
-          cy.getByTestSubj('obltOnboardingInstallElasticAgentAutoDownloadConfigCallout').should(
-            'exist'
-          );
-          cy.getByTestSubj('obltOnboardingInstallElasticAgentStep')
-            .get('.euiCodeBlock')
-            .should('contain', 'autoDownloadConfig=1');
-        });
-
-        it('Download config button is disabled', () => {
-          cy.getByTestSubj('obltOnboardingInstallElasticAgentAutoDownloadConfig').click();
-          cy.getByTestSubj('obltOnboardingConfigureElasticAgentStepDownloadConfig').should(
-            'be.disabled'
-          );
-        });
-      });
-
-      it('is not selected autoDownloadConfig flag is not added to installation script', () => {
-        cy.getByTestSubj('obltOnboardingInstallElasticAgentStep')
-          .get('.euiCodeBlock')
-          .should('not.contain', 'autoDownloadConfig=1');
-      });
-    });
-
-    describe('When user executes the installation script in the host', () => {
-      let onboardingId: string;
-
-      describe('updates on steps are shown in the flow', () => {
-        beforeEach(() => {
-          cy.wait('@createOnboardingFlow')
-            .its('response.body')
-            .then((body) => {
-              onboardingId = body.onboardingId;
-            });
-        });
-
-        describe('Download elastic Agent step', () => {
-          it('shows a loading callout when elastic agent is downloading', () => {
-            cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'loading');
-            cy.getByTestSubj('obltOnboardingStepStatus-loading')
-              .contains('Downloading Elastic Agent')
-              .should('exist');
-          });
-
-          it('shows a success callout when elastic agent is downloaded', () => {
-            cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete');
-            cy.getByTestSubj('obltOnboardingStepStatus-complete')
-              .contains('Elastic Agent downloaded')
-              .should('exist');
-          });
-
-          it('shows a danger callout when elastic agent was not downloaded', () => {
-            cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'danger');
-            cy.getByTestSubj('obltOnboardingStepStatus-danger')
-              .contains('Download Elastic Agent')
-              .should('exist');
-          });
-        });
-
-        describe('Extract elastic Agent step', () => {
-          beforeEach(() => {
-            cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete');
-          });
-
-          it('shows a loading callout when elastic agent is extracting', () => {
-            cy.updateInstallationStepStatus(onboardingId, 'ea-extract', 'loading');
-            cy.getByTestSubj('obltOnboardingStepStatus-loading')
-              .contains('Extracting Elastic Agent')
-              .should('exist');
-          });
-
-          it('shows a success callout when elastic agent is extracted', () => {
-            cy.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete');
-            cy.getByTestSubj('obltOnboardingStepStatus-complete')
-              .contains('Elastic Agent extracted')
-              .should('exist');
-          });
-
-          it('shows a danger callout when elastic agent was not extracted', () => {
-            cy.updateInstallationStepStatus(onboardingId, 'ea-extract', 'danger');
-            cy.getByTestSubj('obltOnboardingStepStatus-danger')
-              .contains('Extract Elastic Agent')
-              .should('exist');
-          });
-        });
-
-        describe('Install elastic Agent step', () => {
-          beforeEach(() => {
-            cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete');
-            cy.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete');
-          });
-
-          it('shows a loading callout when elastic agent is installing', () => {
-            cy.updateInstallationStepStatus(onboardingId, 'ea-install', 'loading');
-            cy.getByTestSubj('obltOnboardingStepStatus-loading')
-              .contains('Installing Elastic Agent')
-              .should('exist');
-          });
-
-          it('shows a success callout when elastic agent is installed', () => {
-            cy.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete');
-            cy.getByTestSubj('obltOnboardingStepStatus-complete')
-              .contains('Elastic Agent installed')
-              .should('exist');
-          });
-
-          it('shows a danger callout when elastic agent was not installed', () => {
-            cy.updateInstallationStepStatus(onboardingId, 'ea-install', 'danger');
-            cy.getByTestSubj('obltOnboardingStepStatus-danger')
-              .contains('Install Elastic Agent')
-              .should('exist');
-          });
-        });
-
-        describe('Check elastic Agent status step', () => {
-          beforeEach(() => {
-            cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete');
-            cy.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete');
-            cy.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete');
-          });
-
-          it('shows a loading callout when getting elastic agent status', () => {
-            cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'loading');
-            cy.getByTestSubj('obltOnboardingStepStatus-loading')
-              .contains('Connecting to the Elastic Agent')
-              .should('exist');
-          });
-
-          it('shows a success callout when elastic agent status is healthy', () => {
-            cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', {
-              agentId: 'test-agent-id',
-            });
-            cy.getByTestSubj('obltOnboardingStepStatus-complete')
-              .contains('Connected to the Elastic Agent')
-              .should('exist');
-          });
-
-          it('shows a warning callout when elastic agent status is not healthy', () => {
-            cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'warning');
-            cy.getByTestSubj('obltOnboardingStepStatus-warning')
-              .contains('Connect to the Elastic Agent')
-              .should('exist');
-          });
-        });
-      });
-    });
-  });
-
-  describe('Configure Elastic Agent step', () => {
-    let onboardingId: string;
-
-    beforeEach(() => {
-      cy.intercept('POST', '/internal/observability_onboarding/logs/flow').as(
-        'createOnboardingFlow'
-      );
-      configureCustomLogs();
-      cy.wait('@createOnboardingFlow')
-        .its('response.body')
-        .then((body) => {
-          onboardingId = body.onboardingId;
-        });
-    });
-
-    describe('When user select Linux OS', () => {
-      beforeEach(() => {
-        cy.getByTestSubj('obltOnboardingInstallElasticAgentAutoDownloadConfig').click();
-        cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete');
-        cy.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete');
-        cy.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete');
-        cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', {
-          agentId: 'test-agent-id',
-        });
-      });
-
-      it('shows loading callout when config is being downloaded to the host', () => {
-        cy.updateInstallationStepStatus(onboardingId, 'ea-config', 'loading');
-        cy.get(
-          '[data-test-subj="obltOnboardingConfigureElasticAgentStep"] .euiStep__titleWrapper [class$="euiStepNumber-s-loading"]'
-        ).should('exist');
-        cy.getByTestSubj('obltOnboardingStepStatus-loading')
-          .contains('Downloading Elastic Agent config')
-          .should('exist');
-      });
-
-      it('shows success callout when the configuration has been written to the host', () => {
-        cy.updateInstallationStepStatus(onboardingId, 'ea-config', 'complete');
-        cy.get(
-          '[data-test-subj="obltOnboardingConfigureElasticAgentStep"] .euiStep__titleWrapper [class$="euiStepNumber-s-complete"]'
-        ).should('exist');
-        cy.getByTestSubj('obltOnboardingStepStatus-complete')
-          .contains('Elastic Agent config written to /opt/Elastic/Agent/elastic-agent.yml')
-          .should('exist');
-      });
-
-      it('shows warning callout when the configuration was not written in the host', () => {
-        cy.updateInstallationStepStatus(onboardingId, 'ea-config', 'warning');
-        cy.get(
-          '[data-test-subj="obltOnboardingConfigureElasticAgentStep"] .euiStep__titleWrapper [class$="euiStepNumber-s-warning"]'
-        ).should('exist');
-        cy.getByTestSubj('obltOnboardingStepStatus-warning')
-          .contains('Configure the agent')
-          .should('exist');
-      });
-    });
-
-    describe('When user select Mac OS', () => {
-      beforeEach(() => {
-        cy.get('.euiButtonGroup').contains('MacOS').click();
-        cy.getByTestSubj('obltOnboardingInstallElasticAgentAutoDownloadConfig').click();
-        cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete');
-        cy.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete');
-        cy.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete');
-        cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', {
-          agentId: 'test-agent-id',
-        });
-      });
-
-      it('shows loading callout when config is being downloaded to the host', () => {
-        cy.updateInstallationStepStatus(onboardingId, 'ea-config', 'loading');
-        cy.get(
-          '[data-test-subj="obltOnboardingConfigureElasticAgentStep"] .euiStep__titleWrapper [class$="euiStepNumber-s-loading"]'
-        ).should('exist');
-        cy.getByTestSubj('obltOnboardingStepStatus-loading')
-          .contains('Downloading Elastic Agent config')
-          .should('exist');
-      });
-
-      it('shows success callout when the configuration has been written to the host', () => {
-        cy.updateInstallationStepStatus(onboardingId, 'ea-config', 'complete');
-        cy.get(
-          '[data-test-subj="obltOnboardingConfigureElasticAgentStep"] .euiStep__titleWrapper [class$="euiStepNumber-s-complete"]'
-        ).should('exist');
-        cy.getByTestSubj('obltOnboardingStepStatus-complete')
-          .contains('Elastic Agent config written to /Library/Elastic/Agent/elastic-agent.yml')
-          .should('exist');
-      });
-
-      it('shows warning callout when the configuration was not written in the host', () => {
-        cy.updateInstallationStepStatus(onboardingId, 'ea-config', 'warning');
-        cy.get(
-          '[data-test-subj="obltOnboardingConfigureElasticAgentStep"] .euiStep__titleWrapper [class$="euiStepNumber-s-warning"]'
-        ).should('exist');
-        cy.getByTestSubj('obltOnboardingStepStatus-warning')
-          .contains('Configure the agent')
-          .should('exist');
-      });
-    });
-
-    describe('When user select Windows', () => {
-      beforeEach(() => {
-        cy.get('.euiButtonGroup').contains('Windows').click();
-      });
-
-      it('step is disabled', () => {
-        cy.get(
-          '[data-test-subj="obltOnboardingConfigureElasticAgentStep"] .euiStep__titleWrapper [class$="euiStepNumber-s-disabled"]'
-        ).should('exist');
-      });
-    });
-  });
-
-  describe('Check logs step', () => {
-    let onboardingId: string;
-
-    beforeEach(() => {
-      cy.intercept('POST', '/internal/observability_onboarding/logs/flow').as(
-        'createOnboardingFlow'
-      );
-      configureCustomLogs();
-      cy.wait('@createOnboardingFlow')
-        .its('response.body')
-        .then((body) => {
-          onboardingId = body.onboardingId;
-        });
-    });
-
-    describe('When user select Linux OS or MacOS', () => {
-      describe('When configure Elastic Agent step is not finished', () => {
-        beforeEach(() => {
-          cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete');
-          cy.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete');
-          cy.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete');
-          cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'loading');
-        });
-
-        it('check logs is not triggered', () => {
-          cy.get(
-            '[data-test-subj="obltOnboardingCheckLogsStep"] .euiStep__titleWrapper [class$="euiStepNumber-s-incomplete"]'
-          ).should('exist');
-          cy.get('.euiStep__title').contains('Ship logs to Elastic Observability').should('exist');
-        });
-      });
-
-      describe('When configure Elastic Agent step has finished', () => {
-        beforeEach(() => {
-          cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete');
-          cy.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete');
-          cy.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete');
-          cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', {
-            agentId: 'test-agent-id',
-          });
-          cy.updateInstallationStepStatus(onboardingId, 'ea-config', 'complete');
-        });
-
-        it('shows loading callout when logs are being checked', () => {
-          cy.get(
-            '[data-test-subj="obltOnboardingCheckLogsStep"] .euiStep__titleWrapper [class$="euiStepNumber-s-loading"]'
-          ).should('exist');
-          cy.get('.euiStep__title').contains('Waiting for logs to be shipped...').should('exist');
-        });
-      });
-    });
-
-    describe('When user select Windows', () => {
-      beforeEach(() => {
-        cy.get('.euiButtonGroup').contains('Windows').click();
-      });
-
-      it('step is disabled', () => {
-        cy.get(
-          '[data-test-subj="obltOnboardingCheckLogsStep"] .euiStep__titleWrapper [class$="euiStepNumber-s-disabled"]'
-        ).should('exist');
-      });
-    });
-  });
-
-  describe('When logs are being shipped', () => {
-    beforeEach(() => {
-      cy.intercept('GET', '**/progress', {
-        status: 200,
-        body: {
-          progress: {
-            'ea-download': { status: 'complete' },
-            'ea-extract': { status: 'complete' },
-            'ea-install': { status: 'complete' },
-            'ea-status': { status: 'complete' },
-            'ea-config': { status: 'complete' },
-            'logs-ingest': { status: 'complete' },
-          },
-        },
-      }).as('checkOnboardingProgress');
-      configureCustomLogs();
-    });
-
-    it('shows success callout when logs has arrived to elastic', () => {
-      cy.wait('@checkOnboardingProgress');
-      cy.get(
-        '[data-test-subj="obltOnboardingCheckLogsStep"] .euiStep__titleWrapper [class$="euiStepNumber-s-complete"]'
-      ).should('exist');
-      cy.get('.euiStep__title').contains('Logs are being shipped!').should('exist');
-    });
-
-    it('when user clicks on Explore Logs it navigates to observability logs explorer', () => {
-      cy.wait('@checkOnboardingProgress');
-      cy.getByTestSubj('obltOnboardingExploreLogs').should('exist').click();
-
-      cy.url().should('include', '/app/discover');
-    });
-  });
-});
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/logs/feedback.cy.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/logs/feedback.cy.ts
deleted file mode 100644
index 542ca6ac80222..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/logs/feedback.cy.ts
+++ /dev/null
@@ -1,23 +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.
- */
-
-// Failing: See https://github.com/elastic/kibana/issues/183341
-describe.skip('[Logs onboarding] Give Feedback', () => {
-  beforeEach(() => {
-    cy.loginAsElastic();
-    cy.visitKibana('/app/observabilityOnboarding');
-  });
-
-  it('feedback button is present in custom logs onboarding', () => {
-    cy.getByTestSubj('obltOnboardingHomeStartLogFileStream').click();
-    cy.getByTestSubj('observabilityOnboardingPageGiveFeedback').should('exist');
-  });
-
-  it('feedback button is not present in the landing page', () => {
-    cy.getByTestSubj('observabilityOnboardingPageGiveFeedback').should('not.exist');
-  });
-});
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/navigation.cy.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/navigation.cy.ts
deleted file mode 100644
index ebaa607179791..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/e2e/navigation.cy.ts
+++ /dev/null
@@ -1,54 +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.
- */
-
-// Failing: See https://github.com/elastic/kibana/issues/183341
-describe.skip('[Observability onboarding] Navigation', () => {
-  beforeEach(() => {
-    cy.loginAsElastic();
-    cy.visitKibana('/app/observabilityOnboarding/');
-  });
-
-  describe('When user clicks on the card', () => {
-    it('navigates to custom logs onboarding', () => {
-      cy.getByTestSubj('obltOnboardingHomeStartLogFileStream').click();
-
-      cy.url().should('include', '/app/observabilityOnboarding/customLogs');
-    });
-
-    it('navigates to apm tutorial', () => {
-      cy.getByTestSubj('obltOnboardingHomeStartApmTutorial').click();
-
-      cy.url().should('include', '/app/home#/tutorial/apm');
-    });
-
-    it('navigates to kubernetes integration', () => {
-      cy.getByTestSubj('obltOnboardingHomeGoToKubernetesIntegration').click();
-
-      cy.url().should('include', '/app/integrations/detail/kubernetes/overview');
-    });
-
-    it('navigates to integrations', () => {
-      cy.getByTestSubj('obltOnboardingHomeExploreIntegrations').click();
-
-      cy.url().should('include', '/app/integrations/browse');
-    });
-  });
-
-  describe('When user clicks on Quick links', () => {
-    it('navigates to use sample data', () => {
-      cy.getByTestSubj('obltOnboardingHomeUseSampleData').click();
-
-      cy.url().should('include', '/app/home#/tutorial_directory/sampleData');
-    });
-
-    it('navigates to upload a file', () => {
-      cy.getByTestSubj('obltOnboardingHomeUploadAFile').click();
-
-      cy.url().should('include', '/app/home#/tutorial_directory/fileDataViz');
-    });
-  });
-});
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/support/commands.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/support/commands.ts
deleted file mode 100644
index dd07f4dc3dd4a..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/support/commands.ts
+++ /dev/null
@@ -1,182 +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 URL from 'url';
-import { ObservabilityOnboardingUsername } from '@kbn/observability-onboarding-plugin/server/test_helpers/create_observability_onboarding_users/authentication';
-
-export type InstallationStep =
-  | 'ea-download'
-  | 'ea-extract'
-  | 'ea-install'
-  | 'ea-status'
-  | 'ea-config';
-
-export type InstallationStepStatus =
-  | 'incomplete'
-  | 'complete'
-  | 'disabled'
-  | 'loading'
-  | 'warning'
-  | 'danger'
-  | 'current';
-
-export interface ElasticAgentStepPayload {
-  agentId: string;
-}
-
-Cypress.Commands.add('loginAsViewerUser', () => {
-  return cy.loginAs({
-    username: ObservabilityOnboardingUsername.viewerUser,
-    password: 'changeme',
-  });
-});
-
-Cypress.Commands.add('loginAsEditorUser', () => {
-  return cy.loginAs({
-    username: ObservabilityOnboardingUsername.editorUser,
-    password: 'changeme',
-  });
-});
-
-Cypress.Commands.add('loginAsLogMonitoringUser', () => {
-  return cy.loginAs({
-    username: ObservabilityOnboardingUsername.logMonitoringUser,
-    password: 'changeme',
-  });
-});
-
-Cypress.Commands.add('loginAsElastic', () => {
-  return cy.loginAs({
-    username: 'elastic',
-    password: 'changeme',
-  });
-});
-
-Cypress.Commands.add(
-  'loginAs',
-  ({ username, password }: { username: string; password: string }) => {
-    const kibanaUrl = Cypress.env('KIBANA_URL');
-    cy.log(`Logging in as ${username} on ${kibanaUrl}`);
-    cy.visit('/');
-    cy.request({
-      log: true,
-      method: 'POST',
-      url: `${kibanaUrl}/internal/security/login`,
-      body: {
-        providerType: 'basic',
-        providerName: 'basic',
-        currentURL: `${kibanaUrl}/login`,
-        params: { username, password },
-      },
-      headers: {
-        'kbn-xsrf': 'e2e_test',
-      },
-    });
-    cy.visit('/');
-  }
-);
-
-Cypress.Commands.add('getByTestSubj', (selector: string) => {
-  return cy.get(`[data-test-subj="${selector}"]`);
-});
-
-Cypress.Commands.add('visitKibana', (url: string, rangeFrom?: string, rangeTo?: string) => {
-  const urlPath = URL.format({
-    pathname: url,
-    query: { rangeFrom, rangeTo },
-  });
-
-  cy.visit(urlPath);
-  cy.getByTestSubj('kbnLoadingMessage').should('exist');
-  cy.getByTestSubj('kbnLoadingMessage').should('not.exist', {
-    timeout: 50000,
-  });
-});
-
-Cypress.Commands.add('installCustomIntegration', (integrationName: string) => {
-  const kibanaUrl = Cypress.env('KIBANA_URL');
-
-  cy.request({
-    log: false,
-    method: 'POST',
-    url: `${kibanaUrl}/api/fleet/epm/custom_integrations`,
-    body: {
-      force: true,
-      integrationName,
-      datasets: [
-        { name: `${integrationName}.access`, type: 'logs' },
-        { name: `${integrationName}.error`, type: 'metrics' },
-        { name: `${integrationName}.warning`, type: 'logs' },
-      ],
-    },
-    headers: {
-      'kbn-xsrf': 'e2e_test',
-      'Elastic-Api-Version': '2023-10-31',
-    },
-    auth: { user: 'editor', pass: 'changeme' },
-  });
-});
-
-Cypress.Commands.add('deleteIntegration', (integrationName: string) => {
-  const kibanaUrl = Cypress.env('KIBANA_URL');
-
-  cy.request({
-    log: false,
-    method: 'GET',
-    url: `${kibanaUrl}/api/fleet/epm/packages/${integrationName}`,
-    headers: {
-      'kbn-xsrf': 'e2e_test',
-    },
-    auth: { user: 'editor', pass: 'changeme' },
-    failOnStatusCode: false,
-  }).then((response) => {
-    const status = response.body.item?.status;
-    if (status === 'installed') {
-      cy.request({
-        log: false,
-        method: 'DELETE',
-        url: `${kibanaUrl}/api/fleet/epm/packages/${integrationName}`,
-        body: {
-          force: false,
-        },
-        headers: {
-          'kbn-xsrf': 'e2e_test',
-          'Elastic-Api-Version': '2023-10-31',
-        },
-        auth: { user: 'editor', pass: 'changeme' },
-      });
-    }
-  });
-});
-
-Cypress.Commands.add(
-  'updateInstallationStepStatus',
-  (
-    onboardingId: string,
-    step: InstallationStep,
-    status: InstallationStepStatus,
-    payload: ElasticAgentStepPayload | undefined
-  ) => {
-    const kibanaUrl = Cypress.env('KIBANA_URL');
-
-    cy.log(onboardingId, step, status);
-
-    cy.request({
-      log: false,
-      method: 'POST',
-      url: `${kibanaUrl}/internal/observability_onboarding/flow/${onboardingId}/step/${step}`,
-      headers: {
-        'kbn-xsrf': 'e2e_test',
-      },
-      auth: { user: 'editor', pass: 'changeme' },
-      body: {
-        status,
-        payload,
-      },
-    });
-  }
-);
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/support/types.d.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/support/types.d.ts
deleted file mode 100644
index 7bb3549a60e7c..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/support/types.d.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-declare namespace Cypress {
-  interface Chainable {
-    loginAs(params: {
-      username: string;
-      password: string;
-    }): Cypress.Chainable<Cypress.Response<any>>;
-    loginAsViewerUser(): Cypress.Chainable<Cypress.Response<any>>;
-    loginAsEditorUser(): Cypress.Chainable<Cypress.Response<any>>;
-    loginAsLogMonitoringUser(): Cypress.Chainable<Cypress.Response<any>>;
-    loginAsElastic(): Cypress.Chainable<Cypress.Response<any>>;
-    getByTestSubj(selector: string): Chainable<JQuery<Element>>;
-    visitKibana(url: string, rangeFrom?: string, rangeTo?: string): void;
-    installCustomIntegration(integrationName: string): void;
-    deleteIntegration(integrationName: string): void;
-    updateInstallationStepStatus(
-      onboardingId: string,
-      step: InstallationStep,
-      status: InstallationStepStatus,
-      payload?: ElasticAgentStepPayload
-    ): void;
-  }
-}
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress_test_runner.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress_test_runner.ts
deleted file mode 100644
index 4a8326d81b246..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress_test_runner.ts
+++ /dev/null
@@ -1,92 +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 cypress from 'cypress';
-import path from 'path';
-import Url from 'url';
-import { createObservabilityOnboardingUsers } from '@kbn/observability-onboarding-plugin/server/test_helpers/create_observability_onboarding_users';
-import { FtrProviderContext } from './ftr_provider_context';
-
-export async function cypressTestRunner({
-  ftrProviderContext: { getService },
-  cypressExecution,
-}: {
-  ftrProviderContext: FtrProviderContext;
-  cypressExecution: typeof cypress.run | typeof cypress.open;
-}) {
-  const config = getService('config');
-
-  const username = config.get('servers.elasticsearch.username');
-  const password = config.get('servers.elasticsearch.password');
-
-  const kibanaUrl = Url.format({
-    protocol: config.get('servers.kibana.protocol'),
-    hostname: config.get('servers.kibana.hostname'),
-    port: config.get('servers.kibana.port'),
-    auth: `${username}:${password}`,
-  });
-
-  const esNode = Url.format({
-    protocol: config.get('servers.elasticsearch.protocol'),
-    port: config.get('servers.elasticsearch.port'),
-    hostname: config.get('servers.elasticsearch.hostname'),
-    auth: `${username}:${password}`,
-  });
-
-  // Creates ObservabilityOnboarding users
-  await createObservabilityOnboardingUsers({
-    elasticsearch: { node: esNode, username, password },
-    kibana: { hostname: kibanaUrl },
-  });
-
-  const esRequestTimeout = config.get('timeouts.esRequestTimeout');
-
-  const kibanaUrlWithoutAuth = Url.format({
-    protocol: config.get('servers.kibana.protocol'),
-    hostname: config.get('servers.kibana.hostname'),
-    port: config.get('servers.kibana.port'),
-  });
-
-  const cypressProjectPath = path.join(__dirname);
-  const { open, ...cypressCliArgs } = getCypressCliArgs();
-
-  const res = await cypressExecution({
-    ...cypressCliArgs,
-    project: cypressProjectPath,
-    config: {
-      e2e: {
-        baseUrl: kibanaUrlWithoutAuth,
-      },
-    },
-    env: {
-      KIBANA_URL: kibanaUrlWithoutAuth,
-      ES_NODE: esNode,
-      ES_REQUEST_TIMEOUT: esRequestTimeout,
-      TEST_CLOUD: process.env.TEST_CLOUD,
-    },
-  });
-
-  return res;
-}
-
-function getCypressCliArgs(): Record<string, unknown> {
-  if (!process.env.CYPRESS_CLI_ARGS) {
-    return {};
-  }
-
-  const { $0, _, ...cypressCliArgs } = JSON.parse(process.env.CYPRESS_CLI_ARGS) as Record<
-    string,
-    unknown
-  >;
-
-  const spec =
-    typeof cypressCliArgs.spec === 'string' && !cypressCliArgs.spec.includes('**')
-      ? `**/${cypressCliArgs.spec}*`
-      : cypressCliArgs.spec;
-
-  return { ...cypressCliArgs, spec };
-}
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_config.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_config.ts
deleted file mode 100644
index 56cb76e2b2ac7..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_config.ts
+++ /dev/null
@@ -1,58 +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 { FtrConfigProviderContext } from '@kbn/test';
-import { CA_CERT_PATH } from '@kbn/dev-utils';
-import { commonFunctionalServices } from '@kbn/ftr-common-functional-services';
-import { commonFunctionalUIServices } from '@kbn/ftr-common-functional-ui-services';
-import path from 'path';
-
-const kibanaYamlFilePath = path.join(__dirname, './ftr_kibana.yml');
-
-async function ftrConfig({ readConfigFile }: FtrConfigProviderContext) {
-  const kibanaCommonTestsConfig = await readConfigFile(
-    require.resolve('@kbn/test-suites-src/common/config')
-  );
-  const xpackFunctionalTestsConfig = await readConfigFile(
-    require.resolve('@kbn/test-suites-xpack/functional/config.base')
-  );
-
-  return {
-    ...kibanaCommonTestsConfig.getAll(),
-
-    services: {
-      ...commonFunctionalServices,
-      ...commonFunctionalUIServices,
-    },
-
-    esTestCluster: {
-      ...xpackFunctionalTestsConfig.get('esTestCluster'),
-      serverArgs: [
-        ...xpackFunctionalTestsConfig.get('esTestCluster.serverArgs'),
-        // define custom es server here
-        // API Keys is enabled at the top level
-        'xpack.security.enabled=true',
-      ],
-    },
-
-    kbnTestServer: {
-      ...xpackFunctionalTestsConfig.get('kbnTestServer'),
-      serverArgs: [
-        ...xpackFunctionalTestsConfig.get('kbnTestServer.serverArgs'),
-        '--home.disableWelcomeScreen=true',
-        '--csp.strict=false',
-        '--csp.warnLegacyBrowsers=false',
-        // define custom kibana server args here
-        `--elasticsearch.ssl.certificateAuthorities=${CA_CERT_PATH}`,
-        `--config=${kibanaYamlFilePath}`,
-      ],
-    },
-  };
-}
-
-// eslint-disable-next-line import/no-default-export
-export default ftrConfig;
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_config_open.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_config_open.ts
deleted file mode 100644
index 18508abf27f0c..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_config_open.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { FtrConfigProviderContext } from '@kbn/test';
-import cypress from 'cypress';
-import { FtrProviderContext } from './ftr_provider_context';
-import { cypressTestRunner } from './cypress_test_runner';
-
-async function ftrConfigOpen({ readConfigFile }: FtrConfigProviderContext) {
-  const kibanaConfig = await readConfigFile(require.resolve('./ftr_config.ts'));
-  return {
-    ...kibanaConfig.getAll(),
-    testRunner,
-  };
-}
-
-export async function testRunner(ftrProviderContext: FtrProviderContext) {
-  await cypressTestRunner({
-    ftrProviderContext,
-    cypressExecution: cypress.open,
-  });
-}
-
-// eslint-disable-next-line import/no-default-export
-export default ftrConfigOpen;
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_config_runner.ts b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_config_runner.ts
deleted file mode 100644
index 535062fdda0b0..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_config_runner.ts
+++ /dev/null
@@ -1,38 +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 { FtrConfigProviderContext } from '@kbn/test';
-import cypress from 'cypress';
-import { cypressTestRunner } from './cypress_test_runner';
-import { FtrProviderContext } from './ftr_provider_context';
-
-async function ftrConfigRun({ readConfigFile }: FtrConfigProviderContext) {
-  const kibanaConfig = await readConfigFile(require.resolve('./ftr_config.ts'));
-
-  return {
-    ...kibanaConfig.getAll(),
-    testRunner,
-  };
-}
-
-async function testRunner(ftrProviderContext: FtrProviderContext) {
-  const result = await cypressTestRunner({
-    ftrProviderContext,
-    cypressExecution: cypress.run,
-  });
-
-  if (
-    result &&
-    ((result as CypressCommandLine.CypressFailedRunResult)?.status === 'failed' ||
-      (result as CypressCommandLine.CypressRunResult)?.totalFailed)
-  ) {
-    process.exit(1);
-  }
-}
-
-// eslint-disable-next-line import/no-default-export
-export default ftrConfigRun;
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_kibana.yml b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_kibana.yml
deleted file mode 100644
index 06507182d40fe..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_kibana.yml
+++ /dev/null
@@ -1 +0,0 @@
-xpack.cloud.id: 'myDeployment:03ce773830e104e139243c8f053c974d'
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/kibana.jsonc b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/kibana.jsonc
deleted file mode 100644
index 033d72a02427f..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/kibana.jsonc
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "type": "test-helper",
-  "id": "@kbn/observability-onboarding-e2e",
-  "owner": ["@elastic/obs-ux-logs-team"],
-  "group": "observability",
-  "visibility": "private",
-  "devOnly": true
-}
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/tsconfig.json b/x-pack/solutions/observability/plugins/observability_onboarding/e2e/tsconfig.json
deleted file mode 100644
index 33051d690a6f7..0000000000000
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/tsconfig.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-  "extends": "../../../../../../tsconfig.base.json",
-  "include": ["**/*"],
-  "exclude": ["tmp", "target/**/*"],
-  "compilerOptions": {
-    "outDir": "target/types",
-    "types": ["cypress", "node", "cypress-real-events"],
-    "isolatedModules": false
-  },
-  "kbn_references": [
-    { "path": "../../../../test/tsconfig.json" },
-    "@kbn/test",
-    "@kbn/dev-utils",
-    "@kbn/cypress-config",
-    "@kbn/observability-onboarding-plugin",
-    "@kbn/ftr-common-functional-services",
-    "@kbn/ftr-common-functional-ui-services",
-    "@kbn/tooling-log"
-  ]
-}
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/tsconfig.json b/x-pack/solutions/observability/plugins/observability_onboarding/tsconfig.json
index 391f1d6fee64f..79e54ce203d63 100644
--- a/x-pack/solutions/observability/plugins/observability_onboarding/tsconfig.json
+++ b/x-pack/solutions/observability/plugins/observability_onboarding/tsconfig.json
@@ -8,7 +8,8 @@
     "public/**/*",
     "../../../../../typings/**/*",
     "public/**/*.json",
-    "server/**/*"
+    "server/**/*",
+    "e2e/**/*"
   ],
   "kbn_references": [
     "@kbn/core",
@@ -43,7 +44,8 @@
     "@kbn/server-route-repository-utils",
     "@kbn/core-application-browser",
     "@kbn/core-plugins-server",
-    "@kbn/logs-shared-plugin"
+    "@kbn/logs-shared-plugin",
+    "@kbn/tooling-log"
   ],
   "exclude": [
     "target/**/*"
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/README.md b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/README.md
new file mode 100644
index 0000000000000..9a45d498a61eb
--- /dev/null
+++ b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/README.md
@@ -0,0 +1,23 @@
+## How to run tests
+
+First start the servers:
+
+```bash
+// ESS
+node scripts/scout.js start-server --stateful
+
+// Serverless
+node scripts/scout.js start-server --serverless=[es|oblt|security]
+```
+
+Then you can run the tests in another terminal:
+
+```bash
+// ESS
+npx playwright test --config x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/playwright.config.ts --grep @ess
+
+// Serverless
+npx playwright test --config x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/playwright.config.ts --grep @svlOblt
+```
+
+Test results are available in `x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/output`
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/fixtures/index.ts b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/fixtures/index.ts
new file mode 100644
index 0000000000000..a928c1d6fe34b
--- /dev/null
+++ b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/fixtures/index.ts
@@ -0,0 +1,50 @@
+/*
+ * 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,
+  PageObjects,
+  createLazyPageObject,
+  ScoutTestFixtures,
+  ScoutWorkerFixtures,
+  KibanaUrl,
+  KbnClient,
+} from '@kbn/scout';
+import { OnboardingHomePage } from './page_objects';
+import { CustomLogsPage } from './page_objects/custom_logs';
+
+export interface ExtendedScoutTestFixtures extends ScoutTestFixtures {
+  pageObjects: PageObjects & {
+    onboardingHomePage: OnboardingHomePage;
+    customLogsPage: CustomLogsPage;
+  };
+}
+
+export const test = base.extend<ExtendedScoutTestFixtures, ScoutWorkerFixtures>({
+  pageObjects: async (
+    {
+      pageObjects,
+      page,
+      kbnUrl,
+      kbnClient,
+    }: {
+      pageObjects: ExtendedScoutTestFixtures['pageObjects'];
+      page: ExtendedScoutTestFixtures['page'];
+      kbnUrl: KibanaUrl;
+      kbnClient: KbnClient;
+    },
+    use: (pageObjects: ExtendedScoutTestFixtures['pageObjects']) => Promise<void>
+  ) => {
+    const extendedPageObjects = {
+      ...pageObjects,
+      onboardingHomePage: createLazyPageObject(OnboardingHomePage, page),
+      customLogsPage: createLazyPageObject(CustomLogsPage, page, kbnUrl, kbnClient),
+    };
+
+    await use(extendedPageObjects);
+  },
+});
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/fixtures/page_objects/custom_logs.ts b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/fixtures/page_objects/custom_logs.ts
new file mode 100644
index 0000000000000..5b4b637ff7b4a
--- /dev/null
+++ b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/fixtures/page_objects/custom_logs.ts
@@ -0,0 +1,195 @@
+/*
+ * 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, KibanaUrl, KbnClient } from '@kbn/scout';
+
+export class CustomLogsPage {
+  static readonly ASSERTION_MESSAGES = {
+    INTEGRATION_NAME_CASE_ERROR: 'An integration name should be lowercase.',
+    DATASET_NAME_CASE_ERROR: 'A dataset name should be lowercase.',
+    EXISTING_INTEGRATION_ERROR: (name: string) =>
+      `Failed to create the integration as an installation with the name ${name} already exists.`,
+
+    DOWNLOADING_AGENT_STATUS: 'Downloading Elastic Agent',
+    DOWNLOADED_AGENT_STATUS: 'Elastic Agent downloaded',
+    DOWNLOAD_AGENT_DANGER_CALLOUT: 'Download Elastic Agent',
+    EXTRACTING_AGENT_STATUS: 'Extracting Elastic Agent',
+    EXTRACTED_AGENT_STATUS: 'Elastic Agent extracted',
+    EXTRACT_AGENT_DANGER_CALLOUT: 'Extract Elastic Agent',
+    INSTALLING_AGENT_STATUS: 'Installing Elastic Agent',
+    INSTALLED_AGENT_STATUS: 'Elastic Agent installed',
+    INSTALL_AGENT_DANGER_CALLOUT: 'Install Elastic Agent',
+    CONNECTING_TO_AGENT_STATUS: 'Connecting to Elastic Agent',
+    CONNECTED_TO_AGENT_STATUS: 'Connected to Elastic Agent',
+    CONNECT_AGENT_WARNING_CALLOUT: 'Connect to the Elastic Agent',
+    DOWNLOAD_AGENT_CONFIG_STATUS: 'Downloading Elastic Agent config',
+    CONFIGURE_AGENT_WARNING_CALLOUT: 'Configure the agent',
+    DOWNLOADING_AGENT_CONFIG_STATUS: 'Downloading Elastic Agent config',
+    AGENT_CONFIGURATION_SUCCESS_CALLOUT_MACOS:
+      'Elastic Agent config written to /Library/Elastic/Agent/elastic-agent.yml',
+    AGENT_CONFIGURATION_SUCCESS_CALLOUT_LINUX:
+      'Elastic Agent config written to /opt/Elastic/Agent/elastic-agent.yml',
+    INSTALLATION_STEP_2_DISABLED: 'Step 2 is disabled',
+  };
+
+  public readonly advancedSettingsContent;
+  public readonly logFilePathList;
+  public readonly continueButton;
+  public readonly addLogFilePathButton;
+  public readonly integrationNameInput;
+  public readonly datasetNameInput;
+  public readonly serviceNameInput;
+  public readonly namespaceInput;
+  public readonly customConfigInput;
+  public readonly customIntegrationSuccessCallout;
+  public readonly customIntegrationErrorCallout;
+  public readonly apiKeyCreateSuccessCallout;
+  public readonly apiKeyPrivilegesErrorCallout;
+  public readonly apiKeyCreateErrorCallout;
+  public readonly linuxCodeSnippetButton;
+  public readonly macOSCodeSnippetButton;
+  public readonly windowsCodeSnippetButton;
+  public readonly autoDownloadConfigurationToggle;
+  public readonly autoDownloadConfigurationCallout;
+  public readonly installCodeSnippet;
+  public readonly windowsInstallElasticAgentDocLink;
+  public readonly configureElasticAgentStep;
+  public readonly downloadConfigurationButton;
+  public readonly stepStatusLoading;
+  public readonly stepStatusComplete;
+  public readonly stepStatusDanger;
+  public readonly stepStatusWarning;
+
+  constructor(
+    private readonly page: ScoutPage,
+    private readonly kbnUrl: KibanaUrl,
+    private readonly kbnClient: KbnClient
+  ) {
+    this.advancedSettingsContent = this.page.testSubj
+      .locator('obltOnboardingCustomLogsAdvancedSettings')
+      .getByRole('group');
+    this.logFilePathList = this.page.locator(`[data-test-subj^=obltOnboardingLogFilePath-]`);
+    this.continueButton = this.page.testSubj.locator('obltOnboardingCustomLogsContinue');
+    this.addLogFilePathButton = this.page.testSubj.locator('obltOnboardingCustomLogsAddFilePath');
+    this.integrationNameInput = this.page.testSubj.locator(
+      'obltOnboardingCustomLogsIntegrationsName'
+    );
+    this.datasetNameInput = this.page.testSubj.locator('obltOnboardingCustomLogsDatasetName');
+    this.serviceNameInput = this.page.testSubj.locator('obltOnboardingCustomLogsServiceName');
+    this.namespaceInput = this.page.testSubj.locator('obltOnboardingCustomLogsNamespace');
+    this.customConfigInput = this.page.testSubj.locator('obltOnboardingCustomLogsCustomConfig');
+    this.customIntegrationSuccessCallout = this.page.testSubj.locator(
+      'obltOnboardingCustomIntegrationInstalled'
+    );
+    this.customIntegrationErrorCallout = this.page.testSubj.locator(
+      'obltOnboardingCustomIntegrationErrorCallout'
+    );
+    this.apiKeyCreateSuccessCallout = this.page.testSubj.locator('obltOnboardingLogsApiKeyCreated');
+    this.apiKeyPrivilegesErrorCallout = this.page.testSubj.locator(
+      'obltOnboardingLogsApiKeyCreationNoPrivileges'
+    );
+    this.apiKeyCreateErrorCallout = this.page.testSubj.locator(
+      'obltOnboardingLogsApiKeyCreationFailed'
+    );
+    this.linuxCodeSnippetButton = this.page.testSubj.locator('linux-tar');
+    this.macOSCodeSnippetButton = this.page.testSubj.locator('macos');
+    this.windowsCodeSnippetButton = this.page.testSubj.locator('windows');
+    this.autoDownloadConfigurationToggle = this.page.testSubj.locator(
+      'obltOnboardingInstallElasticAgentAutoDownloadConfig'
+    );
+    this.autoDownloadConfigurationCallout = this.page.testSubj.locator(
+      'obltOnboardingInstallElasticAgentAutoDownloadConfigCallout'
+    );
+    this.installCodeSnippet = this.page.testSubj
+      .locator('obltOnboardingInstallElasticAgentStep')
+      .getByRole('code');
+    this.windowsInstallElasticAgentDocLink = this.page.testSubj.locator(
+      'obltOnboardingInstallElasticAgentWindowsDocsLink'
+    );
+    this.configureElasticAgentStep = this.page.testSubj.locator(
+      'obltOnboardingConfigureElasticAgentStep'
+    );
+    this.downloadConfigurationButton = this.page.testSubj.locator(
+      'obltOnboardingConfigureElasticAgentStepDownloadConfig'
+    );
+    this.stepStatusLoading = this.page.testSubj.locator('obltOnboardingStepStatus-loading');
+    this.stepStatusComplete = this.page.testSubj.locator('obltOnboardingStepStatus-complete');
+    this.stepStatusDanger = this.page.testSubj.locator('obltOnboardingStepStatus-danger');
+    this.stepStatusWarning = this.page.testSubj.locator('obltOnboardingStepStatus-warning');
+  }
+
+  async goto() {
+    this.page.goto(`${this.kbnUrl.app('observabilityOnboarding')}/customLogs`);
+  }
+
+  async clickBackButton() {
+    await this.page.testSubj.click('observabilityOnboardingFlowBackToSelectionButton');
+  }
+
+  logFilePathInput(index: number) {
+    return this.page.testSubj.locator(`obltOnboardingLogFilePath-${index}`).getByRole('textbox');
+  }
+
+  logFilePathDeleteButton(index: number) {
+    return this.page.testSubj.locator(`obltOnboardingLogFilePathDelete-${index}`);
+  }
+
+  async clickAdvancedSettingsButton() {
+    return this.page.testSubj
+      .locator('obltOnboardingCustomLogsAdvancedSettings')
+      .getByRole('button')
+      .first()
+      .click();
+  }
+
+  async installCustomIntegration(name: string) {
+    await this.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' },
+        ],
+      },
+    });
+  }
+
+  async deleteIntegration(name: string) {
+    const packageInfo = await this.kbnClient.request<{ item: { status: string } }>({
+      method: 'GET',
+      path: `/api/fleet/epm/packages/${name}`,
+      ignoreErrors: [404],
+    });
+
+    if (packageInfo.data.item?.status === 'installed') {
+      await this.kbnClient.request({
+        method: 'DELETE',
+        path: `/api/fleet/epm/packages/${name}`,
+      });
+    }
+  }
+
+  async updateInstallationStepStatus(
+    onboardingId: string,
+    step: string,
+    status: string,
+    payload?: object
+  ) {
+    await this.kbnClient.request({
+      method: 'POST',
+      path: `/internal/observability_onboarding/flow/${onboardingId}/step/${step}`,
+      body: {
+        status,
+        payload,
+      },
+    });
+  }
+}
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/support/e2e.ts b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/fixtures/page_objects/index.ts
similarity index 72%
rename from x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/support/e2e.ts
rename to x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/fixtures/page_objects/index.ts
index 5f5d1eb3b3614..c032371659593 100644
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/cypress/support/e2e.ts
+++ b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/fixtures/page_objects/index.ts
@@ -5,8 +5,4 @@
  * 2.0.
  */
 
-Cypress.on('uncaught:exception', (err, runnable) => {
-  return false;
-});
-
-import './commands';
+export { OnboardingHomePage } from './onboarding_home';
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/fixtures/page_objects/onboarding_home.ts b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/fixtures/page_objects/onboarding_home.ts
new file mode 100644
index 0000000000000..bd35dc4fbe909
--- /dev/null
+++ b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/fixtures/page_objects/onboarding_home.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { ScoutPage } from '@kbn/scout';
+
+export class OnboardingHomePage {
+  constructor(private readonly page: ScoutPage) {}
+
+  async goto() {
+    this.page.gotoApp('observabilityOnboarding');
+  }
+}
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_provider_context.d.ts b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/playwright.config.ts
similarity index 59%
rename from x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_provider_context.d.ts
rename to x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/playwright.config.ts
index b87f35adcccf2..34b370396b67e 100644
--- a/x-pack/solutions/observability/plugins/observability_onboarding/e2e/ftr_provider_context.d.ts
+++ b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/playwright.config.ts
@@ -5,6 +5,9 @@
  * 2.0.
  */
 
-import { GenericFtrProviderContext } from '@kbn/test';
+import { createPlaywrightConfig } from '@kbn/scout';
 
-export type FtrProviderContext = GenericFtrProviderContext<{}, {}>;
+// eslint-disable-next-line import/no-default-export
+export default createPlaywrightConfig({
+  testDir: './tests',
+});
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/tests/custom_logs/configuration.spec.ts b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/tests/custom_logs/configuration.spec.ts
new file mode 100644
index 0000000000000..2a2db5af2c7ec
--- /dev/null
+++ b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/tests/custom_logs/configuration.spec.ts
@@ -0,0 +1,256 @@
+/*
+ * 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 } from '@kbn/scout';
+import { test } from '../../fixtures';
+import { CustomLogsPage } from '../../fixtures/page_objects/custom_logs';
+
+test.describe('Onboarding app - Custom logs configuration', { tag: ['@ess', '@svlOblt'] }, () => {
+  test.beforeEach(async ({ browserAuth, pageObjects: { customLogsPage } }) => {
+    await browserAuth.loginAsAdmin();
+    await customLogsPage.goto();
+  });
+
+  test('When user clicks the back button user goes to the onboarding home page', async ({
+    pageObjects: { customLogsPage },
+    page,
+  }) => {
+    await customLogsPage.clickBackButton();
+    expect(page.url()).toContain('/app/observabilityOnboarding');
+  });
+
+  test(`Users shouldn't be able to continue if logFilePaths is empty`, async ({
+    pageObjects: { customLogsPage },
+  }) => {
+    await expect(customLogsPage.logFilePathInput(0)).toHaveValue('');
+    await expect(customLogsPage.continueButton).toBeDisabled();
+  });
+
+  test(`Users should be able to continue if logFilePaths is not empty`, async ({
+    pageObjects: { customLogsPage },
+  }) => {
+    await customLogsPage.logFilePathInput(0).fill('some/path');
+
+    await expect(customLogsPage.continueButton).not.toBeDisabled();
+  });
+
+  test('Users can add multiple logFilePaths', async ({ pageObjects: { customLogsPage } }) => {
+    await customLogsPage.addLogFilePathButton.click();
+    await expect(customLogsPage.logFilePathInput(0)).toBeVisible();
+    await expect(customLogsPage.logFilePathInput(1)).toBeVisible();
+  });
+
+  test('Users can delete logFilePaths', async ({ pageObjects: { customLogsPage } }) => {
+    await customLogsPage.addLogFilePathButton.click();
+    await expect(customLogsPage.logFilePathList).toHaveCount(2);
+
+    await customLogsPage.logFilePathDeleteButton(1).click();
+    await expect(customLogsPage.logFilePathList).toHaveCount(1);
+  });
+
+  test('Dataset Name and Integration Name are auto generated if it is the first path', async ({
+    pageObjects: { customLogsPage },
+  }) => {
+    await customLogsPage.logFilePathInput(0).fill('myLogs.log');
+
+    await expect(customLogsPage.integrationNameInput).toHaveValue('mylogs');
+    await expect(customLogsPage.datasetNameInput).toHaveValue('mylogs');
+  });
+
+  test('Dataset Name and Integration Name are not generated if it is not the first path', async ({
+    pageObjects: { customLogsPage },
+  }) => {
+    await customLogsPage.addLogFilePathButton.click();
+    await customLogsPage.logFilePathInput(1).fill('myLogs.log');
+
+    await expect(customLogsPage.integrationNameInput).toHaveValue('');
+    await expect(customLogsPage.datasetNameInput).toHaveValue('');
+  });
+
+  test('Service name input should be optional allowing user to continue if it is empty', async ({
+    pageObjects: { customLogsPage },
+  }) => {
+    await customLogsPage.logFilePathInput(0).fill('myLogs.log');
+
+    await expect(customLogsPage.serviceNameInput).toHaveValue('');
+    await expect(customLogsPage.continueButton).not.toBeDisabled();
+  });
+
+  test('Users should expand and collapse the Advanced settings section', async ({
+    pageObjects: { customLogsPage },
+  }) => {
+    await expect(customLogsPage.advancedSettingsContent).not.toBeVisible();
+
+    await customLogsPage.clickAdvancedSettingsButton();
+
+    await expect(customLogsPage.advancedSettingsContent).toBeVisible();
+
+    await customLogsPage.clickAdvancedSettingsButton();
+
+    await expect(customLogsPage.advancedSettingsContent).not.toBeVisible();
+  });
+
+  test('Users should see a default namespace', async ({ pageObjects: { customLogsPage } }) => {
+    customLogsPage.clickAdvancedSettingsButton();
+
+    await expect(customLogsPage.namespaceInput).toHaveValue('default');
+  });
+
+  test('Users should not be able to continue if they do not specify a namespace', async ({
+    pageObjects: { customLogsPage },
+  }) => {
+    customLogsPage.clickAdvancedSettingsButton();
+
+    await customLogsPage.namespaceInput.fill('');
+    await expect(customLogsPage.continueButton).toBeDisabled();
+  });
+
+  test('should be optional allowing user to continue if it is empty', async ({
+    pageObjects: { customLogsPage },
+  }) => {
+    await customLogsPage.clickAdvancedSettingsButton();
+    await customLogsPage.logFilePathInput(0).fill('myLogs.log');
+    await expect(customLogsPage.customConfigInput).toHaveValue('');
+    await expect(customLogsPage.continueButton).not.toBeDisabled();
+  });
+
+  test.describe('Integration name', () => {
+    test.beforeEach(async ({ pageObjects: { customLogsPage } }) => {
+      await customLogsPage.logFilePathInput(0).fill('myLogs.log');
+    });
+
+    test('Users should not be able to continue if they do not specify an integrationName', async ({
+      pageObjects: { customLogsPage },
+    }) => {
+      await customLogsPage.integrationNameInput.fill('');
+      await expect(customLogsPage.continueButton).toBeDisabled();
+    });
+
+    test('value will contain _ instead of special chars', async ({
+      pageObjects: { customLogsPage },
+    }) => {
+      await customLogsPage.integrationNameInput.fill('hello$world');
+      await expect(customLogsPage.integrationNameInput).toHaveValue('hello_world');
+    });
+
+    test('value will be invalid if it is not lowercase', async ({
+      pageObjects: { customLogsPage },
+      page,
+    }) => {
+      await customLogsPage.integrationNameInput.fill('H3llowOrld');
+      await expect(
+        page.getByText(CustomLogsPage.ASSERTION_MESSAGES.INTEGRATION_NAME_CASE_ERROR)
+      ).toBeVisible();
+    });
+  });
+
+  test.describe('datasetName', () => {
+    test.beforeEach(async ({ pageObjects: { customLogsPage } }) => {
+      await customLogsPage.logFilePathInput(0).fill('myLogs.log');
+    });
+
+    test('Users should not be able to continue if they do not specify a datasetName', async ({
+      pageObjects: { customLogsPage },
+    }) => {
+      await customLogsPage.datasetNameInput.fill('');
+      await expect(customLogsPage.continueButton).toBeDisabled();
+    });
+
+    test('value will contain _ instead of special chars', async ({
+      pageObjects: { customLogsPage },
+    }) => {
+      await customLogsPage.datasetNameInput.fill('hello$world');
+      await expect(customLogsPage.datasetNameInput).toHaveValue('hello_world');
+    });
+
+    test('value will be invalid if it is not lowercase', async ({
+      pageObjects: { customLogsPage },
+      page,
+    }) => {
+      await customLogsPage.datasetNameInput.fill('H3llowOrld');
+      await expect(
+        page.getByText(CustomLogsPage.ASSERTION_MESSAGES.DATASET_NAME_CASE_ERROR)
+      ).toBeVisible();
+    });
+  });
+
+  test.describe('Custom integration', () => {
+    const CUSTOM_INTEGRATION_NAME = 'mylogs';
+
+    test.beforeEach(async ({ pageObjects: { customLogsPage } }) => {
+      await customLogsPage.deleteIntegration(CUSTOM_INTEGRATION_NAME);
+    });
+
+    test.describe('when user is missing privileges', () => {
+      test.beforeEach(async ({ browserAuth, page }) => {
+        await browserAuth.loginAsViewer();
+        await page.reload();
+      });
+
+      test.afterEach(async ({ browserAuth, page }) => {
+        await browserAuth.loginAsAdmin();
+        await page.reload();
+      });
+
+      test('installation fails', async ({ pageObjects: { customLogsPage } }) => {
+        await customLogsPage.logFilePathInput(0).fill(`${CUSTOM_INTEGRATION_NAME}.log`);
+        await customLogsPage.continueButton.click();
+
+        await expect(customLogsPage.customIntegrationErrorCallout).toBeVisible();
+      });
+    });
+
+    test.describe('when user has proper privileges', () => {
+      test('installation succeed and user is redirected to install elastic agent step', async ({
+        page,
+        pageObjects: { customLogsPage },
+      }) => {
+        await customLogsPage.logFilePathInput(0).fill(`${CUSTOM_INTEGRATION_NAME}.log`);
+        await customLogsPage.continueButton.click();
+
+        await page.waitForURL('**/app/observabilityOnboarding/customLogs/installElasticAgent');
+      });
+    });
+
+    test('installation fails if integration already exists', async ({
+      pageObjects: { customLogsPage },
+      page,
+    }) => {
+      await customLogsPage.installCustomIntegration(CUSTOM_INTEGRATION_NAME);
+      await customLogsPage.logFilePathInput(0).fill(`${CUSTOM_INTEGRATION_NAME}.log`);
+      await customLogsPage.continueButton.click();
+
+      await expect(
+        page.getByText(
+          CustomLogsPage.ASSERTION_MESSAGES.EXISTING_INTEGRATION_ERROR(CUSTOM_INTEGRATION_NAME)
+        )
+      ).toBeVisible();
+    });
+
+    test.describe('when an error occurred on creation', () => {
+      test('user should see the error displayed', async ({
+        pageObjects: { customLogsPage },
+        page,
+        kbnUrl,
+      }) => {
+        await page.route(kbnUrl.get('/api/fleet/epm/custom_integrations'), (route) => {
+          route.fulfill({
+            status: 500,
+            json: {
+              message: 'Internal error',
+            },
+          });
+        });
+
+        await customLogsPage.logFilePathInput(0).fill(`${CUSTOM_INTEGRATION_NAME}.log`);
+        await customLogsPage.continueButton.click();
+
+        await expect(customLogsPage.customIntegrationErrorCallout).toBeVisible();
+      });
+    });
+  });
+});
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/tests/custom_logs/install_elastic_agent.spec.ts b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/tests/custom_logs/install_elastic_agent.spec.ts
new file mode 100644
index 0000000000000..2dadb23090418
--- /dev/null
+++ b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/tests/custom_logs/install_elastic_agent.spec.ts
@@ -0,0 +1,696 @@
+/*
+ * 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 } from '@kbn/scout';
+import { type ExtendedScoutTestFixtures, test } from '../../fixtures';
+import { CustomLogsPage } from '../../fixtures/page_objects/custom_logs';
+
+const CUSTOM_INTEGRATION_NAME = 'mylogs';
+
+function setupPage({ isAdmin }: { isAdmin: boolean }) {
+  return async ({
+    browserAuth,
+    pageObjects: { customLogsPage },
+    page,
+  }: ExtendedScoutTestFixtures) => {
+    await browserAuth.loginAsAdmin();
+    await customLogsPage.deleteIntegration(CUSTOM_INTEGRATION_NAME);
+
+    if (!isAdmin) {
+      await browserAuth.loginAsPrivilegedUser();
+      await page.reload();
+    }
+
+    await customLogsPage.deleteIntegration(CUSTOM_INTEGRATION_NAME);
+
+    await customLogsPage.goto();
+    await customLogsPage.logFilePathInput(0).fill('mylogs.log');
+    await customLogsPage.continueButton.click();
+  };
+}
+
+test.describe(
+  'Onboarding app - Custom logs install Elastic Agent',
+  { tag: ['@ess', '@svlOblt'] },
+  () => {
+    test.describe('Custom integration', () => {
+      test.beforeEach(setupPage({ isAdmin: true }));
+
+      test('Users should be able to see the custom integration success callout', async ({
+        pageObjects: { customLogsPage },
+      }) => {
+        await expect(customLogsPage.customIntegrationSuccessCallout).toBeVisible();
+      });
+    });
+
+    test.describe('ApiKey generation', () => {
+      test.describe('when user is missing privileges', () => {
+        test.beforeEach(setupPage({ isAdmin: false }));
+
+        test('apiKey is not generated', async ({ pageObjects: { customLogsPage } }) => {
+          await expect(customLogsPage.apiKeyPrivilegesErrorCallout).toBeVisible();
+        });
+      });
+
+      test.describe('when user has proper privileges', () => {
+        test.beforeEach(setupPage({ isAdmin: true }));
+
+        test('apiKey is generated', async ({ pageObjects: { customLogsPage } }) => {
+          await expect(customLogsPage.apiKeyCreateSuccessCallout).toBeVisible();
+        });
+      });
+
+      test.describe('when an error occurred on creation', () => {
+        test.beforeEach(async ({ browserAuth, pageObjects: { customLogsPage }, page }) => {
+          await page.route('**/observability_onboarding/logs/flow', (route) => {
+            route.fulfill({
+              status: 500,
+              body: JSON.stringify({
+                message: 'Internal error',
+              }),
+            });
+          });
+        });
+
+        test.beforeEach(setupPage({ isAdmin: true }));
+
+        test('apiKey is not generated', async ({ pageObjects: { customLogsPage } }) => {
+          await expect(customLogsPage.apiKeyCreateErrorCallout).toBeVisible();
+        });
+      });
+    });
+
+    test.describe('Install the Elastic Agent step', () => {
+      test.beforeEach(setupPage({ isAdmin: true }));
+
+      test.describe('When user select Linux OS', () => {
+        test('Auto download config to host is disabled by default', async ({
+          pageObjects: { customLogsPage },
+        }) => {
+          await customLogsPage.linuxCodeSnippetButton.click();
+          await expect(customLogsPage.autoDownloadConfigurationToggle).not.toBeChecked();
+        });
+
+        test('Installation script is shown', async ({ pageObjects: { customLogsPage } }) => {
+          await expect(customLogsPage.installCodeSnippet).toBeVisible();
+        });
+      });
+
+      test.describe('When user select Mac OS', () => {
+        test.beforeEach(async ({ pageObjects: { customLogsPage } }) => {
+          await customLogsPage.macOSCodeSnippetButton.click();
+        });
+
+        test('Auto download config to host is disabled by default', async ({
+          pageObjects: { customLogsPage },
+        }) => {
+          await expect(customLogsPage.autoDownloadConfigurationToggle).not.toBeChecked();
+        });
+
+        test('Installation script is shown', async ({ pageObjects: { customLogsPage } }) => {
+          await expect(customLogsPage.installCodeSnippet).toBeVisible();
+        });
+      });
+
+      test.describe('When user select Windows OS', () => {
+        test.beforeEach(async ({ pageObjects: { customLogsPage } }) => {
+          await customLogsPage.windowsCodeSnippetButton.click();
+        });
+
+        test('Auto download config to host is disabled by default', async ({
+          pageObjects: { customLogsPage },
+        }) => {
+          await expect(customLogsPage.autoDownloadConfigurationToggle).not.toBeChecked();
+        });
+
+        test('A link to the documentation is shown instead of installation script', async ({
+          pageObjects: { customLogsPage },
+        }) => {
+          await expect(customLogsPage.windowsInstallElasticAgentDocLink).toBeVisible();
+          await expect(customLogsPage.installCodeSnippet).not.toBeVisible();
+        });
+      });
+
+      test.describe('When Auto download config', () => {
+        test.describe('is selected', () => {
+          test('autoDownloadConfig flag is added to installation script', async ({
+            pageObjects: { customLogsPage },
+          }) => {
+            await customLogsPage.autoDownloadConfigurationToggle.click();
+            await expect(customLogsPage.autoDownloadConfigurationCallout).toBeVisible();
+            await expect(customLogsPage.installCodeSnippet).toContainText('autoDownloadConfig=1');
+          });
+
+          test('Download config button is disabled', async ({
+            pageObjects: { customLogsPage },
+          }) => {
+            await customLogsPage.autoDownloadConfigurationToggle.click();
+            await expect(customLogsPage.downloadConfigurationButton).toBeDisabled();
+          });
+        });
+
+        test('is not selected autoDownloadConfig flag is not added to installation script', async ({
+          pageObjects: { customLogsPage },
+        }) => {
+          await expect(customLogsPage.installCodeSnippet).not.toContainText('autoDownloadConfig=1');
+        });
+      });
+
+      test.describe('When user executes the installation script in the host', () => {
+        let onboardingId: string;
+
+        test.describe('updates on steps are shown in the flow', () => {
+          test.beforeEach(async ({ page, pageObjects: { customLogsPage } }) => {
+            await page.route('**/observability_onboarding/logs/flow', async (route) => {
+              const response = await route.fetch();
+              const body = await response.json();
+
+              onboardingId = body.onboardingId;
+
+              await route.fulfill({ response });
+            });
+
+            await expect(customLogsPage.apiKeyCreateSuccessCallout).toBeVisible();
+          });
+
+          test.describe('Download elastic Agent step', () => {
+            test('shows a loading callout when elastic agent is downloading', async ({
+              pageObjects: { customLogsPage },
+            }) => {
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-download',
+                'loading'
+              );
+              await expect(
+                customLogsPage.stepStatusLoading.getByText(
+                  CustomLogsPage.ASSERTION_MESSAGES.DOWNLOADING_AGENT_STATUS
+                )
+              ).toBeVisible();
+            });
+
+            test('shows a success callout when elastic agent is downloaded', async ({
+              pageObjects: { customLogsPage },
+            }) => {
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-download',
+                'complete'
+              );
+              await expect(
+                customLogsPage.stepStatusComplete.getByText(
+                  CustomLogsPage.ASSERTION_MESSAGES.DOWNLOADED_AGENT_STATUS
+                )
+              ).toBeVisible();
+            });
+
+            test('shows a danger callout when elastic agent was not downloaded', async ({
+              pageObjects: { customLogsPage },
+            }) => {
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-download',
+                'danger'
+              );
+              await expect(
+                customLogsPage.stepStatusDanger.getByText(
+                  CustomLogsPage.ASSERTION_MESSAGES.DOWNLOAD_AGENT_DANGER_CALLOUT
+                )
+              ).toBeVisible();
+            });
+          });
+
+          test.describe('Extract elastic Agent step', () => {
+            test.beforeEach(async ({ pageObjects: { customLogsPage } }) => {
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-download',
+                'complete'
+              );
+            });
+
+            test('shows a loading callout when elastic agent is extracting', async ({
+              pageObjects: { customLogsPage },
+            }) => {
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-extract',
+                'loading'
+              );
+              await expect(
+                customLogsPage.stepStatusLoading.getByText(
+                  CustomLogsPage.ASSERTION_MESSAGES.EXTRACTING_AGENT_STATUS
+                )
+              ).toBeVisible();
+            });
+
+            test('shows a success callout when elastic agent is extracted', async ({
+              pageObjects: { customLogsPage },
+            }) => {
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-extract',
+                'complete'
+              );
+              await expect(
+                customLogsPage.stepStatusComplete.getByText(
+                  CustomLogsPage.ASSERTION_MESSAGES.EXTRACTED_AGENT_STATUS
+                )
+              ).toBeVisible();
+            });
+
+            test('shows a danger callout when elastic agent was not extracted', async ({
+              pageObjects: { customLogsPage },
+            }) => {
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-extract',
+                'danger'
+              );
+              await expect(
+                customLogsPage.stepStatusDanger.getByText(
+                  CustomLogsPage.ASSERTION_MESSAGES.EXTRACT_AGENT_DANGER_CALLOUT
+                )
+              ).toBeVisible();
+            });
+          });
+
+          test.describe('Install elastic Agent step', () => {
+            test.beforeEach(async ({ pageObjects: { customLogsPage } }) => {
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-download',
+                'complete'
+              );
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-extract',
+                'complete'
+              );
+            });
+
+            test('shows a loading callout when elastic agent is installing', async ({
+              pageObjects: { customLogsPage },
+            }) => {
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-install',
+                'loading'
+              );
+              await expect(
+                customLogsPage.stepStatusLoading.getByText(
+                  CustomLogsPage.ASSERTION_MESSAGES.INSTALLING_AGENT_STATUS
+                )
+              ).toBeVisible();
+            });
+
+            test('shows a success callout when elastic agent is installed', async ({
+              pageObjects: { customLogsPage },
+            }) => {
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-install',
+                'complete'
+              );
+              await expect(
+                customLogsPage.stepStatusComplete.getByText(
+                  CustomLogsPage.ASSERTION_MESSAGES.INSTALLED_AGENT_STATUS
+                )
+              ).toBeVisible();
+            });
+
+            test('shows a danger callout when elastic agent was not installed', async ({
+              pageObjects: { customLogsPage },
+            }) => {
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-install',
+                'danger'
+              );
+              await expect(
+                customLogsPage.stepStatusDanger.getByText(
+                  CustomLogsPage.ASSERTION_MESSAGES.INSTALL_AGENT_DANGER_CALLOUT
+                )
+              ).toBeVisible();
+            });
+          });
+
+          test.describe('Check elastic Agent status step', () => {
+            test.beforeEach(async ({ pageObjects: { customLogsPage } }) => {
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-download',
+                'complete'
+              );
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-extract',
+                'complete'
+              );
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-install',
+                'complete'
+              );
+            });
+
+            test('shows a loading callout when getting elastic agent status', async ({
+              pageObjects: { customLogsPage },
+            }) => {
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-status',
+                'loading'
+              );
+              await expect(
+                customLogsPage.stepStatusLoading.getByText(
+                  CustomLogsPage.ASSERTION_MESSAGES.CONNECTING_TO_AGENT_STATUS
+                )
+              ).toBeVisible();
+            });
+
+            test('shows a success callout when elastic agent status is healthy', async ({
+              pageObjects: { customLogsPage },
+            }) => {
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-status',
+                'complete',
+                {
+                  agentId: 'test-agent-id',
+                }
+              );
+              await expect(
+                customLogsPage.stepStatusComplete.getByText(
+                  CustomLogsPage.ASSERTION_MESSAGES.CONNECTED_TO_AGENT_STATUS
+                )
+              ).toBeVisible();
+            });
+
+            test('shows a warning callout when elastic agent status is not healthy', async ({
+              pageObjects: { customLogsPage },
+            }) => {
+              await customLogsPage.updateInstallationStepStatus(
+                onboardingId,
+                'ea-status',
+                'warning'
+              );
+              await expect(
+                customLogsPage.stepStatusWarning.getByText(
+                  CustomLogsPage.ASSERTION_MESSAGES.CONNECT_AGENT_WARNING_CALLOUT
+                )
+              ).toBeVisible();
+            });
+          });
+        });
+      });
+    });
+
+    test.describe('Configure Elastic Agent step', () => {
+      let onboardingId: string;
+
+      test.beforeEach(setupPage({ isAdmin: true }));
+
+      test.beforeEach(async ({ page, pageObjects: { customLogsPage } }) => {
+        await page.route('**/observability_onboarding/logs/flow', async (route) => {
+          const response = await route.fetch();
+          const body = await response.json();
+
+          onboardingId = body.onboardingId;
+
+          await route.fulfill({ response });
+        });
+
+        await expect(customLogsPage.apiKeyCreateSuccessCallout).toBeVisible();
+      });
+
+      test.describe('When user select Linux OS', () => {
+        test.beforeEach(async ({ pageObjects: { customLogsPage } }) => {
+          await customLogsPage.autoDownloadConfigurationToggle.click();
+          await customLogsPage.updateInstallationStepStatus(
+            onboardingId,
+            'ea-download',
+            'complete'
+          );
+          await customLogsPage.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete');
+          await customLogsPage.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete');
+          await customLogsPage.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', {
+            agentId: 'test-agent-id',
+          });
+        });
+
+        test('shows loading callout when config is being downloaded to the host', async ({
+          pageObjects: { customLogsPage },
+        }) => {
+          await customLogsPage.updateInstallationStepStatus(onboardingId, 'ea-config', 'loading');
+          await expect(
+            customLogsPage.stepStatusLoading.getByText(
+              CustomLogsPage.ASSERTION_MESSAGES.DOWNLOAD_AGENT_CONFIG_STATUS
+            )
+          ).toBeVisible();
+        });
+
+        test('shows success callout when the configuration has been written to the host', async ({
+          pageObjects: { customLogsPage },
+        }) => {
+          await customLogsPage.updateInstallationStepStatus(onboardingId, 'ea-config', 'complete');
+          await expect(
+            customLogsPage.stepStatusComplete.getByText(
+              CustomLogsPage.ASSERTION_MESSAGES.AGENT_CONFIGURATION_SUCCESS_CALLOUT_LINUX
+            )
+          ).toBeVisible();
+        });
+
+        test('shows warning callout when the configuration was not written in the host', async ({
+          pageObjects: { customLogsPage },
+        }) => {
+          await customLogsPage.updateInstallationStepStatus(onboardingId, 'ea-config', 'warning');
+          await expect(
+            customLogsPage.stepStatusWarning.getByText(
+              CustomLogsPage.ASSERTION_MESSAGES.CONFIGURE_AGENT_WARNING_CALLOUT
+            )
+          ).toBeVisible();
+        });
+      });
+
+      test.describe('When user select Mac OS', () => {
+        test.beforeEach(async ({ pageObjects: { customLogsPage } }) => {
+          await customLogsPage.macOSCodeSnippetButton.click();
+          await customLogsPage.autoDownloadConfigurationToggle.click();
+          await customLogsPage.updateInstallationStepStatus(
+            onboardingId,
+            'ea-download',
+            'complete'
+          );
+          await customLogsPage.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete');
+          await customLogsPage.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete');
+          await customLogsPage.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', {
+            agentId: 'test-agent-id',
+          });
+        });
+
+        test('shows loading callout when config is being downloaded to the host', async ({
+          pageObjects: { customLogsPage },
+        }) => {
+          await customLogsPage.updateInstallationStepStatus(onboardingId, 'ea-config', 'loading');
+          await expect(
+            customLogsPage.stepStatusLoading.getByText(
+              CustomLogsPage.ASSERTION_MESSAGES.DOWNLOADING_AGENT_CONFIG_STATUS
+            )
+          ).toBeVisible();
+        });
+
+        test('shows success callout when the configuration has been written to the host', async ({
+          pageObjects: { customLogsPage },
+        }) => {
+          await customLogsPage.updateInstallationStepStatus(onboardingId, 'ea-config', 'complete');
+          await expect(
+            customLogsPage.stepStatusComplete.getByText(
+              CustomLogsPage.ASSERTION_MESSAGES.AGENT_CONFIGURATION_SUCCESS_CALLOUT_MACOS
+            )
+          ).toBeVisible();
+        });
+
+        test('shows warning callout when the configuration was not written in the host', async ({
+          pageObjects: { customLogsPage },
+        }) => {
+          await customLogsPage.updateInstallationStepStatus(onboardingId, 'ea-config', 'warning');
+          await expect(
+            customLogsPage.stepStatusWarning.getByText(
+              CustomLogsPage.ASSERTION_MESSAGES.CONFIGURE_AGENT_WARNING_CALLOUT
+            )
+          ).toBeVisible();
+        });
+      });
+
+      test.describe('When user select Windows', () => {
+        test.beforeEach(async ({ pageObjects: { customLogsPage } }) => {
+          customLogsPage.windowsCodeSnippetButton.click();
+        });
+
+        test('step is disabled', async ({ pageObjects: { customLogsPage } }) => {
+          await expect(
+            customLogsPage.configureElasticAgentStep.getByText(
+              CustomLogsPage.ASSERTION_MESSAGES.INSTALLATION_STEP_2_DISABLED
+            )
+          ).toBeVisible();
+        });
+      });
+    });
+
+    test.describe('Check logs step', () => {
+      let onboardingId: string;
+
+      test.beforeEach(setupPage({ isAdmin: true }));
+
+      test.beforeEach(async ({ page, pageObjects: { customLogsPage } }) => {
+        await page.route('**/observability_onboarding/logs/flow', async (route) => {
+          const response = await route.fetch();
+          const body = await response.json();
+
+          onboardingId = body.onboardingId;
+
+          await route.fulfill({ response });
+        });
+
+        await expect(customLogsPage.apiKeyCreateSuccessCallout).toBeVisible();
+      });
+
+      test.describe('When user select Linux OS or MacOS', () => {
+        test.describe('When configure Elastic Agent step is not finished', () => {
+          test.beforeEach(async ({ pageObjects: { customLogsPage } }) => {
+            await customLogsPage.updateInstallationStepStatus(
+              onboardingId,
+              'ea-download',
+              'complete'
+            );
+            await customLogsPage.updateInstallationStepStatus(
+              onboardingId,
+              'ea-extract',
+              'complete'
+            );
+            await customLogsPage.updateInstallationStepStatus(
+              onboardingId,
+              'ea-install',
+              'complete'
+            );
+            await customLogsPage.updateInstallationStepStatus(onboardingId, 'ea-status', 'loading');
+          });
+
+          test('check logs is not triggered', async ({ page }) => {
+            await expect(
+              page.locator(
+                '[data-test-subj="obltOnboardingCheckLogsStep"] .euiStep__titleWrapper [class$="euiStepNumber-s-incomplete"]'
+              )
+            ).toBeVisible();
+            await expect(
+              page.locator('.euiStep__title', { hasText: 'Ship logs to Elastic Observability' })
+            ).toBeVisible();
+          });
+        });
+
+        test.describe('When configure Elastic Agent step has finished', () => {
+          test.beforeEach(async ({ pageObjects: { customLogsPage } }) => {
+            await customLogsPage.updateInstallationStepStatus(
+              onboardingId,
+              'ea-download',
+              'complete'
+            );
+            await customLogsPage.updateInstallationStepStatus(
+              onboardingId,
+              'ea-extract',
+              'complete'
+            );
+            await customLogsPage.updateInstallationStepStatus(
+              onboardingId,
+              'ea-install',
+              'complete'
+            );
+            await customLogsPage.updateInstallationStepStatus(
+              onboardingId,
+              'ea-status',
+              'complete',
+              {
+                agentId: 'test-agent-id',
+              }
+            );
+            await customLogsPage.updateInstallationStepStatus(
+              onboardingId,
+              'ea-config',
+              'complete'
+            );
+          });
+
+          test('shows loading callout when logs are being checked', async ({ page }) => {
+            await expect(
+              page.locator(
+                '[data-test-subj="obltOnboardingCheckLogsStep"] .euiStep__titleWrapper [class$="euiStepNumber-s-loading"]'
+              )
+            ).toBeVisible();
+            await expect(
+              page.locator('.euiStep__title', { hasText: 'Waiting for logs to be shipped...' })
+            ).toBeVisible();
+          });
+        });
+      });
+
+      test.describe('When user select Windows', () => {
+        test.beforeEach(async ({ pageObjects: { customLogsPage } }) => {
+          await customLogsPage.windowsCodeSnippetButton.click();
+        });
+
+        test('step is disabled', async ({ pageObjects: { customLogsPage }, page }) => {
+          await expect(
+            page.locator(
+              '[data-test-subj="obltOnboardingCheckLogsStep"] .euiStep__titleWrapper [class$="euiStepNumber-s-disabled"]'
+            )
+          ).toBeVisible();
+        });
+      });
+    });
+
+    test.describe('When logs are being shipped', () => {
+      test.beforeEach(async ({ page }) => {
+        await page.route('**/progress', (route) => {
+          route.fulfill({
+            status: 200,
+            body: JSON.stringify({
+              progress: {
+                'ea-download': { status: 'complete' },
+                'ea-extract': { status: 'complete' },
+                'ea-install': { status: 'complete' },
+                'ea-status': { status: 'complete' },
+                'ea-config': { status: 'complete' },
+                'logs-ingest': { status: 'complete' },
+              },
+            }),
+          });
+        });
+      });
+
+      test.beforeEach(setupPage({ isAdmin: true }));
+
+      test('shows success callout when logs have arrived to elastic', async ({ page }) => {
+        await expect(
+          page.locator(
+            '[data-test-subj="obltOnboardingCheckLogsStep"] .euiStep__titleWrapper [class$="euiStepNumber-s-complete"]'
+          )
+        ).toBeVisible();
+        await expect(
+          page.locator('.euiStep__title', { hasText: 'Logs are being shipped!' })
+        ).toBeVisible();
+      });
+
+      test('when user clicks on Explore Logs it navigates to observability Discover', async ({
+        page,
+      }) => {
+        await page.locator('[data-test-subj="obltOnboardingExploreLogs"]').click();
+        await expect(page).toHaveURL(/\/app\/discover/);
+      });
+    });
+  }
+);
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/tsconfig.json b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/tsconfig.json
new file mode 100644
index 0000000000000..6f9ee7501fef3
--- /dev/null
+++ b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/tsconfig.json
@@ -0,0 +1,15 @@
+{
+  "extends": "../../../../../../tsconfig.base.json",
+  "compilerOptions": {
+    "outDir": "target/types"
+  },
+  "include": [
+    "**/*"
+  ],
+  "kbn_references": [
+    "@kbn/scout"
+  ],
+  "exclude": [
+    "target/**/*"
+  ]
+}
diff --git a/yarn.lock b/yarn.lock
index a2c801f605f31..25df81fc94b74 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6501,10 +6501,6 @@
   version "0.0.0"
   uid ""
 
-"@kbn/observability-onboarding-e2e@link:x-pack/solutions/observability/plugins/observability_onboarding/e2e":
-  version "0.0.0"
-  uid ""
-
 "@kbn/observability-onboarding-plugin@link:x-pack/solutions/observability/plugins/observability_onboarding":
   version "0.0.0"
   uid ""