Merge openmetadata-java-playwright into openmetadata-integration-tests

Folds the UI integration test module into the canonical integration-tests
module under a `ui-it` Maven profile. One test home, one classpath, no
more test-jar reinstall dance or cross-module IntelliJ classpath quirks.

Why: most of the value the UI test module shipped was reusable backend
infra (factories, search helpers, server harness) that worked fine
without a browser. Keeping it in a separate module forced multiple
unnecessary boundaries — test-jar publication, IntelliJ test-classes-
jar-tests phantom paths, src/test placement for AuthBackend code that
should have been in src/main, "where does this test go?" friction.

Layout in integration-tests:
  org/openmetadata/it/auth/    JwtAuthProvider + AuthBackend / OidcBackend
                                / AuthSession / TokenRefresher / ...
  org/openmetadata/it/server/   ContainerizedServer / ServerHandle /
                                ExternalServer / sso/ profile records
  org/openmetadata/it/search/   ReindexHelpers / SearchClient /
                                SearchAssertions / SearchQueryHelper
  org/openmetadata/it/ui/       SessionBrowser / UiSession /
                                UiSessionExtension / TraceRecorder /
                                ClipboardHelper / pages/
  org/openmetadata/it/scenarios/  *UIIT.java tests
  org/openmetadata/it/util/     SdkClients + UiTestServer / OssTestServer
  org/openmetadata/it/factories/  existing + EntityLoader

Build:
  - integration-tests pom gains com.microsoft.playwright:playwright
    (test scope). Other testcontainers / jwt deps already there.
  - test-jar publish-test-harness includes pattern expanded to ship
    server/, search/, ui/ packages alongside auth/, util/, factories/,
    bootstrap/. Downstream consumers (collate) inherit the full UI
    test harness, not just backend factories.
  - New `ui-it` profile runs `**/*UIIT.java` with skip.embedded.bootstrap
    =true, PW_VIDEO=true, per-method parallel @ 0.5 factor. Mirrors the
    failsafe execution from the old playwright module.
  - Existing parallel-tests executions across all profiles gain a
    `**/*UIIT.java` exclude so embedded-mode IT runs don't pick up UI
    tests they can't run.

Module removal:
  - openmetadata-java-playwright/ deleted.
  - parent pom <modules> entry removed.
  - .github/workflows/java-playwright-nightly.yml updated to build and
    test `openmetadata-integration-tests -P ui-it` instead.

Docs:
  - MIGRATION_TRACKING.md and CONVENTIONS.md from the old module are
    UI_MIGRATION_TRACKING.md / UI_TEST_CONVENTIONS.md at the
    integration-tests root.

No test code semantics changed — pure reorganization. The 4-5 backend-
flavored *UIIT.java tests we identified as misplaced (running against
SDK with vestigial UI checks) still live under scenarios/ for now; a
follow-up will rename them to *IT.java and have them target the
embedded TestSuiteBootstrap directly to drop their ~3-minute Docker boot
overhead.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
mohitdeuex 2026-05-11 19:13:29 +05:30
parent 57f1912cec
commit 74bda64340
58 changed files with 226 additions and 684 deletions

View file

