From a56a000820d950b12fcaa8a4fc3970dc366640fa Mon Sep 17 00:00:00 2001 From: Qian Xia Date: Mon, 15 Apr 2024 14:07:16 +0800 Subject: [PATCH] [#2896] Add e2e test case for verifying fileset schema level and kafka topic level --- .../test/web/ui/CatalogsPageTest.java | 332 ++++++++++++++++-- .../test/web/ui/pages/CatalogsPage.java | 46 +++ .../tabsContent/detailsView/DetailsView.js | 22 +- 3 files changed, 370 insertions(+), 30 deletions(-) diff --git a/integration-test/src/test/java/com/datastrato/gravitino/integration/test/web/ui/CatalogsPageTest.java b/integration-test/src/test/java/com/datastrato/gravitino/integration/test/web/ui/CatalogsPageTest.java index 466500447c9..6eee4a01174 100644 --- a/integration-test/src/test/java/com/datastrato/gravitino/integration/test/web/ui/CatalogsPageTest.java +++ b/integration-test/src/test/java/com/datastrato/gravitino/integration/test/web/ui/CatalogsPageTest.java @@ -9,7 +9,9 @@ import com.datastrato.gravitino.NameIdentifier; import com.datastrato.gravitino.client.GravitinoAdminClient; import com.datastrato.gravitino.client.GravitinoMetalake; +import com.datastrato.gravitino.file.Fileset; import com.datastrato.gravitino.integration.test.container.ContainerSuite; +import com.datastrato.gravitino.integration.test.container.HiveContainer; import com.datastrato.gravitino.integration.test.container.TrinoITContainers; import com.datastrato.gravitino.integration.test.util.AbstractIT; import com.datastrato.gravitino.integration.test.web.ui.pages.CatalogsPage; @@ -19,6 +21,7 @@ import com.datastrato.gravitino.rel.types.Types; import com.google.common.collect.Maps; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import org.junit.jupiter.api.AfterAll; @@ -37,6 +40,7 @@ public class CatalogsPageTest extends AbstractWebIT { CatalogsPage catalogsPage = new CatalogsPage(); protected static TrinoITContainers trinoITContainers; + private static final ContainerSuite containerSuite = ContainerSuite.getInstance(); protected static GravitinoAdminClient gravitinoClient; private static GravitinoMetalake metalake; private static Catalog catalog; @@ -52,21 +56,30 @@ public class CatalogsPageTest extends AbstractWebIT { private static final String WEB_TITLE = "Gravitino"; private static final String CATALOG_TABLE_TITLE = "Schemas"; private static final String SCHEMA_TABLE_TITLE = "Tables"; + private static final String SCHEMA_FILESET_TITLE = "Filesets"; + private static final String SCHEMA_TOPIC_TITLE = "Topics"; private static final String TABLE_TABLE_TITLE = "Columns"; private static final String METALAKE_NAME = "test"; private static final String METALAKE_SELECT_NAME = "metalake_select_name"; - private static final String CATALOG_TYPE = "relational"; + private static final String CATALOG_TYPE_RELATIONAL = "relational"; + private static final String CATALOG_TYPE_FILESET = "fileset"; + private static final String CATALOG_TYPE_MESSAGING = "messaging"; private static final String DEFAULT_CATALOG_NAME = "default_catalog"; private static final String HIVE_CATALOG_NAME = "catalog_hive"; - private static final String MODIFIED_CATALOG_NAME = HIVE_CATALOG_NAME + "_edited"; + private static final String MODIFIED_HIVE_CATALOG_NAME = HIVE_CATALOG_NAME + "_edited"; private static final String ICEBERG_CATALOG_NAME = "catalog_iceberg"; private static final String FILESET_CATALOG_NAME = "catalog_fileset"; private static final String KAFKA_CATALOG_NAME = "catalog_kafka"; private static final String SCHEMA_NAME = "default"; + private static final String SCHEMA_NAME_FILESET = "schema_fileset"; + private static final String FILESET_NAME = "fileset1"; + private static final String TOPIC_NAME = "topic1"; private static final String TABLE_NAME = "table1"; private static final String TABLE_NAME_2 = "table2"; private static final String COLUMN_NAME = "column"; private static final String COLUMN_NAME_2 = "column_2"; + private static final String PROPERTIES_KEY1 = "key1"; + private static final String PROPERTIES_VALUE1 = "val1"; private static final String MYSQL_CATALOG_NAME = "catalog_mysql"; private static final String MYSQL_JDBC_DRIVER = "com.mysql.cj.jdbc.Driver"; @@ -78,6 +91,8 @@ public class CatalogsPageTest extends AbstractWebIT { private static final String COMMON_JDBC_USER = "trino"; private static final String COMMON_JDBC_PWD = "ds123"; + private static String defaultBaseLocation; + @BeforeAll public static void before() throws Exception { gravitinoClient = AbstractIT.getGravitinoClient(); @@ -92,8 +107,35 @@ public static void before() throws Exception { hdfsUri = trinoITContainers.getHdfsUri(); mysqlUri = trinoITContainers.getMysqlUri(); postgresqlUri = trinoITContainers.getPostgresqlUri(); + + containerSuite.startHiveContainer(); + } + + /** + * Create the specified schema + * + * @param metalakeName The name of the Metalake where the schema will be created. + * @param catalogName The name of the Catalog where the schema will be created. + * @param schemaName The name of the Schema where the schema will be created. + */ + void createSchema(String metalakeName, String catalogName, String schemaName) { + Map properties = Maps.newHashMap(); + properties.put(PROPERTIES_KEY1, PROPERTIES_VALUE1); + catalog + .asSchemas() + .createSchema( + NameIdentifier.of(metalakeName, catalogName, schemaName), "comment", properties); } + /** + * Creates a table with a single column in the specified Metalake, Catalog, Schema, and Table. + * + * @param metalakeName The name of the Metalake where the table will be created. + * @param catalogName The name of the Catalog where the table will be created. + * @param schemaName The name of the Schema where the table will be created. + * @param tableName The name of the Table to be created. + * @param colName The name of the Column to be created in the Table. + */ void createTableAndColumn( String metalakeName, String catalogName, @@ -111,6 +153,80 @@ void createTableAndColumn( properties); } + /** + * Retrieves the default base location for the given schema name. + * + * @param schemaName The name of the schema. + * @return The default HDFS storage location for the schema. + */ + private static String defaultBaseLocation(String schemaName) { + if (defaultBaseLocation == null) { + defaultBaseLocation = + String.format( + "hdfs://%s:%d/user/hadoop/%s.db", + containerSuite.getHiveContainer().getContainerIpAddress(), + HiveContainer.HDFS_DEFAULTFS_PORT, + schemaName.toLowerCase()); + } + return defaultBaseLocation; + } + + /** + * Retrieves the storage location for the given schema name and fileset name. + * + * @param schemaName The name of the schema. + * @param filesetName The name of the fileset. + * @return The storage path for the combination of schema and fileset. + */ + private static String storageLocation(String schemaName, String filesetName) { + return defaultBaseLocation(schemaName) + "/" + filesetName; + } + + /** + * Creates a fileset within the specified Metalake, Catalog, Schema, and Fileset names. + * + * @param metalakeName The name of the Metalake. + * @param catalogName The name of the Catalog. + * @param schemaName The name of the Schema. + * @param filesetName The name of the Fileset. + */ + void createFileset( + String metalakeName, String catalogName, String schemaName, String filesetName) { + Map properties = Maps.newHashMap(); + properties.put(PROPERTIES_KEY1, PROPERTIES_VALUE1); + String storageLocation = storageLocation(schemaName, filesetName); + Catalog catalog_fileset = + metalake.loadCatalog(NameIdentifier.ofCatalog(metalakeName, catalogName)); + catalog_fileset + .asFilesetCatalog() + .createFileset( + NameIdentifier.of(metalakeName, catalogName, schemaName, filesetName), + "comment", + Fileset.Type.MANAGED, + storageLocation, + properties); + } + + /** + * Creates a Kafka topic within the specified Metalake, Catalog, Schema, and Topic names. + * + * @param metalakeName The name of the Metalake. + * @param catalogName The name of the Catalog. + * @param schemaName The name of the Schema. + * @param topicName The name of the Kafka topic. + */ + void createTopic(String metalakeName, String catalogName, String schemaName, String topicName) { + Catalog catalog_kafka = + metalake.loadCatalog(NameIdentifier.ofCatalog(metalakeName, catalogName)); + catalog_kafka + .asTopicCatalog() + .createTopic( + NameIdentifier.of(metalakeName, catalogName, schemaName, topicName), + "comment", + null, + Collections.emptyMap()); + } + @AfterAll public static void after() { try { @@ -283,21 +399,22 @@ public void testViewCatalogDetails() throws InterruptedException { @Test @Order(10) - public void testEditCatalog() throws InterruptedException { + public void testEditHiveCatalog() throws InterruptedException { catalogsPage.clickEditCatalogBtn(HIVE_CATALOG_NAME); - catalogsPage.setCatalogNameField(MODIFIED_CATALOG_NAME); + catalogsPage.setCatalogNameField(MODIFIED_HIVE_CATALOG_NAME); clickAndWait(catalogsPage.handleSubmitCatalogBtn); - Assertions.assertTrue(catalogsPage.verifyEditedCatalog(MODIFIED_CATALOG_NAME)); + Assertions.assertTrue(catalogsPage.verifyEditedCatalog(MODIFIED_HIVE_CATALOG_NAME)); } // test catalog show schema list @Test @Order(11) public void testClickCatalogLink() { - catalogsPage.clickCatalogLink(METALAKE_NAME, MODIFIED_CATALOG_NAME, CATALOG_TYPE); + catalogsPage.clickCatalogLink( + METALAKE_NAME, MODIFIED_HIVE_CATALOG_NAME, CATALOG_TYPE_RELATIONAL); Assertions.assertTrue(catalogsPage.verifyShowTableTitle(CATALOG_TABLE_TITLE)); Assertions.assertTrue(catalogsPage.verifyShowDataItemInList(SCHEMA_NAME, false)); - Assertions.assertTrue(catalogsPage.verifySelectedNode(MODIFIED_CATALOG_NAME)); + Assertions.assertTrue(catalogsPage.verifySelectedNode(MODIFIED_HIVE_CATALOG_NAME)); } @Test @@ -309,7 +426,7 @@ public void testRefreshCatalogPage() { Assertions.assertTrue(catalogsPage.verifyShowDataItemInList(SCHEMA_NAME, false)); List treeNodes = Arrays.asList( - MODIFIED_CATALOG_NAME, + MODIFIED_HIVE_CATALOG_NAME, SCHEMA_NAME, ICEBERG_CATALOG_NAME, MYSQL_CATALOG_NAME, @@ -317,7 +434,7 @@ public void testRefreshCatalogPage() { FILESET_CATALOG_NAME, KAFKA_CATALOG_NAME); Assertions.assertTrue(catalogsPage.verifyTreeNodes(treeNodes)); - Assertions.assertTrue(catalogsPage.verifySelectedNode(MODIFIED_CATALOG_NAME)); + Assertions.assertTrue(catalogsPage.verifySelectedNode(MODIFIED_HIVE_CATALOG_NAME)); } // test schema show table list @@ -326,8 +443,9 @@ public void testRefreshCatalogPage() { public void testClickSchemaLink() { // create table createTableAndColumn( - METALAKE_NAME, MODIFIED_CATALOG_NAME, SCHEMA_NAME, TABLE_NAME, COLUMN_NAME); - catalogsPage.clickSchemaLink(METALAKE_NAME, MODIFIED_CATALOG_NAME, CATALOG_TYPE, SCHEMA_NAME); + METALAKE_NAME, MODIFIED_HIVE_CATALOG_NAME, SCHEMA_NAME, TABLE_NAME, COLUMN_NAME); + catalogsPage.clickSchemaLink( + METALAKE_NAME, MODIFIED_HIVE_CATALOG_NAME, CATALOG_TYPE_RELATIONAL, SCHEMA_NAME); Assertions.assertTrue(catalogsPage.verifyShowTableTitle(SCHEMA_TABLE_TITLE)); Assertions.assertTrue(catalogsPage.verifyShowDataItemInList(TABLE_NAME, false)); Assertions.assertTrue(catalogsPage.verifySelectedNode(SCHEMA_NAME)); @@ -342,7 +460,7 @@ public void testRefreshSchemaPage() { Assertions.assertTrue(catalogsPage.verifyShowDataItemInList(TABLE_NAME, false)); List treeNodes = Arrays.asList( - MODIFIED_CATALOG_NAME, + MODIFIED_HIVE_CATALOG_NAME, SCHEMA_NAME, TABLE_NAME, ICEBERG_CATALOG_NAME, @@ -359,7 +477,11 @@ public void testRefreshSchemaPage() { @Order(15) public void testClickTableLink() { catalogsPage.clickTableLink( - METALAKE_NAME, MODIFIED_CATALOG_NAME, CATALOG_TYPE, SCHEMA_NAME, TABLE_NAME); + METALAKE_NAME, + MODIFIED_HIVE_CATALOG_NAME, + CATALOG_TYPE_RELATIONAL, + SCHEMA_NAME, + TABLE_NAME); Assertions.assertTrue(catalogsPage.verifyShowTableTitle(TABLE_TABLE_TITLE)); Assertions.assertTrue(catalogsPage.verifyTableColumns()); Assertions.assertTrue(catalogsPage.verifyShowDataItemInList(COLUMN_NAME, true)); @@ -377,7 +499,7 @@ public void testRefreshTablePage() { Assertions.assertTrue(catalogsPage.verifyShowDataItemInList(COLUMN_NAME, true)); List treeNodes = Arrays.asList( - MODIFIED_CATALOG_NAME, + MODIFIED_HIVE_CATALOG_NAME, SCHEMA_NAME, TABLE_NAME, ICEBERG_CATALOG_NAME, @@ -395,44 +517,59 @@ public void testSelectMetalake() throws InterruptedException { Assertions.assertTrue(catalogsPage.verifyEmptyCatalog()); catalogsPage.metalakeSelectChange(METALAKE_NAME); - Assertions.assertTrue(catalogsPage.verifyGetCatalog(MODIFIED_CATALOG_NAME)); + Assertions.assertTrue(catalogsPage.verifyGetCatalog(MODIFIED_HIVE_CATALOG_NAME)); } @Test @Order(18) public void testClickTreeList() throws InterruptedException { String icebergNode = - String.format("{{%s}}{{%s}}{{%s}}", METALAKE_NAME, ICEBERG_CATALOG_NAME, CATALOG_TYPE); + String.format( + "{{%s}}{{%s}}{{%s}}", METALAKE_NAME, ICEBERG_CATALOG_NAME, CATALOG_TYPE_RELATIONAL); catalogsPage.clickTreeNode(icebergNode); Assertions.assertTrue(catalogsPage.verifyGetCatalog(ICEBERG_CATALOG_NAME)); String mysqlNode = - String.format("{{%s}}{{%s}}{{%s}}", METALAKE_NAME, MYSQL_CATALOG_NAME, CATALOG_TYPE); + String.format( + "{{%s}}{{%s}}{{%s}}", METALAKE_NAME, MYSQL_CATALOG_NAME, CATALOG_TYPE_RELATIONAL); catalogsPage.clickTreeNode(mysqlNode); Assertions.assertTrue(catalogsPage.verifyGetCatalog(MYSQL_CATALOG_NAME)); String pgNode = - String.format("{{%s}}{{%s}}{{%s}}", METALAKE_NAME, PG_CATALOG_NAME, CATALOG_TYPE); + String.format( + "{{%s}}{{%s}}{{%s}}", METALAKE_NAME, PG_CATALOG_NAME, CATALOG_TYPE_RELATIONAL); catalogsPage.clickTreeNode(pgNode); Assertions.assertTrue(catalogsPage.verifyGetCatalog(PG_CATALOG_NAME)); String filesetNode = - String.format("{{%s}}{{%s}}{{%s}}", METALAKE_NAME, FILESET_CATALOG_NAME, "fileset"); + String.format( + "{{%s}}{{%s}}{{%s}}", METALAKE_NAME, FILESET_CATALOG_NAME, CATALOG_TYPE_FILESET); catalogsPage.clickTreeNode(filesetNode); Assertions.assertTrue(catalogsPage.verifyGetCatalog(FILESET_CATALOG_NAME)); + String kafkaNode = + String.format( + "{{%s}}{{%s}}{{%s}}", METALAKE_NAME, KAFKA_CATALOG_NAME, CATALOG_TYPE_MESSAGING); + catalogsPage.clickTreeNode(kafkaNode); + Assertions.assertTrue(catalogsPage.verifyGetCatalog(KAFKA_CATALOG_NAME)); String hiveNode = - String.format("{{%s}}{{%s}}{{%s}}", METALAKE_NAME, MODIFIED_CATALOG_NAME, CATALOG_TYPE); + String.format( + "{{%s}}{{%s}}{{%s}}", + METALAKE_NAME, MODIFIED_HIVE_CATALOG_NAME, CATALOG_TYPE_RELATIONAL); catalogsPage.clickTreeNode(hiveNode); Assertions.assertTrue(catalogsPage.verifyShowTableTitle(CATALOG_TABLE_TITLE)); - Assertions.assertTrue(catalogsPage.verifyGetCatalog(MODIFIED_CATALOG_NAME)); + Assertions.assertTrue(catalogsPage.verifyGetCatalog(MODIFIED_HIVE_CATALOG_NAME)); String schemaNode = String.format( "{{%s}}{{%s}}{{%s}}{{%s}}", - METALAKE_NAME, MODIFIED_CATALOG_NAME, CATALOG_TYPE, SCHEMA_NAME); + METALAKE_NAME, MODIFIED_HIVE_CATALOG_NAME, CATALOG_TYPE_RELATIONAL, SCHEMA_NAME); catalogsPage.clickTreeNode(schemaNode); Assertions.assertTrue(catalogsPage.verifyShowTableTitle(SCHEMA_TABLE_TITLE)); Assertions.assertTrue(catalogsPage.verifyShowDataItemInList(TABLE_NAME, false)); String tableNode = String.format( "{{%s}}{{%s}}{{%s}}{{%s}}{{%s}}", - METALAKE_NAME, MODIFIED_CATALOG_NAME, CATALOG_TYPE, SCHEMA_NAME, TABLE_NAME); + METALAKE_NAME, + MODIFIED_HIVE_CATALOG_NAME, + CATALOG_TYPE_RELATIONAL, + SCHEMA_NAME, + TABLE_NAME); catalogsPage.clickTreeNode(tableNode); Assertions.assertTrue(catalogsPage.verifyShowTableTitle(TABLE_TABLE_TITLE)); Assertions.assertTrue(catalogsPage.verifyShowDataItemInList(COLUMN_NAME, true)); @@ -443,19 +580,25 @@ public void testClickTreeList() throws InterruptedException { @Order(19) public void testTreeNodeRefresh() throws InterruptedException { createTableAndColumn( - METALAKE_NAME, MODIFIED_CATALOG_NAME, SCHEMA_NAME, TABLE_NAME_2, COLUMN_NAME_2); + METALAKE_NAME, MODIFIED_HIVE_CATALOG_NAME, SCHEMA_NAME, TABLE_NAME_2, COLUMN_NAME_2); String hiveNode = - String.format("{{%s}}{{%s}}{{%s}}", METALAKE_NAME, MODIFIED_CATALOG_NAME, CATALOG_TYPE); + String.format( + "{{%s}}{{%s}}{{%s}}", + METALAKE_NAME, MODIFIED_HIVE_CATALOG_NAME, CATALOG_TYPE_RELATIONAL); catalogsPage.clickTreeNode(hiveNode); String schemaNode = String.format( "{{%s}}{{%s}}{{%s}}{{%s}}", - METALAKE_NAME, MODIFIED_CATALOG_NAME, CATALOG_TYPE, SCHEMA_NAME); + METALAKE_NAME, MODIFIED_HIVE_CATALOG_NAME, CATALOG_TYPE_RELATIONAL, SCHEMA_NAME); catalogsPage.clickTreeNodeRefresh(schemaNode); String tableNode = String.format( "{{%s}}{{%s}}{{%s}}{{%s}}{{%s}}", - METALAKE_NAME, MODIFIED_CATALOG_NAME, CATALOG_TYPE, SCHEMA_NAME, TABLE_NAME_2); + METALAKE_NAME, + MODIFIED_HIVE_CATALOG_NAME, + CATALOG_TYPE_RELATIONAL, + SCHEMA_NAME, + TABLE_NAME_2); catalogsPage.clickTreeNode(tableNode); Assertions.assertTrue(catalogsPage.verifyShowTableTitle(TABLE_TABLE_TITLE)); Assertions.assertTrue(catalogsPage.verifyShowDataItemInList(COLUMN_NAME_2, true)); @@ -464,6 +607,141 @@ public void testTreeNodeRefresh() throws InterruptedException { @Test @Order(20) + public void testViewFilesetCatalog() throws InterruptedException { + // 1. back to the list catalog of metalake + catalogsPage.clickMetalakeLink(METALAKE_NAME); + // 2. create schema and fileset of fileset catalog + createSchema(METALAKE_NAME, FILESET_CATALOG_NAME, SCHEMA_NAME_FILESET); + createFileset(METALAKE_NAME, FILESET_CATALOG_NAME, SCHEMA_NAME_FILESET, FILESET_NAME); + // 3. click fileset catalog tree node + String filesetCatalogNode = + String.format( + "{{%s}}{{%s}}{{%s}}", METALAKE_NAME, FILESET_CATALOG_NAME, CATALOG_TYPE_FILESET); + catalogsPage.clickTreeNode(filesetCatalogNode); + // 4. verify show table title、 schema name and tree node + Assertions.assertTrue(catalogsPage.verifyShowTableTitle(CATALOG_TABLE_TITLE)); + Assertions.assertTrue(catalogsPage.verifyShowDataItemInList(SCHEMA_NAME_FILESET)); + List treeNodes = + Arrays.asList( + MODIFIED_HIVE_CATALOG_NAME, + ICEBERG_CATALOG_NAME, + MYSQL_CATALOG_NAME, + PG_CATALOG_NAME, + FILESET_CATALOG_NAME, + SCHEMA_NAME_FILESET, + KAFKA_CATALOG_NAME); + Assertions.assertTrue(catalogsPage.verifyTreeNodes(treeNodes)); + // 5. click schema tree node + String filesetSchemaNode = + String.format( + "{{%s}}{{%s}}{{%s}}{{%s}}", + METALAKE_NAME, FILESET_CATALOG_NAME, CATALOG_TYPE_FILESET, SCHEMA_NAME_FILESET); + catalogsPage.clickTreeNode(filesetSchemaNode); + // 6. verify show table title、 fileset name and tree node + Assertions.assertTrue(catalogsPage.verifyShowTableTitle(SCHEMA_FILESET_TITLE)); + Assertions.assertTrue(catalogsPage.verifyShowDataItemInList(FILESET_NAME)); + treeNodes = + Arrays.asList( + MODIFIED_HIVE_CATALOG_NAME, + ICEBERG_CATALOG_NAME, + MYSQL_CATALOG_NAME, + PG_CATALOG_NAME, + FILESET_CATALOG_NAME, + SCHEMA_NAME_FILESET, + FILESET_NAME, + KAFKA_CATALOG_NAME); + Assertions.assertTrue(catalogsPage.verifyTreeNodes(treeNodes)); + // 7. click fileset tree node + String filesetNode = + String.format( + "{{%s}}{{%s}}{{%s}}{{%s}}{{%s}}", + METALAKE_NAME, + FILESET_CATALOG_NAME, + CATALOG_TYPE_FILESET, + SCHEMA_NAME_FILESET, + FILESET_NAME); + catalogsPage.clickTreeNode(filesetNode); + // 8. verify show tab details + Assertions.assertTrue(catalogsPage.verifyShowDetailsContent()); + Assertions.assertTrue( + catalogsPage.verifyShowPropertiesItemInList( + "key", PROPERTIES_KEY1, PROPERTIES_KEY1, false)); + Assertions.assertTrue( + catalogsPage.verifyShowPropertiesItemInList( + "value", PROPERTIES_KEY1, PROPERTIES_VALUE1, false)); + } + + @Test + @Order(21) + public void testViewKafkaCatalog() throws InterruptedException { + // 1. back to the list catalog of metalake + catalogsPage.metalakeSelectChange(METALAKE_SELECT_NAME); + Assertions.assertTrue(catalogsPage.verifyEmptyCatalog()); + + catalogsPage.metalakeSelectChange(METALAKE_NAME); + // 2. create topic of kafka catalog + createTopic(METALAKE_NAME, KAFKA_CATALOG_NAME, SCHEMA_NAME, TOPIC_NAME); + // 3. click kafka catalog tree node + String kafkaCatalogNode = + String.format( + "{{%s}}{{%s}}{{%s}}", METALAKE_NAME, KAFKA_CATALOG_NAME, CATALOG_TYPE_MESSAGING); + catalogsPage.clickTreeNode(kafkaCatalogNode); + // 4. verify show table title、 schema name and tree node + Assertions.assertTrue(catalogsPage.verifyShowTableTitle(CATALOG_TABLE_TITLE)); + Assertions.assertTrue(catalogsPage.verifyShowDataItemInList(SCHEMA_NAME)); + List treeNodes = + Arrays.asList( + MODIFIED_HIVE_CATALOG_NAME, + ICEBERG_CATALOG_NAME, + MYSQL_CATALOG_NAME, + PG_CATALOG_NAME, + FILESET_CATALOG_NAME, + KAFKA_CATALOG_NAME, + SCHEMA_NAME); + Assertions.assertTrue(catalogsPage.verifyTreeNodes(treeNodes)); + // 5. click schema tree node + String kafkaSchemaNode = + String.format( + "{{%s}}{{%s}}{{%s}}{{%s}}", + METALAKE_NAME, KAFKA_CATALOG_NAME, CATALOG_TYPE_MESSAGING, SCHEMA_NAME); + catalogsPage.clickTreeNode(kafkaSchemaNode); + // 6. verify show table title、 fileset name and tree node + Assertions.assertTrue(catalogsPage.verifyShowTableTitle(SCHEMA_TOPIC_TITLE)); + Assertions.assertTrue(catalogsPage.verifyShowDataItemInList(TOPIC_NAME)); + treeNodes = + Arrays.asList( + MODIFIED_HIVE_CATALOG_NAME, + ICEBERG_CATALOG_NAME, + MYSQL_CATALOG_NAME, + PG_CATALOG_NAME, + FILESET_CATALOG_NAME, + KAFKA_CATALOG_NAME, + SCHEMA_NAME, + TOPIC_NAME); + Assertions.assertTrue(catalogsPage.verifyTreeNodes(treeNodes)); + // 7. click fileset tree node + String filesetNode = + String.format( + "{{%s}}{{%s}}{{%s}}{{%s}}{{%s}}", + METALAKE_NAME, KAFKA_CATALOG_NAME, CATALOG_TYPE_MESSAGING, SCHEMA_NAME, TOPIC_NAME); + catalogsPage.clickTreeNode(filesetNode); + // 8. verify show tab details + Assertions.assertTrue(catalogsPage.verifyShowDetailsContent()); + // 9. verify show highlight properties + Assertions.assertTrue( + catalogsPage.verifyShowPropertiesItemInList( + "key", "partition-count", "partition-count", true)); + Assertions.assertTrue( + catalogsPage.verifyShowPropertiesItemInList("value", "partition-count", "1", true)); + Assertions.assertTrue( + catalogsPage.verifyShowPropertiesItemInList( + "key", "replication-factor", "replication-factor", true)); + Assertions.assertTrue( + catalogsPage.verifyShowPropertiesItemInList("value", "replication-factor", "1", true)); + } + + @Test + @Order(22) public void testBackHomePage() throws InterruptedException { clickAndWait(catalogsPage.backHomeBtn); Assertions.assertTrue(catalogsPage.verifyBackHomePage()); diff --git a/integration-test/src/test/java/com/datastrato/gravitino/integration/test/web/ui/pages/CatalogsPage.java b/integration-test/src/test/java/com/datastrato/gravitino/integration/test/web/ui/pages/CatalogsPage.java index 8f8c1a73a20..675bf7108e1 100644 --- a/integration-test/src/test/java/com/datastrato/gravitino/integration/test/web/ui/pages/CatalogsPage.java +++ b/integration-test/src/test/java/com/datastrato/gravitino/integration/test/web/ui/pages/CatalogsPage.java @@ -201,6 +201,18 @@ public void clickDeleteCatalogBtn(String name) { } } + public void clickMetalakeLink(String metalakeName) { + try { + String xpath = "//a[@href='?metalake=" + metalakeName + "']"; + WebElement link = tableGrid.findElement(By.xpath(xpath)); + WebDriverWait wait = new WebDriverWait(driver, MAX_TIMEOUT); + wait.until(ExpectedConditions.elementToBeClickable(By.xpath(xpath))); + clickAndWait(link); + } catch (Exception e) { + LOG.error(e.getMessage(), e); + } + } + public void clickCatalogLink(String metalakeName, String catalogName, String catalogType) { try { String xpath = @@ -450,6 +462,40 @@ public boolean verifyShowTableTitle(String title) { } } + /** + * Verifies if a given property item is present in a specified list. + * + * @param item The key or value item of the property. + * @param key The key of the property. + * @param value The value of key item of the property. + * @param isHighlight Whether to highlight the property item or not. + * @return True if the property item is found in the list, false otherwise. + */ + public boolean verifyShowPropertiesItemInList( + String item, String key, String value, Boolean isHighlight) { + try { + Thread.sleep(ACTION_SLEEP_MILLIS); + String xpath; + if (isHighlight) { + xpath = "//div[@data-refer='props-" + item + "-" + key + "-highlight']"; + } else { + xpath = "//div[@data-refer='props-" + item + "-" + key + "']"; + } + WebElement propertyElement = driver.findElement(By.xpath(xpath)); + boolean match = Objects.equals(propertyElement.getText(), value); + + if (!match) { + LOG.error("Prop: does not include itemName: {}", value); + return false; + } + + return true; + } catch (Exception e) { + LOG.error(e.getMessage(), e); + return false; + } + } + public boolean verifyShowDataItemInList(String itemName, Boolean isColumnLevel) { try { Thread.sleep(ACTION_SLEEP_MILLIS); diff --git a/web/src/app/metalakes/metalake/rightContent/tabsContent/detailsView/DetailsView.js b/web/src/app/metalakes/metalake/rightContent/tabsContent/detailsView/DetailsView.js index a15b287a259..c1977b832fc 100644 --- a/web/src/app/metalakes/metalake/rightContent/tabsContent/detailsView/DetailsView.js +++ b/web/src/app/metalakes/metalake/rightContent/tabsContent/detailsView/DetailsView.js @@ -129,7 +129,7 @@ const DetailsView = () => { Properties - + { : 400 }} > - {item.key} +
+ {item.key} +
`${theme.spacing(2.75)} !important` }}> @@ -166,7 +174,15 @@ const DetailsView = () => { : 400 }} > - {item.value} +
+ {item.value} +