OpenMetadata/openmetadata-integration-tests
Sriharsha Chintalapani 897f9cfd1b
Add changeSummary API endpoint and UI components (#26533)
* Add changeSummary API endpoint and UI components for description source tracking

Add a new /v1/changeSummary/{entityType}/{id|name/fqn} endpoint that
returns per-field change metadata (who changed it, source type, timestamp).
Supports fieldPrefix filtering for column-level queries on large tables
and limit/offset pagination.

UI additions:
- DescriptionSourceBadge component showing AI badge on AI-generated descriptions
- useChangeSummary hook for fetching change summary data
- changeSummaryAPI REST client
- "accepted-by" translation key

Integration tests added to BaseEntityIT covering all entity types:
get by ID, get by FQN, fieldPrefix filtering, pagination, and 404 cases.

Closes #1648

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix checkstyle

* Integrate DescriptionSourceBadge into UI and address PR review comments

- Add authorization checks (VIEW_BASIC) to ChangeSummaryResource endpoints
- Fix pagination defaults and simplify pagination logic
- Remove silent try-catch in integration tests, use assertThrows for 404
- Wire useChangeSummary hook into GenericProvider context
- Render AI-generated badge on entity descriptions (DescriptionV1)
- Render AI-generated badge on column descriptions (TableDescription)
- Pass changeSummary entry to ColumnDetailPanel's DescriptionSection
- Fix stale useMemo dependency in DescriptionV1 header
- Fix missing Less variable import in description-source-badge.less
- Add Playwright E2E tests for ChangeSummary badge feature

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Address PR review feedback: fix column FQN parsing, badge labels, backend optimization

- Fix ColumnDetailPanel to use EntityLink.getTableColumnNameFromColumnFqn
  instead of naive substring for changeSummary key lookup
- Show correct badge label per source type (AI/Automated/Propagated)
  instead of always showing "Automated"
- Fetch only changeDescription field instead of * in both endpoints
- Add @Min/@Max validation for limit and offset parameters
- Pass uriInfo to repository calls instead of null
- Pass explicit limit=1000 in GenericProvider to avoid truncated results
- Import ChangeSource from generated/type/changeSummaryMap (correct schema)
- Add getChangeSummaryByFqn to REST client matching API surface
- Add keyboard accessibility (tabIndex, role) to badge
- Remove untranslated "accepted-by" from non-English locales (fallback to en-us)
- Add "ai" label key to en-us locale
- Strengthen integration test assertions to verify non-empty results

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Improve change summary description layout

* Expand change summary support across assets

* Fix changeSummary race condition and LLMModel entity type mismatch

- Add request cancellation to useChangeSummary hook to prevent stale data
  when users switch entities rapidly
- Fix LLMModelResourceIT entity type from "llmmodel" to "llmModel" to match
  the registered entity type in Entity.java

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix Playwright strict mode violation and sync i18n translations

- Use .first() for ai-suggested-badge locator in ChangeSummaryBadge test
  to handle DescriptionV1 rendering the badge in both header and metadata
- Reorder imports per organize-imports rules
- Sync ai-suggested and authored-by keys to all 18 locale files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix

* fix

* fix

* implemented the new UI changes for AI description

* fixed the lint issues

* addressed gitar comment

* fixed the translations

* fixed unit test

* addressed PR comment

* fixed odcs playwright test

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Pere Miquel Brull <peremiquelbrull@gmail.com>
Co-authored-by: Rohit0301 <rj03012002@gmail.com>
Co-authored-by: Rohit Jain <60229265+Rohit0301@users.noreply.github.com>
2026-04-09 23:05:52 -07:00
..
src/test Add changeSummary API endpoint and UI components (#26533) 2026-04-09 23:05:52 -07:00
K8S_TESTS.md Code cleanup based on IDE flagged warnings (#26808) 2026-03-27 06:17:01 -07:00
pom.xml Add Json Logging (#26357) 2026-03-31 16:15:07 -07:00
README.md Faster tests (#24948) 2025-12-26 23:47:49 -08:00
TEST_MIGRATION_TRACKER.md Faster tests (#24948) 2025-12-26 23:47:49 -08:00

OpenMetadata Integration Tests

This module contains SDK-based integration tests that run against a real OpenMetadata server using Testcontainers. Tests execute in parallel and are isolated using TestNamespace.

Quick Start

# Run all tests with MySQL + Elasticsearch (default)
mvn test -pl :openmetadata-integration-tests

# Run with PostgreSQL + OpenSearch
mvn test -pl :openmetadata-integration-tests -Ppostgres-opensearch

# Run a specific test
mvn test -pl :openmetadata-integration-tests -Dtest="TableResourceIT"

Available Profiles

Profile Database Search Engine
mysql-elasticsearch (default) MySQL 8.3.0 Elasticsearch 8.11.4
postgres-opensearch PostgreSQL 15 OpenSearch 2.19.0
postgres-elasticsearch PostgreSQL 15 Elasticsearch 8.11.4
mysql-opensearch MySQL 8.3.0 OpenSearch 2.19.0

Writing a New Integration Test

1. Create the Test Class

Extend BaseEntityIT for entity CRUD tests or create a standalone test class:

package org.openmetadata.it.tests;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import org.junit.jupiter.api.Test;
import org.openmetadata.it.util.TestNamespace;
import org.openmetadata.schema.api.data.CreateTable;
import org.openmetadata.schema.entity.data.Table;

public class MyFeatureIT extends BaseEntityIT<Table, CreateTable> {

  @Override
  protected String getEntityType() {
    return "table";
  }

  @Override
  protected Table createEntity(CreateTable request) {
    return SdkClients.adminClient().tables().create(request);
  }

  @Override
  protected CreateTable createRequest(String name, TestNamespace ns) {
    return new CreateTable()
        .withName(name)
        .withDatabaseSchema(SharedEntities.getSchema().getFullyQualifiedName())
        .withColumns(List.of(new Column().withName("id").withDataType(ColumnDataType.INT)));
  }

  @Test
  void myCustomTest(TestNamespace ns) throws Exception {
    CreateTable request = createRequest(ns.prefix("myTable"), ns);
    Table table = createEntity(request);

    assertNotNull(table.getId());
    assertEquals(request.getName(), table.getName());
  }
}

2. Key Concepts

TestNamespace

Every test method receives a TestNamespace parameter that provides unique prefixes for entity names:

@Test
void myTest(TestNamespace ns) {
  String uniqueName = ns.prefix("myEntity");  // e.g., "abc123_myEntity"
}

This ensures tests don't conflict when running in parallel.

SdkClients

Get pre-configured SDK clients for different users:

OpenMetadataClient adminClient = SdkClients.adminClient();
OpenMetadataClient user1Client = SdkClients.user1Client();
OpenMetadataClient botClient = SdkClients.botClient();

SharedEntities

Access pre-created entities for tests:

DatabaseService service = SharedEntities.getService();
Database database = SharedEntities.getDatabase();
DatabaseSchema schema = SharedEntities.getSchema();
User adminUser = SharedEntities.getAdminUser();

3. BaseEntityIT Features

When extending BaseEntityIT, you get these tests automatically:

Test Description
post_entityCreate_200 Create entity successfully
get_entity_200_OK Get entity by ID
get_entityByName_200 Get entity by FQN
get_entityNotFound_404 Get non-existent entity
put_entityCreate_200 Create via PUT
patch_entityAttributes_200 Patch entity attributes
delete_entityAsAdmin_200 Delete entity
get_entityListWithPagination_200 List with pagination
test_sdkCRUDOperations Full CRUD via SDK
... and 30+ more

4. Controlling Test Behavior

Use flags to customize which inherited tests run:

public class MyEntityIT extends BaseEntityIT<MyEntity, CreateMyEntity> {
  {
    supportsPatch = true;          // Enable PATCH tests
    supportsTags = true;           // Enable tag tests
    supportsOwner = true;          // Enable owner tests
    supportsSearchIndex = true;    // Enable search tests
    supportsDomains = true;        // Enable domain tests
  }
}

5. Best Practices

  1. Use TestNamespace.prefix() for all entity names to ensure uniqueness
  2. Don't clean up entities - TestNamespace isolation handles this
  3. Use specific imports - No wildcard imports (import static ....*)
  4. Keep tests independent - Don't rely on order of execution
  5. Use Awaitility for async operations - Not Thread.sleep()
Awaitility.await()
    .atMost(Duration.ofSeconds(30))
    .pollInterval(Duration.ofMillis(500))
    .until(() -> someCondition());
  1. Avoid single-line comments - Write self-documenting code

Project Structure

openmetadata-integration-tests/
├── src/test/java/org/openmetadata/it/
│   ├── auth/           # JWT token generation
│   ├── env/            # Test infrastructure (TestSuiteBootstrap)
│   ├── factories/      # Entity factory classes
│   ├── tests/          # Integration test classes
│   └── util/           # Utilities (SdkClients, TestNamespace)
└── src/test/resources/
    ├── openmetadata-secure-test.yaml  # Test config
    └── *.der                          # JWT keys

Test Infrastructure

Tests use TestSuiteBootstrap (a JUnit LauncherSessionListener) that:

  1. Starts database container (MySQL or PostgreSQL)
  2. Starts search container (Elasticsearch or OpenSearch)
  3. Starts Fuseki SPARQL container (for RDF tests)
  4. Starts the OpenMetadata application
  5. Initializes SharedEntities

All containers are started once per test run and shared across all tests.

Running in CI

GitHub workflows run these tests on every PR:

  • integration-tests-mysql-elasticsearch.yml - MySQL + Elasticsearch
  • integration-tests-postgres-opensearch.yml - PostgreSQL + OpenSearch

Tests require the "safe to test" label on PRs.