@ -9,12 +9,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# Nightly run of the Java Playwright suite. Runs the same scenarios as the PR
# workflow today; expands in Phase 3 to include the external-mode matrix
# (ES+OS), distributed reindex coordination, and crash-recovery scenarios.
# Tracks EPIC #3731, satisfies tickets #3767 / #3792.
# Nightly run of the UI integration suite (*UIIT.java) — lives inside
# openmetadata-integration-tests under the `ui-it` Maven profile. Expands in
# Phase 3 to include the external-mode matrix (ES + OS), distributed reindex
# coordination, and crash-recovery scenarios. Tracks EPIC #3731 / tickets
# #3767, #3792.
name: Java Playwright (Nightly)
name: UI Integration Tests (Nightly)
on:
schedule:
@ -26,7 +27,7 @@ permissions:
checks: write
jobs:
java-playwright-nightly:
ui-it-nightly:
runs-on: ubuntu-latest
timeout-minutes: 90
strategy:
@ -76,14 +77,14 @@ jobs:
# consistent across actors.
run: echo "127.0.0.1 om-mock-idp" | sudo tee -a /etc/hosts
- name: Build dependencies for Java Playwright module
- name: Build dependencies for integration-tests
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: mvn -DskipTests clean install -pl :openmetadata-java-playwright -am
run: mvn -DskipTests clean install -pl :openmetadata-integration-tests -am
- name: Install Playwright browsers
run: |
mvn -pl :openmetadata-java-playwright dependency:build-classpath -Dmdep.outputFile=/tmp/cp.txt -q
mvn -pl :openmetadata-integration-tests dependency:build-classpath -Dmdep.outputFile=/tmp/cp.txt -q
java -cp "$(cat /tmp/cp.txt)" com.microsoft.playwright.CLI install --with-deps chromium
- name: Free build artifacts
@ -93,17 +94,16 @@ jobs:
rm -rf openmetadata-shaded-deps/*/target
df -h /
- name: Run Java Playwright scenarios (${{ matrix.searchEngine }})
- name: Run UI integration tests (${{ matrix.searchEngine }})
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
JPW_MODE: embedded
run: |
if [ "${{ matrix.searchEngine }}" = "elasticsearch" ]; then
mvn verify -pl :openmetadata-java-playwright \
mvn verify -P ui-it -pl :openmetadata-integration-tests \
-DsearchType=elasticsearch \
-DsearchImage=docker.elastic.co/elasticsearch/elasticsearch:9.3.0
else
mvn verify -pl :openmetadata-java-playwright
mvn verify -P ui-it -pl :openmetadata-integration-tests
fi
- name: Upload Playwright traces
@ -111,7 +111,7 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: playwright-traces-${{ matrix.searchEngine }}-${{ github.run_id }}
path: openmetadata-java-playwright/target/playwright-traces
path: openmetadata-integration-tests/target/playwright-traces
if-no-files-found: ignore
retention-days: 14
@ -120,7 +120,7 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: failsafe-reports-${{ matrix.searchEngine }}-${{ github.run_id }}
path: openmetadata-java-playwright/target/failsafe-reports
path: openmetadata-integration-tests/target/failsafe-reports
if-no-files-found: ignore
retention-days: 14
@ -130,4 +130,4 @@ jobs:
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
fail_on_test_failures: true
report_paths: 'openmetadata-java-playwright/target/failsafe-reports/TEST-*.xml'
report_paths: 'openmetadata-integration-tests/target/failsafe-reports/TEST-*.xml'

View file

@ -160,6 +160,13 @@
<version>4.4.0</version>
<scope>test</scope>
</dependency>
<!-- Playwright Java for UI integration tests (*UIIT.java) -->
<dependency>
<groupId>com.microsoft.playwright</groupId>
<artifactId>playwright</artifactId>
<version>1.49.0</version>
<scope>test</scope>
</dependency>
<!-- RDF support (Apache Jena) for RDF tests -->
<dependency>
<groupId>org.apache.jena</groupId>
@ -208,6 +215,9 @@
<include>org/openmetadata/it/auth/**</include>
<include>org/openmetadata/it/util/**</include>
<include>org/openmetadata/it/factories/**</include>
<include>org/openmetadata/it/server/**</include>
<include>org/openmetadata/it/search/**</include>
<include>org/openmetadata/it/ui/**</include>
<include>org/openmetadata/it/tests/BaseEntityIT*</include>
<include>private_key.der</include>
<include>public_key.der</include>
@ -291,6 +301,7 @@
<exclude>**/SystemResourceIT.java</exclude>
<exclude>**/VectorEmbeddingIntegrationIT.java</exclude>
<exclude>**/GlossaryOntologyExportIT.java</exclude>
<exclude>**/*UIIT.java</exclude>
</excludes>
<systemPropertyVariables>
<databaseType>mysql</databaseType>
@ -383,6 +394,7 @@
<exclude>**/VectorEmbeddingIntegrationIT.java</exclude>
<exclude>**/PatchTableEmbeddingIT.java</exclude>
<exclude>**/GlossaryOntologyExportIT.java</exclude>
<exclude>**/*UIIT.java</exclude>
</excludes>
<systemPropertyVariables>
<databaseType>postgres</databaseType>
@ -477,6 +489,7 @@
<exclude>**/VectorEmbeddingIntegrationIT.java</exclude>
<exclude>**/PatchTableEmbeddingIT.java</exclude>
<exclude>**/GlossaryOntologyExportIT.java</exclude>
<exclude>**/*UIIT.java</exclude>
</excludes>
<systemPropertyVariables>
<databaseType>postgres</databaseType>
@ -568,6 +581,7 @@
<exclude>**/SystemResourceIT.java</exclude>
<exclude>**/VectorEmbeddingIntegrationIT.java</exclude>
<exclude>**/GlossaryOntologyExportIT.java</exclude>
<exclude>**/*UIIT.java</exclude>
</excludes>
<systemPropertyVariables>
<databaseType>postgres</databaseType>
@ -660,6 +674,7 @@
<exclude>**/VectorEmbeddingIntegrationIT.java</exclude>
<exclude>**/PatchTableEmbeddingIT.java</exclude>
<exclude>**/GlossaryOntologyExportIT.java</exclude>
<exclude>**/*UIIT.java</exclude>
</excludes>
<systemPropertyVariables>
<databaseType>mysql</databaseType>
@ -750,6 +765,7 @@
<exclude>**/SystemResourceIT.java</exclude>
<exclude>**/VectorEmbeddingIntegrationIT.java</exclude>
<exclude>**/GlossaryOntologyExportIT.java</exclude>
<exclude>**/*UIIT.java</exclude>
</excludes>
<systemPropertyVariables>
<databaseType>mysql</databaseType>
@ -894,6 +910,7 @@
<exclude>**/SystemResourceIT.java</exclude>
<exclude>**/VectorEmbeddingIntegrationIT.java</exclude>
<exclude>**/GlossaryOntologyExportIT.java</exclude>
<exclude>**/*UIIT.java</exclude>
</excludes>
<systemPropertyVariables>
<enableRdf>true</enableRdf>
@ -923,5 +940,55 @@
</plugins>
</build>
</profile>
<!-- UI integration tests (*UIIT.java). Run with `mvn verify -P ui-it`. Boots the OM
Docker image via ContainerizedServer + Playwright; embedded TestSuiteBootstrap is
skipped. Per-method parallel; tests with global state opt out via @ResourceLock
or @Execution(SAME_THREAD). -->
<profile>
<id>ui-it</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven.failsafe.version}</version>
<executions>
<execution>
<id>ui-scenario-tests</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<forkCount>1</forkCount>
<reuseForks>true</reuseForks>
<argLine>-Xmx4096m -XX:+UseG1GC</argLine>
<includes>
<include>**/*UIIT.java</include>
</includes>
<systemPropertyVariables>
<skip.embedded.bootstrap>true</skip.embedded.bootstrap>
<!-- Video recording on by default while the suite is young — captures
each run to target/playwright-videos/ for triage. Disable per-run
with -DPW_VIDEO=false. -->
<PW_VIDEO>true</PW_VIDEO>
<junit.jupiter.extensions.autodetection.enabled>true</junit.jupiter.extensions.autodetection.enabled>
<junit.jupiter.execution.parallel.enabled>true</junit.jupiter.execution.parallel.enabled>
<junit.jupiter.execution.parallel.mode.default>concurrent</junit.jupiter.execution.parallel.mode.default>
<junit.jupiter.execution.parallel.mode.classes.default>same_thread</junit.jupiter.execution.parallel.mode.classes.default>
<junit.jupiter.execution.parallel.config.strategy>dynamic</junit.jupiter.execution.parallel.config.strategy>
<junit.jupiter.execution.parallel.config.dynamic.factor>0.5</junit.jupiter.execution.parallel.config.dynamic.factor>
</systemPropertyVariables>
<trimStackTrace>false</trimStackTrace>
<reportFormat>plain</reportFormat>
<useFile>true</useFile>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.auth;
package org.openmetadata.it.auth;
import com.microsoft.playwright.BrowserContext;
import java.util.Locale;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.auth;
package org.openmetadata.it.auth;
import static org.junit.jupiter.api.Assumptions.assumeTrue;

View file

