소스 검색

[e2e] Produce message tests, schema registry tests (#984)

* #825 add methods for creating Schema Registry

* #825 Produced message added and Schema Registry added

* add test for produced message

* update topic test

* fix test 'produce message', added tag for docker selenium image

* added schema registry rests

* changed schema value

* changed locator for schema selector

* added verification container running, need to close before new test class

* fix for timeout exception, removed deletion of cookies

* small fix for remote driver

* small fix for remote driver v2

* fix for api deletion if not exist

Co-authored-by: kshpilchyna <kshpilchyna@provectus.com>
Co-authored-by: Roman Zabaluev <rzabaluev@provectus.com>
ChristinaKristane 3 년 전
부모
커밋
4ebc74212c
22개의 변경된 파일607개의 추가작업 그리고 72개의 파일을 삭제
  1. 27 15
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/base/BaseTest.java
  2. 4 1
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/base/TestConfiguration.java
  3. 37 27
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/helpers/ApiHelper.java
  4. 11 9
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/MainPage.java
  5. 4 1
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/Pages.java
  6. 43 0
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/ProduceMessagePage.java
  7. 4 2
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/connector/ConnectorUpdateView.java
  8. 51 0
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/schema/SchemaCreateView.java
  9. 52 0
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/schema/SchemaEditView.java
  10. 40 0
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/schema/SchemaRegistryList.java
  11. 38 0
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/schema/SchemaView.java
  12. 3 4
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/topic/TopicCreateEditSettingsView.java
  13. 48 11
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/topic/TopicView.java
  14. 2 2
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/tests/ConnectorsTests.java
  15. 161 0
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/tests/SchemasTests.java
  16. 29 0
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/tests/TopicTests.java
  17. 1 0
      kafka-ui-e2e-checks/src/test/resources/producedkey.txt
  18. 7 0
      kafka-ui-e2e-checks/src/test/resources/schema_Json_Value.json
  19. 24 0
      kafka-ui-e2e-checks/src/test/resources/schema_avro_for_update.json
  20. 15 0
      kafka-ui-e2e-checks/src/test/resources/schema_avro_value.json
  21. 5 0
      kafka-ui-e2e-checks/src/test/resources/schema_protobuf_value.txt
  22. 1 0
      kafka-ui-e2e-checks/src/test/resources/testData.txt

+ 27 - 15
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/base/BaseTest.java

@@ -13,9 +13,8 @@ import io.qameta.allure.selenide.AllureSelenide;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FileUtils;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.DisplayNameGeneration;
+import org.junit.jupiter.api.*;
+import org.openqa.selenium.Dimension;
 import org.openqa.selenium.OutputType;
 import org.openqa.selenium.TakesScreenshot;
 import org.openqa.selenium.chrome.ChromeOptions;
@@ -23,11 +22,11 @@ import org.openqa.selenium.remote.RemoteWebDriver;
 import org.testcontainers.Testcontainers;
 import org.testcontainers.containers.BrowserWebDriverContainer;
 import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.utility.DockerImageName;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
-import java.time.Duration;
 import java.util.Arrays;
 
 @Slf4j
@@ -40,12 +39,9 @@ public class BaseTest {
 
     private Screenshooter screenshooter = new Screenshooter();
 
-    public static BrowserWebDriverContainer<?> webDriverContainer =
-            new BrowserWebDriverContainer<>()
-                    .withCapabilities(new ChromeOptions()
-                            .addArguments("--no-sandbox")
-                            .addArguments("--disable-dev-shm-usage"))
-                    .waitingFor(Wait.defaultWaitStrategy().withStartupTimeout(Duration.ofSeconds(90)));
+    private static final String IMAGE_NAME = TestConfiguration.IMAGE_NAME;
+    private static final String IMAGE_TAG = TestConfiguration.IMAGE_TAG;
+    protected static BrowserWebDriverContainer<?> webDriverContainer = null;
 
     public void compareScreenshots(String name) {
         screenshooter.compareScreenshots(name);
@@ -55,13 +51,32 @@ public class BaseTest {
         screenshooter.compareScreenshots(name, shouldUpdateScreenshots);
     }
 
+    @BeforeEach
+    public void setWebDriver(){
+        RemoteWebDriver remoteWebDriver = webDriverContainer.getWebDriver();
+        WebDriverRunner.setWebDriver(remoteWebDriver);
+        remoteWebDriver.manage().window().setSize(new Dimension(1440, 1024));
+    }
+
     @BeforeAll
     public static void start() {
+        DockerImageName image = DockerImageName.parse(IMAGE_NAME).withTag(IMAGE_TAG);
+        webDriverContainer = new BrowserWebDriverContainer<>(image)
+                .withCapabilities(new ChromeOptions().addArguments("--disable-dev-shm-usage"))
+                .waitingFor(Wait.forHttp("/"))
+                .waitingFor(Wait.forLogMessage(".*Started Selenium Standalone.*", 1));
         Testcontainers.exposeHostPorts(8080);
         webDriverContainer.start();
         webDriverContainer.isRunning();
-        RemoteWebDriver remoteWebDriver = webDriverContainer.getWebDriver();
-        WebDriverRunner.setWebDriver(remoteWebDriver);
+        webDriverContainer.isHostAccessible();
+    }
+
+    @AfterAll
+    public static void tearDown(){
+        if(webDriverContainer.isRunning()) {
+            webDriverContainer.close();
+            webDriverContainer.stop();
+        }
     }
 
     static {
@@ -80,17 +95,14 @@ public class BaseTest {
         setup();
     }
 
-
     @AfterEach
     public void afterMethod() {
-        webDriverContainer.getWebDriver().manage().deleteAllCookies();
         Allure.addAttachment("Screenshot",
                 new ByteArrayInputStream(((TakesScreenshot) webDriverContainer.getWebDriver()).getScreenshotAs(OutputType.BYTES)));
     }
 
     @SneakyThrows
     private static void setup() {
-
         Configuration.reportsFolder = TestConfiguration.REPORTS_FOLDER;
         Configuration.screenshots = TestConfiguration.SCREENSHOTS;
         Configuration.savePageSource = TestConfiguration.SAVE_PAGE_SOURCE;

+ 4 - 1
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/base/TestConfiguration.java

@@ -9,7 +9,7 @@ public class TestConfiguration {
       Boolean.parseBoolean(System.getProperty("USE_LOCAL_BROWSER", "true"));
   public static String REPORTS_FOLDER = System.getProperty("REPORTS_FOLDER", "allure-results");
   public static Boolean SCREENSHOTS =
-      Boolean.parseBoolean(System.getProperty("SCREENSHOTS", "false"));
+      Boolean.parseBoolean(System.getProperty("SCREENSHOTS", "true"));
   public static Boolean SAVE_PAGE_SOURCE =
       Boolean.parseBoolean(System.getProperty("SAVE_PAGE_SOURCE", "false"));
   public static Boolean REOPEN_BROWSER_ON_FAIL =
@@ -17,4 +17,7 @@ public class TestConfiguration {
   public static String BROWSER = System.getProperty("BROWSER", "chrome");
   public static String BROWSER_SIZE = System.getProperty("BROWSER_SIZE", "1920x1080");
   public static Boolean ENABLE_VNC = Boolean.parseBoolean(System.getProperty("ENABLE_VNC", "true"));
+  public static String IMAGE_NAME = System.getProperty("SELENIUM_DOCKER_IMAGE", "selenium/standalone-chrome");
+  public static String IMAGE_TAG = System.getProperty("SELENIUM_IMAGE_TAG", "102.0");
+
 }

+ 37 - 27
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/helpers/ApiHelper.java

@@ -1,15 +1,12 @@
 package com.provectus.kafka.ui.helpers;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.gson.Gson;
 import com.provectus.kafka.ui.api.ApiClient;
 import com.provectus.kafka.ui.api.api.KafkaConnectApi;
 import com.provectus.kafka.ui.api.api.MessagesApi;
+import com.provectus.kafka.ui.api.api.SchemasApi;
 import com.provectus.kafka.ui.api.api.TopicsApi;
-import com.provectus.kafka.ui.api.model.CreateTopicMessage;
-import com.provectus.kafka.ui.api.model.ErrorResponse;
-import com.provectus.kafka.ui.api.model.NewConnector;
-import com.provectus.kafka.ui.api.model.TopicCreation;
+import com.provectus.kafka.ui.api.model.*;
 import com.provectus.kafka.ui.base.TestConfiguration;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
@@ -35,7 +32,22 @@ public class ApiHelper {
         return new TopicsApi(new ApiClient().setBasePath(baseURL));
     }
 
+    @SneakyThrows
+    private SchemasApi schemaApi() {
+        return new SchemasApi(new ApiClient().setBasePath(baseURL));
+    }
+
+    @SneakyThrows
+    private KafkaConnectApi connectorApi() {
+        return new KafkaConnectApi(new ApiClient().setBasePath(baseURL));
+    }
+
+    @SneakyThrows
+    private MessagesApi messageApi() {
+        return new MessagesApi(new ApiClient().setBasePath(baseURL));
+    }
 
+    @SneakyThrows
     public void createTopic(String clusterName, String topicName) {
         TopicCreation topic = new TopicCreation();
         topic.setName(topicName);
@@ -50,26 +62,32 @@ public class ApiHelper {
         }
     }
 
-
     public void deleteTopic(String clusterName, String topicName) {
         try {
             topicApi().deleteTopic(clusterName, topicName).block();
+        } catch (WebClientResponseException ignore) {
+        }
+    }
+
+    @SneakyThrows
+    public void createSchema(String clusterName, String schemaName, SchemaType type, String schemaValue) {
+        NewSchemaSubject schemaSubject = new NewSchemaSubject();
+        schemaSubject.setSubject(schemaName);
+        schemaSubject.setSchema(schemaValue);
+        schemaSubject.setSchemaType(type);
+        try {
+            schemaApi().createNewSchema(clusterName, schemaSubject).block();
         } catch (WebClientResponseException ex) {
-            ErrorResponse errorResponse = new Gson().fromJson(ex.getResponseBodyAsString(), ErrorResponse.class);
-            if (errorResponse.getMessage().startsWith("This server does not host this")) {
-                log.info("This server does not host this " + topicName);
-            } else {
-                throw ex;
-            }
+            ex.printStackTrace();
         }
     }
 
     @SneakyThrows
-    private KafkaConnectApi connectorApi() {
-        ApiClient defaultClient = new ApiClient();
-        defaultClient.setBasePath(baseURL);
-        KafkaConnectApi connectorsApi = new KafkaConnectApi(defaultClient);
-        return connectorsApi;
+    public void deleteSchema(String clusterName, String schemaName) {
+        try {
+            schemaApi().deleteSchema(clusterName, schemaName).block();
+        } catch (WebClientResponseException ignore) {
+        }
     }
 
     @SneakyThrows
@@ -88,7 +106,7 @@ public class ApiHelper {
         connector.setConfig(configMap);
         try {
             connectorApi().deleteConnector(clusterName, connectName, connectorName).block();
-        } catch (WebClientResponseException ignored){
+        } catch (WebClientResponseException ignored) {
         }
         connectorApi().createConnector(clusterName, connectName, connector).block();
     }
@@ -97,17 +115,9 @@ public class ApiHelper {
         return connectorApi().getConnects(clusterName).blockFirst().getName();
     }
 
-    @SneakyThrows
-    private MessagesApi messageApi() {
-        ApiClient defaultClient = new ApiClient();
-        defaultClient.setBasePath(baseURL);
-        MessagesApi messagesApi = new MessagesApi(defaultClient);
-        return messagesApi;
-    }
-
     @SneakyThrows
     public void sendMessage(String clusterName, String topicName, String messageContentJson,
-            String messageKey) {
+                            String messageKey) {
         CreateTopicMessage createMessage = new CreateTopicMessage();
         createMessage.partition(0);
         createMessage.setContent(messageContentJson);

+ 11 - 9
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/MainPage.java

@@ -42,18 +42,20 @@ public class MainPage {
     }
 
 
-    public enum SideMenuOptions {
-        BROKERS("Brokers"),
-        TOPICS("Topics"),
-        CONSUMERS("Consumers"),
-        SCHEMA_REGISTRY("Schema registry");
+  public enum SideMenuOptions {
+    BROKERS("Brokers"),
+    TOPICS("Topics"),
+    CONSUMERS("Consumers"),
+    SCHEMA_REGISTRY("Schema Registry");
 
-        String value;
+    String value;
 
-        SideMenuOptions(String value) {
-            this.value = value;
-        }
+    SideMenuOptions(String value) {
+      this.value = value;
     }
+  }
+
+
 
     @Step
     public MainPage goToSideMenu(String clusterName, SideMenuOptions option) {

+ 4 - 1
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/Pages.java

@@ -2,6 +2,7 @@ package com.provectus.kafka.ui.pages;
 
 import com.provectus.kafka.ui.pages.connector.ConnectorsList;
 import com.provectus.kafka.ui.pages.connector.ConnectorsView;
+import com.provectus.kafka.ui.pages.schema.SchemaRegistryList;
 import com.provectus.kafka.ui.pages.topic.TopicView;
 import com.provectus.kafka.ui.pages.topic.TopicsList;
 
@@ -12,11 +13,13 @@ public class Pages {
     public MainPage mainPage = new MainPage();
     public TopicsList topicsList = new TopicsList();
     public TopicView topicView = new TopicView();
+    public ProduceMessagePage produceMessagePage = new ProduceMessagePage();
     public ConnectorsList connectorsList = new ConnectorsList();
     public ConnectorsView connectorsView = new ConnectorsView();
+    public SchemaRegistryList schemaRegistry = new SchemaRegistryList();
 
     public MainPage open() {
-       return openMainPage();
+        return openMainPage();
     }
 
     public MainPage openMainPage() {

+ 43 - 0
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/ProduceMessagePage.java

@@ -0,0 +1,43 @@
+package com.provectus.kafka.ui.pages;
+
+import com.codeborne.selenide.Condition;
+import com.codeborne.selenide.SelenideElement;
+import com.provectus.kafka.ui.pages.topic.TopicView;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+
+import static com.codeborne.selenide.Selenide.$;
+import static com.codeborne.selenide.Selenide.Wait;
+
+public class ProduceMessagePage{
+
+    private final SelenideElement keyField = $(By.xpath("//div[@id = 'key']/textarea"));
+    private final SelenideElement contentField = $(By.xpath("//div[@id = 'content']/textarea"));
+    private final SelenideElement headersField = $(By.xpath("//div[@id = 'headers']/textarea"));
+    private final SelenideElement sendBtn = $(By.xpath("//button[@type = 'submit']"));
+
+    public ProduceMessagePage setKeyField(String value) {
+        Wait().until(ExpectedConditions.urlContains("message"));
+        keyField.sendKeys(Keys.chord(Keys.DELETE));
+        keyField.setValue(value);
+        return this;
+    }
+
+    public ProduceMessagePage setContentFiled(String value) {
+        Wait().until(ExpectedConditions.urlContains("message"));
+        contentField.sendKeys(Keys.DELETE);
+        contentField.setValue(value);
+        return this;
+    }
+
+    public ProduceMessagePage setHeaderFiled(String value) {
+        headersField.setValue(value);
+        return new ProduceMessagePage();
+    }
+
+    public TopicView submitProduceMessage() {
+        sendBtn.shouldBe(Condition.visible).click();
+        return new TopicView();
+    }
+}

+ 4 - 2
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/connector/ConnectorUpdateView.java

@@ -5,6 +5,7 @@ import com.codeborne.selenide.SelenideElement;
 import com.provectus.kafka.ui.utils.BrowserUtils;
 import io.qameta.allure.Step;
 import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
 
 import static com.codeborne.selenide.Selectors.byLinkText;
 import static com.codeborne.selenide.Selenide.*;
@@ -33,8 +34,9 @@ public class ConnectorUpdateView {
     }
 
     @Step("Set connector config JSON")
-    public ConnectorsView updConnectorConfig(String configJson) throws InterruptedException {
-        contentTextArea.doubleClick();
+    public ConnectorsView updConnectorConfig(String configJson) {
+        $("#config").click();
+        contentTextArea.sendKeys(Keys.LEFT_CONTROL+"a");
         contentTextArea.setValue("");
         contentTextArea.setValue(String.valueOf(configJson.toCharArray()));
         $("#config").click();

+ 51 - 0
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/schema/SchemaCreateView.java

@@ -0,0 +1,51 @@
+package com.provectus.kafka.ui.pages.schema;
+
+import com.codeborne.selenide.SelenideElement;
+import com.provectus.kafka.ui.utils.BrowserUtils;
+import org.openqa.selenium.By;
+
+import static com.codeborne.selenide.Selenide.$;
+import static com.codeborne.selenide.Selenide.$x;
+
+public class SchemaCreateView {
+
+    private SelenideElement subjectName = $(By.xpath("//input[@name='subject']"));
+    private SelenideElement schemaField = $(By.xpath("//textarea[@name='schema']"));
+    private SelenideElement submitSchemaButton = $(By.xpath("//button[@type='submit']"));
+
+    public SchemaCreateView selectSchemaTypeFromDropdown(SchemaType schemaType) {
+        $("ul[role='listbox']").click();
+        $x("//li[text()='" + schemaType.getValue() + "']").click();
+        return this;
+    }
+
+    public SchemaView clickSubmit() {
+        BrowserUtils.javaExecutorClick(submitSchemaButton);
+        return new SchemaView();
+    }
+
+    public SchemaCreateView setSubjectName(String name) {
+        subjectName.setValue(name);
+        return this;
+    }
+
+    public SchemaCreateView setSchemaField(String text) {
+        schemaField.setValue(text);
+        return this;
+    }
+
+    public enum SchemaType {
+        AVRO("AVRO"),
+        JSON("JSON"),
+        PROTOBUF("PROTOBUF");
+
+        String value;
+
+        SchemaType(String value) {
+            this.value = value;
+        }
+        public String getValue(){
+            return value;
+        }
+    }
+}

+ 52 - 0
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/schema/SchemaEditView.java

@@ -0,0 +1,52 @@
+package com.provectus.kafka.ui.pages.schema;
+
+import com.codeborne.selenide.Condition;
+import com.codeborne.selenide.Selenide;
+import com.codeborne.selenide.SelenideElement;
+import com.provectus.kafka.ui.api.model.CompatibilityLevel;
+import com.provectus.kafka.ui.utils.BrowserUtils;
+import io.qameta.allure.Step;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+
+import static com.codeborne.selenide.Selenide.$;
+import static com.codeborne.selenide.Selenide.$x;
+
+public class SchemaEditView {
+
+    SelenideElement newSchemaTextArea = $("#newSchema [wrap]");
+
+
+    public SchemaEditView selectSchemaTypeFromDropdown(SchemaCreateView.SchemaType schemaType) {
+        $x("//ul[@name='schemaType']").click();
+        $x("//li[text()='" + schemaType.getValue() + "']").click();
+        return this;
+    }
+
+    public SchemaEditView selectCompatibilityLevelFromDropdown(CompatibilityLevel.CompatibilityEnum level) {
+        $x("//ul[@name='compatibilityLevel']").click();
+        $x("//li[text()='" + level.getValue() + "']").click();
+        return this;
+    }
+
+    public SchemaView clickSubmit() {
+        BrowserUtils.javaExecutorClick($(By.xpath("//button[@type='submit']")));
+        return new SchemaView();
+    }
+
+    @Step("Set new schema value")
+    public SchemaEditView setNewSchemaValue(String configJson) {
+        $("#newSchema").click();
+        newSchemaTextArea.sendKeys(Keys.CONTROL + "a", Keys.BACK_SPACE);
+        Selenide.executeJavaScript("arguments[0].value = '';", $("#newSchema"));
+        newSchemaTextArea.setValue(configJson);
+        return this;
+    }
+
+
+    public SchemaRegistryList removeSchema() {
+        $(By.xpath("//*[contains(text(),'Remove')]")).click();
+        $(By.xpath("//*[text()='Confirm']")).shouldBe(Condition.visible).click();
+        return new SchemaRegistryList();
+    }
+}

+ 40 - 0
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/schema/SchemaRegistryList.java

@@ -0,0 +1,40 @@
+package com.provectus.kafka.ui.pages.schema;
+
+import com.codeborne.selenide.Condition;
+import com.codeborne.selenide.SelenideElement;
+import com.provectus.kafka.ui.utils.BrowserUtils;
+import io.qameta.allure.Step;
+import lombok.SneakyThrows;
+import org.openqa.selenium.By;
+
+import static com.codeborne.selenide.Selenide.*;
+
+public class SchemaRegistryList {
+
+    private SelenideElement schemaButton = $(By.xpath("//*[contains(text(),'Create Schema')]"));
+
+    public SchemaCreateView clickCreateSchema() {
+        BrowserUtils.javaExecutorClick(schemaButton);
+        return new SchemaCreateView();
+    }
+
+    public SchemaView openSchema(String schemaName) {
+        $(By.xpath("//*[contains(text(),'" + schemaName + "')]")).click();
+        return new SchemaView();
+    }
+
+    @SneakyThrows
+    public SchemaRegistryList isNotVisible(String schemaName) {
+        $x(String.format("//*[contains(text(),'%s')]",schemaName)).shouldNotBe(Condition.visible);
+        return this;
+    }
+
+    @Step
+    public SchemaRegistryList isSchemaVisible(String schemaName) {
+        $$("tbody td>a")
+                .find(Condition.exactText(schemaName))
+                .shouldBe(Condition.visible);
+        return this;
+    }
+}
+

+ 38 - 0
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/schema/SchemaView.java

@@ -0,0 +1,38 @@
+package com.provectus.kafka.ui.pages.schema;
+
+import com.codeborne.selenide.Condition;
+import com.provectus.kafka.ui.api.model.CompatibilityLevel;
+import com.provectus.kafka.ui.utils.BrowserUtils;
+import io.qameta.allure.Step;
+import org.openqa.selenium.By;
+
+import static com.codeborne.selenide.Selenide.$;
+import static com.codeborne.selenide.Selenide.$x;
+
+public class SchemaView {
+
+    @Step
+    public SchemaView isOnSchemaViewPage() {
+        $("div#schema").shouldBe(Condition.visible);
+        return this;
+    }
+
+    @Step
+    public SchemaView isCompatibility(CompatibilityLevel.CompatibilityEnum compatibility){
+        $x("//div//p[.='" + compatibility.getValue() + "']").shouldBe(Condition.visible);
+        return this;
+    }
+
+    @Step
+    public SchemaEditView openEditSchema(){
+        $x("//button[text()= 'Edit Schema']").click();
+        return new SchemaEditView();
+    }
+
+    public SchemaRegistryList removeSchema() {
+        BrowserUtils.javaExecutorClick($(".dropdown.is-right button"));
+        $(By.xpath("//*[contains(text(),'Remove')]")).click();
+        $(By.xpath("//*[text()='Submit']")).shouldBe(Condition.visible).click();
+        return new SchemaRegistryList();
+    }
+}

+ 3 - 4
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/topic/TopicCreateEditSettingsView.java

@@ -14,7 +14,7 @@ public class TopicCreateEditSettingsView {
     private final SelenideElement timeToRetain = $(By.cssSelector("input#timeToRetain"));
     private final SelenideElement maxMessageBytes = $(By.name("maxMessageBytes"));
 
-    public TopicCreateEditSettingsView setTopicName(String topicName){
+    public TopicCreateEditSettingsView setTopicName(String topicName) {
         $("input#topicFormName").setValue(topicName);
         return this;
     }
@@ -68,11 +68,10 @@ public class TopicCreateEditSettingsView {
 
     public TopicCreateEditSettingsView selectCleanupPolicy(String cleanupPolicyOptionValue) {
         $("ul#topicFormCleanupPolicy").click();
-        $x("//li[text()='" + cleanupPolicyOptionValue +"']").click();
+        $x("//li[text()='" + cleanupPolicyOptionValue + "']").click();
         return this;
     }
 
-
     public TopicCreateEditSettingsView selectRetentionBytes(String visibleValue) {
         return selectFromDropDownByVisibleText("retentionBytes", visibleValue);
     }
@@ -158,7 +157,7 @@ public class TopicCreateEditSettingsView {
         private SelenideElement selectElement;
 
         public KafkaUISelectElement(String selectElementName) {
-            this.selectElement = $("ul[role=listbox][name="+selectElementName+"]");
+            this.selectElement = $("ul[role=listbox][name=" + selectElementName + "]");
         }
 
         public KafkaUISelectElement(SelenideElement selectElement) {

+ 48 - 11
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/pages/topic/TopicView.java

@@ -5,9 +5,12 @@ import com.codeborne.selenide.Selenide;
 import com.codeborne.selenide.SelenideElement;
 import com.provectus.kafka.ui.base.TestConfiguration;
 import com.provectus.kafka.ui.extensions.WaitUtils;
+import com.provectus.kafka.ui.pages.ProduceMessagePage;
+import com.provectus.kafka.ui.utils.BrowserUtils;
 import io.qameta.allure.Step;
 import lombok.SneakyThrows;
 import lombok.experimental.ExtensionMethod;
+import org.openqa.selenium.By;
 
 import static com.codeborne.selenide.Selectors.byLinkText;
 import static com.codeborne.selenide.Selenide.*;
@@ -16,7 +19,7 @@ import static com.codeborne.selenide.Selenide.*;
 public class TopicView {
 
     private static final String path = "/ui/clusters/%s/topics/%s";
-    private final SelenideElement dotMenuHeader = $(".fPWftu.sc-fHYyUA > .dropdown.is-right");
+    private final SelenideElement dotMenuHeader = $$(".dropdown.is-right button").first();
     private final SelenideElement dotMenuFooter = $$(".dropdown.is-right button").get(1);
 
     @Step
@@ -27,30 +30,47 @@ public class TopicView {
 
     @Step
     public TopicView isOnTopicViewPage() {
-       $("nav[role=navigation] a.is-active.is-primary").shouldBe(Condition.visible);
+        $(By.linkText("Overview")).shouldBe(Condition.visible);
         return this;
     }
 
     @SneakyThrows
     public TopicCreateEditSettingsView openEditSettings() {
-        dotMenuHeader.click();
-        $x("//a[text()= '" + DotMenuHeaderItems.EDIT_SETTINGS.getValue() +"']").click();
+        BrowserUtils.javaExecutorClick(dotMenuHeader);
+        $x("//a[text()= '" + DotMenuHeaderItems.EDIT_SETTINGS.getValue() + "']").click();
         return new TopicCreateEditSettingsView();
     }
 
+    @Step
+    public TopicView openTopicMenu(TopicMenu menu) {
+        $(By.linkText(menu.getValue())).shouldBe(Condition.visible).click();
+        return this;
+    }
 
     @SneakyThrows
     public TopicsList deleteTopic() {
-        dotMenuHeader.click();
+        BrowserUtils.javaExecutorClick(dotMenuHeader);
         $("#dropdown-menu").$(byLinkText(DotMenuHeaderItems.REMOVE_TOPIC.getValue())).click();
         $$("div[role=\"dialog\"] button").find(Condition.exactText("Submit")).click();
         return new TopicsList();
     }
 
+    @SneakyThrows
+    public ProduceMessagePage clickOnButton(String buttonName) {
+        BrowserUtils.javaExecutorClick($(By.xpath("//div//button[text()='%s']".formatted(buttonName))));
+        return new ProduceMessagePage();
+    }
+
+    public boolean isKeyMessageVisible(String keyMessage) {
+        return keyMessage.equals($("td[title]").getText());
+    }
+
+    public boolean isContentMessageVisible(String contentMessage) {
+        return contentMessage.equals($(".bPpPJI.sc-gkdBiK").getText());
+    }
+
     private enum DotMenuHeaderItems {
-        EDIT_SETTINGS("Edit settings"),
-        CLEAR_MESSAGES("Clear messages"),
-        REMOVE_TOPIC("Remove topic");
+        EDIT_SETTINGS("Edit settings"), CLEAR_MESSAGES("Clear messages"), REMOVE_TOPIC("Remove topic");
 
         private String value;
 
@@ -64,9 +84,26 @@ public class TopicView {
 
         @Override
         public String toString() {
-            return "DotMenuHeaderItems{" +
-                    "value='" + value + '\'' +
-                    '}';
+            return "DotMenuHeaderItems{" + "value='" + value + '\'' + '}';
+        }
+    }
+
+    public enum TopicMenu {
+        OVERVIEW("Overview"), MESSAGES("Messages"), CONSUMERS("Consumers"), SETTINGS("Settings");
+
+        private String value;
+
+        TopicMenu(String value) {
+            this.value = value;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return "TopicMenu{" + "value='" + value + '\'' + '}';
         }
     }
 }

+ 2 - 2
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/tests/ConnectorsTests.java

@@ -72,7 +72,6 @@ public class ConnectorsTests extends BaseTest {
                 .connectorIsVisibleInList(SINK_CONNECTOR, TOPIC_FOR_CONNECTOR);
     }
 
-    //disable test due 500 error during create connector via api
     @SneakyThrows
     @DisplayName("should update a connector")
     @Test
@@ -83,7 +82,8 @@ public class ConnectorsTests extends BaseTest {
                 pages.connectorsView.connectorIsVisibleOnOverview();
         pages.connectorsView.openEditConfig()
                         .updConnectorConfig(FileUtils.getResourceAsString("config_for_update_connector.json"));
-        pages.openConnectorsList(LOCAL_CLUSTER).connectorIsVisibleInList(CONNECTOR_FOR_UPDATE, TOPIC_FOR_UPDATE_CONNECTOR);
+        pages.openConnectorsList(LOCAL_CLUSTER)
+                .connectorIsVisibleInList(CONNECTOR_FOR_UPDATE, TOPIC_FOR_UPDATE_CONNECTOR);
     }
 
     @SneakyThrows

+ 161 - 0
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/tests/SchemasTests.java

@@ -0,0 +1,161 @@
+package com.provectus.kafka.ui.tests;
+
+import com.provectus.kafka.ui.api.model.CompatibilityLevel;
+import com.provectus.kafka.ui.api.model.SchemaType;
+import com.provectus.kafka.ui.base.BaseTest;
+import com.provectus.kafka.ui.helpers.Helpers;
+import com.provectus.kafka.ui.pages.MainPage;
+import com.provectus.kafka.ui.pages.schema.SchemaCreateView;
+import lombok.SneakyThrows;
+import org.junit.jupiter.api.*;
+
+import static org.apache.kafka.common.utils.Utils.readFileAsString;
+
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class SchemasTests extends BaseTest {
+
+    public static final String SECOND_LOCAL = "secondLocal";
+    public static final String SCHEMA_AVRO_CREATE = "avro_schema";
+    public static final String SCHEMA_JSON_CREATE = "json_schema";
+    public static final String SCHEMA_PROTOBUF_CREATE = "protobuf_schema";
+    public static final String SCHEMA_AVRO_API_UPDATE = "avro_schema_for_update_api";
+    public static final String SCHEMA_AVRO_API = "avro_schema_api";
+    public static final String SCHEMA_JSON_API = "json_schema_api";
+    public static final String SCHEMA_PROTOBUF_API = "protobuf_schema_api";
+    private static final String PATH_AVRO_VALUE = System.getProperty("user.dir") + "/src/test/resources/schema_avro_value.json";
+    private static final String PATH_AVRO_FOR_UPDATE = System.getProperty("user.dir") + "/src/test/resources/schema_avro_for_update.json";
+    private static final String PATH_PROTOBUF_VALUE = System.getProperty("user.dir") + "/src/test/resources/schema_protobuf_value.txt";
+    private static final String PATH_JSON_VALUE = System.getProperty("user.dir") + "/src/test/resources/schema_Json_Value.json";
+
+    @BeforeAll
+    @SneakyThrows
+    public static void beforeAll() {
+        Helpers.INSTANCE.apiHelper.createSchema(SECOND_LOCAL, SCHEMA_AVRO_API_UPDATE, SchemaType.AVRO, readFileAsString(PATH_AVRO_VALUE));
+        Helpers.INSTANCE.apiHelper.createSchema(SECOND_LOCAL, SCHEMA_AVRO_API, SchemaType.AVRO, readFileAsString(PATH_AVRO_VALUE));
+        Helpers.INSTANCE.apiHelper.createSchema(SECOND_LOCAL, SCHEMA_JSON_API, SchemaType.JSON, readFileAsString(PATH_JSON_VALUE));
+        Helpers.INSTANCE.apiHelper.createSchema(SECOND_LOCAL, SCHEMA_PROTOBUF_API, SchemaType.PROTOBUF, readFileAsString(PATH_PROTOBUF_VALUE));
+    }
+
+    @AfterAll
+    @SneakyThrows
+    public static void afterAll() {
+        Helpers.INSTANCE.apiHelper.deleteSchema(SECOND_LOCAL, SCHEMA_AVRO_CREATE);
+        Helpers.INSTANCE.apiHelper.deleteSchema(SECOND_LOCAL, SCHEMA_JSON_CREATE);
+        Helpers.INSTANCE.apiHelper.deleteSchema(SECOND_LOCAL, SCHEMA_PROTOBUF_CREATE);
+        Helpers.INSTANCE.apiHelper.deleteSchema(SECOND_LOCAL, SCHEMA_AVRO_API_UPDATE);
+        Helpers.INSTANCE.apiHelper.deleteSchema(SECOND_LOCAL, SCHEMA_AVRO_API);
+        Helpers.INSTANCE.apiHelper.deleteSchema(SECOND_LOCAL, SCHEMA_JSON_API);
+        Helpers.INSTANCE.apiHelper.deleteSchema(SECOND_LOCAL, SCHEMA_PROTOBUF_API);
+
+    }
+
+    @SneakyThrows
+    @DisplayName("should create AVRO schema")
+    @Test
+    @Order(1)
+    void createSchemaAvro() {
+        pages.openMainPage()
+                .goToSideMenu(SECOND_LOCAL, MainPage.SideMenuOptions.SCHEMA_REGISTRY);
+        pages.schemaRegistry.clickCreateSchema()
+                .setSubjectName(SCHEMA_AVRO_CREATE)
+                .setSchemaField(readFileAsString(PATH_AVRO_VALUE))
+                .selectSchemaTypeFromDropdown(SchemaCreateView.SchemaType.AVRO)
+                .clickSubmit()
+                .isOnSchemaViewPage();
+        pages.mainPage
+                .goToSideMenu(SECOND_LOCAL, MainPage.SideMenuOptions.SCHEMA_REGISTRY);
+        pages.schemaRegistry.isSchemaVisible(SCHEMA_AVRO_CREATE);
+    }
+
+    @SneakyThrows
+    @DisplayName("should update AVRO schema")
+    @Test
+    @Order(2)
+    void updateSchemaAvro() {
+        pages.openMainPage()
+                .goToSideMenu(SECOND_LOCAL, MainPage.SideMenuOptions.SCHEMA_REGISTRY);
+        pages.schemaRegistry.openSchema(SCHEMA_AVRO_API_UPDATE)
+                .isOnSchemaViewPage()
+                .openEditSchema()
+                .selectCompatibilityLevelFromDropdown(CompatibilityLevel.CompatibilityEnum.NONE)
+                .setNewSchemaValue(readFileAsString(PATH_AVRO_FOR_UPDATE))
+                .clickSubmit()
+                .isOnSchemaViewPage()
+                .isCompatibility(CompatibilityLevel.CompatibilityEnum.NONE);
+    }
+
+    @SneakyThrows
+    @DisplayName("should delete AVRO schema")
+    @Test
+    @Order(3)
+    void deleteSchemaAvro() {
+        pages.openMainPage()
+                .goToSideMenu(SECOND_LOCAL, MainPage.SideMenuOptions.SCHEMA_REGISTRY);
+        pages.schemaRegistry.openSchema(SCHEMA_AVRO_API)
+                .isOnSchemaViewPage()
+                .removeSchema()
+                .isNotVisible(SCHEMA_AVRO_API);
+    }
+
+    @SneakyThrows
+    @DisplayName("should create JSON schema")
+    @Test
+    @Order(4)
+    void createSchemaJson() {
+        pages.openMainPage()
+                .goToSideMenu(SECOND_LOCAL, MainPage.SideMenuOptions.SCHEMA_REGISTRY);
+        pages.schemaRegistry.clickCreateSchema()
+                .setSubjectName(SCHEMA_JSON_CREATE)
+                .setSchemaField(readFileAsString(PATH_JSON_VALUE))
+                .selectSchemaTypeFromDropdown(SchemaCreateView.SchemaType.JSON)
+                .clickSubmit()
+                .isOnSchemaViewPage();
+        pages.mainPage
+                .goToSideMenu(SECOND_LOCAL, MainPage.SideMenuOptions.SCHEMA_REGISTRY);
+        pages.schemaRegistry.isSchemaVisible(SCHEMA_JSON_CREATE);
+    }
+
+    @SneakyThrows
+    @DisplayName("should delete JSON schema")
+    @Test
+    @Order(5)
+    void deleteSchemaJson() {
+        pages.openMainPage()
+                .goToSideMenu(SECOND_LOCAL, MainPage.SideMenuOptions.SCHEMA_REGISTRY);
+        pages.schemaRegistry.openSchema(SCHEMA_JSON_API)
+                .isOnSchemaViewPage()
+                .removeSchema()
+                .isNotVisible(SCHEMA_JSON_API);
+    }
+
+    @SneakyThrows
+    @DisplayName("should create PROTOBUF schema")
+    @Test
+    @Order(6)
+    void createSchemaProtobuf() {
+        pages.openMainPage()
+                .goToSideMenu(SECOND_LOCAL, MainPage.SideMenuOptions.SCHEMA_REGISTRY);
+        pages.schemaRegistry.clickCreateSchema()
+                .setSubjectName(SCHEMA_PROTOBUF_CREATE)
+                .setSchemaField(readFileAsString(PATH_PROTOBUF_VALUE))
+                .selectSchemaTypeFromDropdown(SchemaCreateView.SchemaType.PROTOBUF)
+                .clickSubmit()
+                .isOnSchemaViewPage();
+        pages.mainPage
+                .goToSideMenu(SECOND_LOCAL, MainPage.SideMenuOptions.SCHEMA_REGISTRY);
+        pages.schemaRegistry.isSchemaVisible(SCHEMA_PROTOBUF_CREATE);
+    }
+
+    @SneakyThrows
+    @DisplayName("should delete PROTOBUF schema")
+    @Test
+    @Order(7)
+    void deleteSchemaProtobuf() {
+        pages.openMainPage()
+                .goToSideMenu(SECOND_LOCAL, MainPage.SideMenuOptions.SCHEMA_REGISTRY);
+        pages.schemaRegistry.openSchema(SCHEMA_PROTOBUF_API)
+                .isOnSchemaViewPage()
+                .removeSchema()
+                .isNotVisible(SCHEMA_PROTOBUF_API);
+    }
+}

+ 29 - 0
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/tests/TopicTests.java

@@ -3,10 +3,14 @@ package com.provectus.kafka.ui.tests;
 import com.provectus.kafka.ui.base.BaseTest;
 import com.provectus.kafka.ui.helpers.Helpers;
 import com.provectus.kafka.ui.pages.MainPage;
+import com.provectus.kafka.ui.pages.topic.TopicView;
 import io.qameta.allure.Issue;
 import lombok.SneakyThrows;
 import org.junit.jupiter.api.*;
 
+import static org.apache.kafka.common.utils.Utils.readFileAsString;
+
+
 public class TopicTests extends BaseTest {
 
     public static final String NEW_TOPIC = "new-topic";
@@ -17,6 +21,11 @@ public class TopicTests extends BaseTest {
     public static final String UPDATED_TIME_TO_RETAIN_VALUE = "604800001";
     public static final String UPDATED_MAX_SIZE_ON_DISK = "20 GB";
     public static final String UPDATED_MAX_MESSAGE_BYTES = "1000020";
+    private static final String KEY_TO_PRODUCE_MESSAGE = System.getProperty("user.dir") + "/src/test/resources/producedkey.txt";
+    private static final String CONTENT_TO_PRODUCE_MESSAGE = System.getProperty("user.dir") + "/src/test/resources/testData.txt";
+
+
+
 
     @BeforeAll
     @SneakyThrows
@@ -61,6 +70,7 @@ public class TopicTests extends BaseTest {
         pages.openTopicsList(SECOND_LOCAL)
                 .isOnPage();
         pages.openTopicView(SECOND_LOCAL, TOPIC_TO_UPDATE)
+                .isOnTopicViewPage()
                 .openEditSettings()
                 .selectCleanupPolicy(COMPACT_POLICY_VALUE)
                 .setMinInsyncReplicas(10)
@@ -93,4 +103,23 @@ public class TopicTests extends BaseTest {
                 .isOnPage()
                 .isTopicNotVisible(TOPIC_TO_DELETE);
     }
+
+    @Disabled("Due to issue https://github.com/provectus/kafka-ui/issues/2140 ignore this test")
+    @Issue("2140")
+    @SneakyThrows
+    @DisplayName("produce message")
+    @Test
+    void produceMessage(){
+        pages.openTopicsList(SECOND_LOCAL)
+                .isOnPage()
+                .openTopic(TOPIC_TO_UPDATE)
+                .isOnTopicViewPage()
+                .openTopicMenu(TopicView.TopicMenu.MESSAGES)
+                .clickOnButton("Produce Message")
+                .setContentFiled(readFileAsString(CONTENT_TO_PRODUCE_MESSAGE))
+                .setKeyField(readFileAsString(KEY_TO_PRODUCE_MESSAGE))
+                .submitProduceMessage();
+                Assertions.assertTrue(pages.topicView.isKeyMessageVisible(readFileAsString(KEY_TO_PRODUCE_MESSAGE)));
+                Assertions.assertTrue(pages.topicView.isContentMessageVisible(readFileAsString(CONTENT_TO_PRODUCE_MESSAGE)));
+    }
 }

+ 1 - 0
kafka-ui-e2e-checks/src/test/resources/producedkey.txt

@@ -0,0 +1 @@
+"key"

+ 7 - 0
kafka-ui-e2e-checks/src/test/resources/schema_Json_Value.json

@@ -0,0 +1,7 @@
+{
+  "connector.class": "io.confluent.connect.jdbc.JdbcSinkConnector",
+  "connection.url": "jdbc:postgresql://postgres-db:5432/test",
+  "connection.user": "dev_user",
+  "connection.password": "12345",
+  "topics": "topic_for_connector"
+}

+ 24 - 0
kafka-ui-e2e-checks/src/test/resources/schema_avro_for_update.json

@@ -0,0 +1,24 @@
+{
+  "type": "record",
+  "name": "Message",
+  "namespace": "com.provectus.kafka",
+  "fields": [
+    {
+      "name": "text",
+      "type": [
+        "null",
+        "string"
+      ],
+      "default": null
+    },
+    {
+      "name": "value",
+      "type": [
+        "null",
+        "string",
+        "long"
+      ],
+      "default": null
+    }
+  ]
+}

+ 15 - 0
kafka-ui-e2e-checks/src/test/resources/schema_avro_value.json

@@ -0,0 +1,15 @@
+{
+  "type": "record",
+  "name": "Student",
+  "namespace": "DataFlair",
+  "fields": [
+    {
+      "name": "Name",
+      "type": "string"
+    },
+    {
+      "name": "Age",
+      "type": "int"
+    }
+  ]
+}

+ 5 - 0
kafka-ui-e2e-checks/src/test/resources/schema_protobuf_value.txt

@@ -0,0 +1,5 @@
+enum SchemaType {
+  AVRO = 0;
+  JSON = 1;
+  PROTOBUF = 2;
+  }

+ 1 - 0
kafka-ui-e2e-checks/src/test/resources/testData.txt

@@ -0,0 +1 @@
+"print"