@ -1,10 +1,10 @@
package org.openmetadata.jpw.auth;
package org.openmetadata.it.auth;
import com.microsoft.playwright.BrowserContext;
import java.util.Map;
import org.openmetadata.jpw.server.ServerHandle;
import org.openmetadata.jpw.server.sso.MockOidcServer;
import org.openmetadata.jpw.server.sso.SsoProfile;
import org.openmetadata.it.server.ServerHandle;
import org.openmetadata.it.server.sso.MockOidcServer;
import org.openmetadata.it.server.sso.SsoProfile;
/**
* One auth backend = one way OM is configured to authenticate, plus how tokens are

View file

@ -1,10 +1,10 @@
package org.openmetadata.jpw.auth;
package org.openmetadata.it.auth;
import java.util.Locale;
import org.openmetadata.jpw.server.sso.ClientType;
import org.openmetadata.jpw.server.sso.CustomOidcProfile;
import org.openmetadata.jpw.server.sso.GoogleProfile;
import org.openmetadata.jpw.server.sso.OktaProfile;
import org.openmetadata.it.server.sso.ClientType;
import org.openmetadata.it.server.sso.CustomOidcProfile;
import org.openmetadata.it.server.sso.GoogleProfile;
import org.openmetadata.it.server.sso.OktaProfile;
/**
* Resolves the JVM's active {@link AuthBackend} from the {@code jpw.auth} system property

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.auth;
package org.openmetadata.it.auth;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;

View file

@ -1,13 +1,13 @@
package org.openmetadata.jpw.auth;
package org.openmetadata.it.auth;
import com.microsoft.playwright.BrowserContext;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import org.openmetadata.it.auth.JwtAuthProvider;
import org.openmetadata.jpw.server.ServerHandle;
import org.openmetadata.jpw.server.sso.MockOidcServer;
import org.openmetadata.jpw.server.sso.SsoProfile;
import org.openmetadata.it.server.ServerHandle;
import org.openmetadata.it.server.sso.MockOidcServer;
import org.openmetadata.it.server.sso.SsoProfile;
/**
* Default backend OM runs with its built-in JWT auth and tests use admin tokens minted

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.auth;
package org.openmetadata.it.auth;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.auth;
package org.openmetadata.it.auth;
import com.microsoft.playwright.BrowserContext;
import java.net.URI;
@ -15,9 +15,9 @@ import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.openmetadata.jpw.server.ServerHandle;
import org.openmetadata.jpw.server.sso.MockOidcServer;
import org.openmetadata.jpw.server.sso.SsoProfile;
import org.openmetadata.it.server.ServerHandle;
import org.openmetadata.it.server.sso.MockOidcServer;
import org.openmetadata.it.server.sso.SsoProfile;
/**
* Single OIDC backend works for any {@link SsoProfile} (Google, Okta, custom OIDC) and

View file

@ -1,12 +1,12 @@
package org.openmetadata.jpw.auth;
package org.openmetadata.it.auth;
import java.time.Duration;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.openmetadata.it.util.SdkClients;
import org.openmetadata.jpw.server.ServerHandle;
import org.openmetadata.jpw.server.sso.MockOidcServer;
import org.openmetadata.it.server.ServerHandle;
import org.openmetadata.it.server.sso.MockOidcServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.auth;
package org.openmetadata.it.auth;
import java.time.Duration;
import java.time.Instant;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.scenarios.auth.signin;
package org.openmetadata.it.scenarios.auth.signin;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
@ -6,12 +6,12 @@ import com.microsoft.playwright.Page;
import java.util.regex.Pattern;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.openmetadata.jpw.auth.AuthAssumptions;
import org.openmetadata.jpw.auth.NoPreloadAuth;
import org.openmetadata.jpw.ui.UiSession;
import org.openmetadata.jpw.ui.UiSessionExtension;
import org.openmetadata.jpw.ui.pages.MockIdpLoginPage;
import org.openmetadata.jpw.ui.pages.SignInPage;
import org.openmetadata.it.auth.AuthAssumptions;
import org.openmetadata.it.auth.NoPreloadAuth;
import org.openmetadata.it.ui.UiSession;
import org.openmetadata.it.ui.UiSessionExtension;
import org.openmetadata.it.ui.pages.MockIdpLoginPage;
import org.openmetadata.it.ui.pages.SignInPage;
/**
* End-to-end sign-in flow under the Google SSO confidential-client backend: clicks the

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.scenarios.loader;
package org.openmetadata.it.scenarios.loader;
import static org.assertj.core.api.Assertions.assertThat;
@ -11,7 +11,7 @@ import org.openmetadata.it.factories.EntityLoadSummary;
import org.openmetadata.it.factories.EntityLoader;
import org.openmetadata.it.util.TestNamespace;
import org.openmetadata.it.util.TestNamespaceExtension;
import org.openmetadata.jpw.util.UiTestServer;
import org.openmetadata.it.util.UiTestServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.scenarios.search.reindex;
package org.openmetadata.it.scenarios.search.reindex;
import static org.assertj.core.api.Assertions.assertThat;
@ -18,13 +18,13 @@ import org.openmetadata.it.factories.EntityLoadSummary;
import org.openmetadata.it.factories.EntityLoader;
import org.openmetadata.it.util.TestNamespace;
import org.openmetadata.it.util.TestNamespaceExtension;
import org.openmetadata.jpw.search.ReindexHelpers;
import org.openmetadata.jpw.search.SearchQueryHelper;
import org.openmetadata.jpw.search.SearchQueryHelper.SearchProbe;
import org.openmetadata.jpw.server.ServerHandle;
import org.openmetadata.jpw.ui.UiSession;
import org.openmetadata.jpw.ui.UiSessionExtension;
import org.openmetadata.jpw.ui.pages.SearchIndexAppPage;
import org.openmetadata.it.search.ReindexHelpers;
import org.openmetadata.it.search.SearchQueryHelper;
import org.openmetadata.it.search.SearchQueryHelper.SearchProbe;
import org.openmetadata.it.server.ServerHandle;
import org.openmetadata.it.ui.UiSession;
import org.openmetadata.it.ui.UiSessionExtension;
import org.openmetadata.it.ui.pages.SearchIndexAppPage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.scenarios.search.reindex;
package org.openmetadata.it.scenarios.search.reindex;
import static org.assertj.core.api.Assertions.assertThat;
@ -19,14 +19,13 @@ import org.openmetadata.it.factories.EntityLoadSummary;
import org.openmetadata.it.factories.EntityLoader;
import org.openmetadata.it.util.TestNamespace;
import org.openmetadata.it.util.TestNamespaceExtension;
import org.openmetadata.jpw.search.ReindexHelpers;
import org.openmetadata.jpw.search.SearchQueryHelper;
import org.openmetadata.jpw.search.SearchQueryHelper.SearchProbe;
import org.openmetadata.jpw.server.ServerHandle;
import org.openmetadata.jpw.ui.UiSession;
import org.openmetadata.jpw.ui.UiSessionExtension;
import org.openmetadata.jpw.ui.pages.SearchIndexAppPage;
import org.openmetadata.jpw.util.UiTestServer;
import org.openmetadata.it.search.ReindexHelpers;
import org.openmetadata.it.search.SearchQueryHelper;
import org.openmetadata.it.search.SearchQueryHelper.SearchProbe;
import org.openmetadata.it.server.ServerHandle;
import org.openmetadata.it.ui.UiSession;
import org.openmetadata.it.ui.UiSessionExtension;
import org.openmetadata.it.ui.pages.SearchIndexAppPage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.scenarios.search.reindex;
package org.openmetadata.it.scenarios.search.reindex;
import java.time.Duration;
import java.util.Map;
@ -12,11 +12,11 @@ import org.openmetadata.it.factories.EntityLoadSummary;
import org.openmetadata.it.factories.EntityLoader;
import org.openmetadata.it.util.TestNamespace;
import org.openmetadata.it.util.TestNamespaceExtension;
import org.openmetadata.jpw.ui.UiSession;
import org.openmetadata.jpw.ui.UiSessionExtension;
import org.openmetadata.jpw.ui.pages.ExplorePage;
import org.openmetadata.jpw.ui.pages.ExplorePage.Tab;
import org.openmetadata.jpw.ui.pages.SearchIndexAppPage;
import org.openmetadata.it.ui.UiSession;
import org.openmetadata.it.ui.UiSessionExtension;
import org.openmetadata.it.ui.pages.ExplorePage;
import org.openmetadata.it.ui.pages.ExplorePage.Tab;
import org.openmetadata.it.ui.pages.SearchIndexAppPage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.scenarios.sso;
package org.openmetadata.it.scenarios.sso;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -10,13 +10,13 @@ import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.openmetadata.jpw.server.ContainerizedServer;
import org.openmetadata.jpw.server.sso.ClientType;
import org.openmetadata.jpw.server.sso.GoogleProfile;
import org.openmetadata.it.server.ContainerizedServer;
import org.openmetadata.it.server.sso.ClientType;
import org.openmetadata.it.server.sso.GoogleProfile;
/**
* End-to-end wiring check for SSO mode: launches OM with the Google confidential-client
* profile and the {@link org.openmetadata.jpw.server.sso.MockOidcServer} sidecar, then
* profile and the {@link org.openmetadata.it.server.sso.MockOidcServer} sidecar, then
* fetches OM's public {@code /api/v1/system/config/auth} endpoint to confirm OM picked up
* the SSO env vars at boot provider {@code google}, client type {@code confidential},
* authority pointing at the mock IdP under the {@code om-mock-idp} hostname.

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.scenarios.sso;
package org.openmetadata.it.scenarios.sso;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -10,7 +10,7 @@ import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.openmetadata.jpw.server.sso.MockOidcServer;
import org.openmetadata.it.server.sso.MockOidcServer;
import org.testcontainers.containers.Network;
/**

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.scenarios.ui.smoke;
package org.openmetadata.it.scenarios.ui.smoke;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
@ -8,9 +8,9 @@ import org.openmetadata.it.factories.DatabaseSchemaTestFactory;
import org.openmetadata.it.factories.TableTestFactory;
import org.openmetadata.it.util.TestNamespace;
import org.openmetadata.it.util.TestNamespaceExtension;
import org.openmetadata.jpw.ui.UiSession;
import org.openmetadata.jpw.ui.UiSessionExtension;
import org.openmetadata.jpw.ui.pages.TablePage;
import org.openmetadata.it.ui.UiSession;
import org.openmetadata.it.ui.UiSessionExtension;
import org.openmetadata.it.ui.pages.TablePage;
import org.openmetadata.schema.entity.data.DatabaseSchema;
import org.openmetadata.schema.entity.data.Table;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.scenarios.ui.topic;
package org.openmetadata.it.scenarios.ui.topic;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
@ -7,9 +7,9 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.openmetadata.it.factories.TopicTestFactory;
import org.openmetadata.it.util.TestNamespace;
import org.openmetadata.it.util.TestNamespaceExtension;
import org.openmetadata.jpw.ui.UiSession;
import org.openmetadata.jpw.ui.UiSessionExtension;
import org.openmetadata.jpw.ui.pages.TopicPage;
import org.openmetadata.it.ui.UiSession;
import org.openmetadata.it.ui.UiSessionExtension;
import org.openmetadata.it.ui.pages.TopicPage;
import org.openmetadata.schema.entity.data.Topic;
/**

View file

@ -1,11 +1,11 @@
package org.openmetadata.jpw.search;
package org.openmetadata.it.search;
import java.time.Duration;
import java.util.Map;
import java.util.Set;
import org.awaitility.Awaitility;
import org.awaitility.core.ConditionTimeoutException;
import org.openmetadata.jpw.server.ServerHandle;
import org.openmetadata.it.server.ServerHandle;
import org.openmetadata.schema.entity.app.AppRunRecord;
import org.openmetadata.sdk.network.HttpClient;
import org.openmetadata.sdk.network.HttpMethod;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.search;
package org.openmetadata.it.search;
import static org.assertj.core.api.Assertions.assertThat;
@ -7,7 +7,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.openmetadata.jpw.server.ServerHandle;
import org.openmetadata.it.server.ServerHandle;
/**
* Assertions over the live search engine index existence, doc counts, alias resolution,

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.search;
package org.openmetadata.it.search;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@ -8,7 +8,7 @@ import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import org.openmetadata.jpw.server.ServerHandle;
import org.openmetadata.it.server.ServerHandle;
/**
* Thin JSON-over-HTTP client for the search engine (works against ES and OpenSearch).

View file

@ -1,11 +1,11 @@
package org.openmetadata.jpw.search;
package org.openmetadata.it.search;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.openmetadata.jpw.server.ServerHandle;
import org.openmetadata.it.server.ServerHandle;
import org.openmetadata.sdk.network.HttpClient;
import org.openmetadata.sdk.network.HttpMethod;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.server;
package org.openmetadata.it.server;
import com.github.dockerjava.api.model.ExposedPort;
import com.github.dockerjava.api.model.HealthCheck;
@ -13,8 +13,8 @@ import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import org.openmetadata.jpw.server.sso.MockOidcServer;
import org.openmetadata.jpw.server.sso.SsoProfile;
import org.openmetadata.it.server.sso.MockOidcServer;
import org.openmetadata.it.server.sso.SsoProfile;
import org.openmetadata.sdk.client.OpenMetadataClient;
import org.openmetadata.sdk.config.OpenMetadataConfig;
import org.opensearch.testcontainers.OpensearchContainer;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.server;
package org.openmetadata.it.server;
import java.net.URI;
import java.util.Locale;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.server;
package org.openmetadata.it.server;
import java.net.URI;
import java.util.Objects;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.server.sso;
package org.openmetadata.it.server.sso;
/**
* OAuth2 client type selects between {@code response_type=id_token} (browser receives

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.server.sso;
package org.openmetadata.it.server.sso;
import java.util.Map;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.server.sso;
package org.openmetadata.it.server.sso;
import com.github.dockerjava.api.model.ExposedPort;
import com.github.dockerjava.api.model.PortBinding;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.server.sso;
package org.openmetadata.it.server.sso;
import java.util.HashMap;
import java.util.Map;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.server.sso;
package org.openmetadata.it.server.sso;
import java.util.Map;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.server.sso;
package org.openmetadata.it.server.sso;
import java.util.Map;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.ui;
package org.openmetadata.it.ui;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Locator.ClickOptions;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.ui;
package org.openmetadata.it.ui;
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserType;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.ui;
package org.openmetadata.it.ui;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.Tracing;

View file

@ -1,8 +1,8 @@
package org.openmetadata.jpw.ui;
package org.openmetadata.it.ui;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.Page;
import org.openmetadata.jpw.server.ServerHandle;
import org.openmetadata.it.server.ServerHandle;
/**
* Per-test handle around a fresh {@link BrowserContext} pre-authenticated for the OM UI.

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.ui;
package org.openmetadata.it.ui;
import com.microsoft.playwright.Browser.NewContextOptions;
import com.microsoft.playwright.BrowserContext;
@ -15,10 +15,10 @@ import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.openmetadata.jpw.auth.AuthSession;
import org.openmetadata.jpw.auth.NoPreloadAuth;
import org.openmetadata.jpw.server.ServerHandle;
import org.openmetadata.jpw.util.UiTestServer;
import org.openmetadata.it.auth.AuthSession;
import org.openmetadata.it.auth.NoPreloadAuth;
import org.openmetadata.it.server.ServerHandle;
import org.openmetadata.it.util.UiTestServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.ui.pages;
package org.openmetadata.it.ui.pages;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
@ -7,7 +7,7 @@ import com.microsoft.playwright.assertions.PlaywrightAssertions;
import com.microsoft.playwright.options.WaitForSelectorState;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import org.openmetadata.jpw.ui.UiSession;
import org.openmetadata.it.ui.UiSession;
/**
* Page object for {@code /explore/<tab>} the entity discovery surface.

View file

@ -1,9 +1,9 @@
package org.openmetadata.jpw.ui.pages;
package org.openmetadata.it.ui.pages;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.options.AriaRole;
import org.openmetadata.jpw.ui.UiSession;
import org.openmetadata.it.ui.UiSession;
/**
* Page object for {@code navikt/mock-oauth2-server}'s interactive login form. Reached by

View file

@ -1,8 +1,8 @@
package org.openmetadata.jpw.ui.pages;
package org.openmetadata.it.ui.pages;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import org.openmetadata.jpw.ui.UiSession;
import org.openmetadata.it.ui.UiSession;
/**
* Base class for OM UI page objects.

View file

@ -1,4 +1,4 @@
package org.openmetadata.jpw.ui.pages;
package org.openmetadata.it.ui.pages;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Locator.WaitForOptions;
@ -6,7 +6,7 @@ import com.microsoft.playwright.Page;
import com.microsoft.playwright.assertions.PlaywrightAssertions;
import com.microsoft.playwright.options.WaitForSelectorState;
import java.time.Duration;
import org.openmetadata.jpw.ui.UiSession;
import org.openmetadata.it.ui.UiSession;
/**
* Page object for {@code /settings/apps/SearchIndexingApplication} the Search Indexing

View file

@ -1,9 +1,9 @@
package org.openmetadata.jpw.ui.pages;
package org.openmetadata.it.ui.pages;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.options.AriaRole;
import org.openmetadata.jpw.ui.UiSession;
import org.openmetadata.it.ui.UiSession;
/**
* Page object for the OM sign-in surface ({@code /signin}). Exposes both the basic-auth

View file

@ -1,8 +1,8 @@
package org.openmetadata.jpw.ui.pages;
package org.openmetadata.it.ui.pages;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import org.openmetadata.jpw.ui.UiSession;
import org.openmetadata.it.ui.UiSession;
/**
* Page object for {@code /table/<fqn>} a single table's details page.

View file

@ -1,8 +1,8 @@
package org.openmetadata.jpw.ui.pages;
package org.openmetadata.it.ui.pages;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import org.openmetadata.jpw.ui.UiSession;
import org.openmetadata.it.ui.UiSession;
/**
* Page object for {@code /topic/<fqn>} a single topic's details page.

View file

@ -1,9 +1,9 @@
package org.openmetadata.jpw.util;
package org.openmetadata.it.util;
import java.net.URI;
import org.openmetadata.it.bootstrap.TestSuiteBootstrap;
import org.openmetadata.it.util.SdkClients;
import org.openmetadata.jpw.server.ServerHandle;
import org.openmetadata.it.server.ServerHandle;
/**
* Builds a {@link ServerHandle} backed by the embedded OpenMetadata test stack.

View file

@ -1,15 +1,15 @@
package org.openmetadata.jpw.util;
package org.openmetadata.it.util;
import org.openmetadata.it.util.SdkClients;
import org.openmetadata.jpw.auth.AuthBackend;
import org.openmetadata.jpw.auth.AuthBackends;
import org.openmetadata.jpw.auth.AuthSession;
import org.openmetadata.jpw.auth.TokenRefresher;
import org.openmetadata.jpw.auth.TokenSet;
import org.openmetadata.jpw.server.ContainerizedServer;
import org.openmetadata.jpw.server.ExternalServer;
import org.openmetadata.jpw.server.ServerHandle;
import org.openmetadata.jpw.server.sso.MockOidcServer;
import org.openmetadata.it.auth.AuthBackend;
import org.openmetadata.it.auth.AuthBackends;
import org.openmetadata.it.auth.AuthSession;
import org.openmetadata.it.auth.TokenRefresher;
import org.openmetadata.it.auth.TokenSet;
import org.openmetadata.it.server.ContainerizedServer;
import org.openmetadata.it.server.ExternalServer;
import org.openmetadata.it.server.ServerHandle;
import org.openmetadata.it.server.sso.MockOidcServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View file

@ -1,15 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>[%thread] %-5level %logger{5} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.openmetadata.it" level="INFO" />
<logger name="org.openmetadata.service" level="WARN" />
<logger name="org.testcontainers" level="INFO" />
<logger name="org.elasticsearch" level="WARN" />
<logger name="org.opensearch" level="WARN" />
<logger name="om-server-container" level="INFO" />
<root level="WARN">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View file

@ -1,148 +0,0 @@
# openmetadata-java-playwright
Java-driven end-to-end scenario suite for OpenMetadata. Boots a real server, seeds data via the SDK, and validates backend behaviour — reindex, search, ingestion, governance — with optional Playwright-Java browser checks.
> Tracks EPIC [#3731](https://github.com/open-metadata/openmetadata-collate/issues/3731). Satisfies open tickets [#3767](https://github.com/open-metadata/openmetadata-collate/issues/3767) (e2e suite for SearchIndexingApplication) and [#3792](https://github.com/open-metadata/openmetadata-collate/issues/3792) (Playwright nightly suite for search scenarios).
## Why a separate module?
| Existing | Gap this module fills |
|---|---|
| `openmetadata-integration-tests` | API CRUD, isolated entity tests. Can't easily express "seed → trigger reindex → assert engine state → verify in UI" scenarios. |
| `openmetadata-ui` Playwright (TS) | Frontend perspective, written by UI engineers. Misses backend edge cases that are obvious to backend engineers (orchestrator failure paths, alias swaps, distributed coordination). |
This module is the backend engineer's scenario suite. Same Testcontainers + SDK harness as `openmetadata-integration-tests` (via test-jar dependency), plus Playwright-Java for the cases that need a browser.
## Modes
The module ships with two execution modes, selected by the `JPW_MODE` environment variable. Backend reindex scenarios use embedded mode (fast, hermetic). UI scenarios use external mode (real UI bundle served).
### Embedded (default — backend scenarios)
`TestSuiteBootstrap` (reused from `openmetadata-integration-tests`) starts MySQL/PostgreSQL + Elasticsearch/OpenSearch via Testcontainers and boots `OpenMetadataApplication` in-JVM via `DropwizardAppExtension`. Tests connect via SDK using JWT-cached `SdkClients.adminClient()`.
- Boot time: ~3060s
- Debuggable: set a breakpoint in `SearchIndexApp` and the IDE debugger will hit it
- Limitation: no UI bundle is served — UI scenarios skip via `@DisabledIfEnvironmentVariable(named = "JPW_MODE", matches = "external")` running in reverse
### External (UI + future distributed/crash scenarios)
Tests connect to an already-running stack. Phase 1 supports this for UI scenarios; later phases will add distributed reindex, crash recovery, and ingestion E2E here.
When `JPW_MODE=external` is set:
- The embedded `TestSuiteBootstrap` skips its boot (no Testcontainers spin-up)
- Embedded scenarios are skipped via `@DisabledIfEnvironmentVariable`
- UI scenarios are enabled via `@EnabledIfEnvironmentVariable`
- `ExternalServer.fromEnv()` reads `OM_URL` + `OM_ADMIN_TOKEN` and builds the SDK client
## Layout
```
openmetadata-java-playwright/
src/main/java/org/openmetadata/jpw/
server/ServerHandle.java connection details (URL, SDK client, search engine endpoint)
search/ReindexHelpers.java trigger SearchIndexingApplication + Awaitility wait
search/SearchClient.java stdlib HTTP client to the search engine
search/SearchAssertions.java doc count, alias→index, presence/absence assertions
ui/PlaywrightFixture.java browser session lifecycle + traces
src/test/java/org/openmetadata/jpw/
util/OssTestServer.java builds a ServerHandle from TestSuiteBootstrap
scenarios/search/reindex/ Phase 1 scenarios
```
The harness lives in `src/main/java` so the Collate module (`collate-java-playwright`) can depend on it directly.
## Running locally
### One-time setup
```bash
# Build everything the module needs
mvn -DskipTests clean install -pl :openmetadata-java-playwright -am
# Install Playwright browsers (one-time per machine; UI scenarios need it, backend ones don't)
mvn -pl :openmetadata-java-playwright dependency:build-classpath -Dmdep.outputFile=/tmp/cp.txt -q
java -cp "$(cat /tmp/cp.txt)" com.microsoft.playwright.CLI install chromium
```
### Backend scenarios (embedded mode)
```bash
# All backend scenarios, OpenSearch (default)
mvn verify -pl :openmetadata-java-playwright
# Elasticsearch instead
mvn verify -pl :openmetadata-java-playwright \
-DsearchType=elasticsearch \
-DsearchImage=docker.elastic.co/elasticsearch/elasticsearch:9.3.0
# Single scenario
mvn verify -pl :openmetadata-java-playwright -Dit.test=FullReindexFromCleanStateIT
```
### UI scenarios
UI scenarios are **transparent**`mvn verify -Dit.test='*UIIT'` just works. `UiTestServer` auto-picks the right backing stack:
| If you set... | UI tests run against |
|---|---|
| Nothing (default) | A freshly-built containerized stack (MySQL + OpenSearch + the OM server image built from your local `openmetadata-dist` tarball). First run ~5 min for the dist build, ~2 min for image build + container boot. Subsequent runs reuse Docker layer cache. |
| `OM_URL` + `OM_ADMIN_TOKEN` | Whatever stack those vars point at (e.g. a `./docker/run_local_docker.sh` you already have running). |
| `OM_TEST_IMAGE=openmetadata/server:1.11.4` | A containerized stack using that pre-built image instead of building one from local code. Useful for testing against released versions. |
```bash
# 1) Just run it. First time will build the dist tarball (~5 min) and the image.
mvn verify -pl :openmetadata-java-playwright -Dit.test='*UIIT'
```
That's it. The test seeds a table via the SDK, triggers `SearchIndexingApplication`, opens Chromium, navigates to Explore, types the table name, presses Enter, asserts the table appears.
### Iterating against a stack you already have running
If you already have `./docker/run_local_docker.sh -m ui -d mysql` going, point the test at it and skip the rebuild:
```bash
export OM_URL=http://localhost:8585
export OM_ADMIN_TOKEN='<JWT from UI: Settings Bots ingestion-bot Token>'
mvn verify -pl :openmetadata-java-playwright -Dit.test='*UIIT'
```
`UiTestServer` detects the env vars and uses them automatically.
### Watching the browser
Edit `PlaywrightFixture.java` line 51, change `setHeadless(true)``setHeadless(false).setSlowMo(300)`. Re-run; Chromium pops up.
### Skipping the wasted embedded boot when only running UI tests
By default, when you run `mvn verify`, the `TestSuiteBootstrap` LauncherSessionListener fires and boots an embedded MySQL+OpenSearch even if you filter to UI tests. Suppress it with:
```bash
mvn verify -pl :openmetadata-java-playwright -Dit.test='*UIIT' -Dskip.embedded.bootstrap=true
```
## Adding a scenario
1. Pick (or create) a sub-package under `src/test/java/org/openmetadata/jpw/scenarios/`.
2. Name the class `<Behaviour>IT.java` so failsafe picks it up.
3. Use `@Execution(SAME_THREAD)` if your scenario triggers the SearchIndexingApplication (it's a shared resource).
4. Build a `ServerHandle` once in `@BeforeAll` via `OssTestServer.defaultHandle()`.
5. Seed via `*TestFactory` classes from `openmetadata-integration-tests` (already on the classpath).
6. Drive search via `ReindexHelpers`, assert via `SearchAssertions`.
7. Reference the EPIC sub-issue(s) the scenario protects against in the class Javadoc.
## CI
| Workflow | Trigger | What it runs |
|---|---|---|
| `java-playwright-pr.yml` | Path-filtered PR + `run-java-playwright` label + dispatch | Embedded mode, OpenSearch only, fast subset |
| `java-playwright-nightly.yml` | Cron `0 2 * * *` + dispatch | Embedded mode, ES + OS matrix; expands in Phase 3 to external mode |
Path filter triggers on changes to `openmetadata-service/src/.../searchIndex/**`, `.../search/**`, the spec, the SDK search service, the integration-tests bootstrap, and this module itself.
## Phasing
- **Phase 1 (this PR)**: skeleton, harness, 3 reindex scenarios, embedded mode, CI wiring.
- **Phase 2**: scenarios for buckets D (stats), E (ES/OS parity), F (query correctness), G (lifecycle), I (column embeddings), J (permissions). UI scenarios (search after reindex appears in Explore).
- **Phase 3**: external mode (`docker-compose-e2e.yml` + `ExternalServer`), distributed reindex (#25058, #3750, #3757), crash recovery, perf smoke (#3961).
- **Phase 4+**: ingestion E2E, governance, lineage.

View file

@ -1,238 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>platform</artifactId>
<groupId>org.open-metadata</groupId>
<version>1.12.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>openmetadata-java-playwright</artifactId>
<name>OpenMetadata Java Playwright Scenario Tests</name>
<description>
Java-driven end-to-end scenario suite for OpenMetadata. Boots a real server
(embedded or external), seeds data via the SDK, and validates backend
behaviour — reindex, search, ingestion, governance — with optional
Playwright-Java browser checks. Satisfies EPIC #3731 / tickets #3767, #3792.
</description>
<packaging>jar</packaging>
<properties>
<maven.surefire.version>3.1.2</maven.surefire.version>
<maven.failsafe.version>3.1.2</maven.failsafe.version>
<playwright.version>1.49.0</playwright.version>
</properties>
<dependencies>
<!-- Harness deps (compile scope: harness is consumed by Collate's java-playwright module too) -->
<dependency>
<groupId>org.open-metadata</groupId>
<artifactId>openmetadata-sdk</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.27.7</version>
</dependency>
<dependency>
<groupId>com.microsoft.playwright</groupId>
<artifactId>playwright</artifactId>
<version>${playwright.version}</version>
</dependency>
<!-- Testcontainers — needed at compile because ContainerizedServer (src/main) wraps them. -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.21.4</version>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mysql</artifactId>
<version>1.21.4</version>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>1.21.4</version>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>k3s</artifactId>
<version>1.21.4</version>
</dependency>
<dependency>
<groupId>org.opensearch</groupId>
<artifactId>opensearch-testcontainers</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-api</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${org.junit.jupiter.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- Test scope: integration-tests harness (TestSuiteBootstrap LauncherSessionListener auto-fires) -->
<dependency>
<groupId>org.open-metadata</groupId>
<artifactId>openmetadata-integration-tests</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<!-- Forces -am to build openmetadata-dist (which produces the tar.gz the docker image needs).
Marked optional so this artifact isn't placed on our classpath. -->
<dependency>
<groupId>org.open-metadata</groupId>
<artifactId>openmetadata-dist</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.open-metadata</groupId>
<artifactId>openmetadata-service</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>elasticsearch</artifactId>
<version>1.21.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.21.4</version>
<scope>test</scope>
</dependency>
<!-- Required so TestSuiteBootstrap (loaded via ServiceLoader) class-verifies even when
we suppress its execution. It transitively imports DropwizardAppExtension, Jdbi,
Apache HttpClient5, JWT, etc. -->
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-testing</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${org.junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven.failsafe.version}</version>
<executions>
<!-- Embedded-mode IT (no UI). Uses TestSuiteBootstrap to start the OM server in-JVM.
Excludes UI tests so we don't double-bootstrap. -->
<execution>
<id>scenario-tests</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<forkCount>1</forkCount>
<reuseForks>true</reuseForks>
<argLine>-Xmx4096m -XX:+UseG1GC</argLine>
<includes>
<include>**/*IT.java</include>
</includes>
<excludes>
<exclude>**/*UIIT.java</exclude>
</excludes>
<systemPropertyVariables>
<databaseType>mysql</databaseType>
<databaseImage>mysql:8.3.0</databaseImage>
<searchType>opensearch</searchType>
<searchImage>opensearchproject/opensearch:2.13.0</searchImage>
<junit.jupiter.extensions.autodetection.enabled>true</junit.jupiter.extensions.autodetection.enabled>
</systemPropertyVariables>
</configuration>
</execution>
<!-- UI integration tests. Brings its own server via UiTestServer (containerized or
external) and Playwright; embedded TestSuiteBootstrap is skipped. Per-method
parallel; tests with global state must use @ResourceLock or @Execution(SAME_THREAD). -->
<execution>
<id>ui-scenario-tests</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<forkCount>1</forkCount>
<reuseForks>true</reuseForks>
<argLine>-Xmx4096m -XX:+UseG1GC</argLine>
<includes>
<include>**/*UIIT.java</include>
</includes>
<systemPropertyVariables>
<skip.embedded.bootstrap>true</skip.embedded.bootstrap>
<!-- Video recording on by default while the suite is young — captures
each run to target/playwright-videos/ for triage. Disable per-run with
-DPW_VIDEO=false. -->
<PW_VIDEO>true</PW_VIDEO>
<junit.jupiter.extensions.autodetection.enabled>true</junit.jupiter.extensions.autodetection.enabled>
<junit.jupiter.execution.parallel.enabled>true</junit.jupiter.execution.parallel.enabled>
<junit.jupiter.execution.parallel.mode.default>concurrent</junit.jupiter.execution.parallel.mode.default>
<junit.jupiter.execution.parallel.mode.classes.default>same_thread</junit.jupiter.execution.parallel.mode.classes.default>
<junit.jupiter.execution.parallel.config.strategy>dynamic</junit.jupiter.execution.parallel.config.strategy>
<junit.jupiter.execution.parallel.config.dynamic.factor>0.5</junit.jupiter.execution.parallel.config.dynamic.factor>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.openmetadata.jpw" level="INFO" />
<logger name="org.openmetadata.it" level="INFO" />
<logger name="org.openmetadata.service" level="WARN" />
<logger name="org.testcontainers" level="INFO" />
<logger name="org.elasticsearch" level="WARN" />
<logger name="org.opensearch" level="WARN" />
<logger name="om-server-container" level="INFO" />
<root level="WARN">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View file

@ -1,121 +0,0 @@
clusterName: openmetadata
swagger:
resourcePackage: org.openmetadata.service.webservice.resources
server:
rootPath: '/api/*'
enableVirtualThreads: true
applicationConnectors:
- type: http
port: 0
uriCompliance: UNSAFE
adminConnectors:
- type: http
port: 0
logging:
level: INFO
appenders:
- type: console
layout:
type: om-event-layout
format: ${LOG_FORMAT:-text}
appendLineSeparator: true
database:
driverClass: org.postgresql.Driver
user: test
password:
url: jdbc:postgresql://localhost:5432/openmetadata
# Optimized for single JVM with method-level parallelization
# Dynamic factor 1.0 = ~8 threads on 8-core, need sufficient connections
maxSize: 100
minSize: 20
initialSize: 20
checkConnectionWhileIdle: true
checkConnectionOnBorrow: true
evictionInterval: 30 seconds
minIdleTime: 10 seconds
validationQuery: "SELECT 1"
maxWaitForConnection: 30 seconds
migrationConfiguration:
flywayPath: "../bootstrap/sql/migrations/flyway"
nativePath: "../bootstrap/sql/migrations/native"
extensionPath: ""
secretsManagerConfiguration:
secretsManager: db
tags: []
health:
delayedShutdownHandlerEnabled: true
shutdownWaitPeriod: 5s
healthChecks:
- name: OpenMetadataServerHealthCheck
critical: true
authorizerConfiguration:
className: "org.openmetadata.service.security.DefaultAuthorizer"
containerRequestFilter: "org.openmetadata.service.security.JwtFilter"
adminPrincipals:
- "admin"
testPrincipals:
- "test"
principalDomain: "open-metadata.org"
enforcePrincipalDomain: false
enableSecureSocketConnection: false
allowedEmailRegistrationDomains:
- "all"
authenticationConfiguration:
clientType: "public"
provider: "openmetadata"
providerName: ""
publicKeyUrls:
- "https://www.googleapis.com/oauth2/v3/certs"
authority: "https://accounts.google.com"
clientId: "dummy"
callbackUrl: "http://localhost:8585/callback"
jwtPrincipalClaims:
- "email"
- "preferred_username"
- "sub"
enableSelfSignup : true
jwtTokenConfiguration:
rsapublicKeyFilePath: "src/test/resources/public_key.der"
rsaprivateKeyFilePath: "src/test/resources/private_key.der"
jwtissuer: "open-metadata.org"
keyId: "test-key"
eventHandlerConfiguration:
eventHandlerClassNames:
- "org.openmetadata.service.events.AuditEventHandler"
- "org.openmetadata.service.events.ChangeEventHandler"
eventMonitoringConfiguration:
eventMonitor: "prometheus"
batchSize: 10
pathPattern: ["/*"]
latency: [0.90]
pipelineServiceClientConfiguration:
className: "org.openmetadata.service.clients.pipeline.airflow.AirflowRESTClient"
metadataApiEndpoint: http://localhost:8585/api
apiEndpoint: http://localhost:8080
hostIp: ""
healthCheckInterval: 300
verifySSL: "no-ssl"
authProvider: "openmetadata"
parameters:
username: admin
password: admin
timeout: 10
truststorePath: ""
truststorePassword: ""
fernetConfiguration:
fernetKey: ihZpp5gmmDvVsgoOG6OVivKWwC9vd5JQ
objectStorage:
enabled: false
provider: NOOP
maxFileSize: 5242880
# RDF Configuration - will be dynamically configured by TestSuiteBootstrap
rdf:
enabled: false
baseUri: "https://open-metadata.org/"
storageType: "FUSEKI"
remoteEndpoint: "http://localhost:3030/openmetadata"
username: "admin"
password: "test-admin"
dataset: "openmetadata"

View file

@ -36,7 +36,6 @@
<module>openmetadata-service</module>
<module>openmetadata-k8s-operator</module>
<module>openmetadata-integration-tests</module>
<module>openmetadata-java-playwright</module>
<module>openmetadata-mcp</module>
<module>openmetadata-ui-core-components</module>
<module>openmetadata-ui</module>