Browse Source

Merge branch 'master' into Topic_custom_params_are_disabled_upon_editing

David 2 years ago
parent
commit
be7f54b03b
34 changed files with 559 additions and 655 deletions
  1. 8 8
      .github/workflows/e2e-checks.yaml
  2. 10 1
      kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/OAuthPropertiesConverter.java
  3. 10 5
      kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/ReactiveAdminClient.java
  4. 0 3
      kafka-ui-e2e-checks/.env.example
  5. 1 1
      kafka-ui-e2e-checks/src/main/java/com/provectus/kafka/ui/pages/NaviSideBar.java
  6. 4 4
      kafka-ui-e2e-checks/src/main/java/com/provectus/kafka/ui/services/ApiService.java
  7. 1 1
      kafka-ui-e2e-checks/src/main/java/com/provectus/kafka/ui/settings/BaseSource.java
  8. 30 52
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/base/BaseTest.java
  9. 0 19
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/base/Config.java
  10. 2 2
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/base/Facade.java
  11. 0 53
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/base/Setup.java
  12. 6 6
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/suite/connectors/ConnectorsTests.java
  13. 3 3
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/suite/schemas/SchemasTests.java
  14. 3 3
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/suite/topics/TopicMessagesTests.java
  15. 3 4
      kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/suite/topics/TopicsTests.java
  16. 1 1
      kafka-ui-react-app/jest.config.ts
  17. 5 5
      kafka-ui-react-app/package.json
  18. 369 349
      kafka-ui-react-app/pnpm-lock.yaml
  19. 1 1
      kafka-ui-react-app/src/components/App.tsx
  20. 1 1
      kafka-ui-react-app/src/components/Connect/New/New.tsx
  21. 0 1
      kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/Details.spec.tsx
  22. 12 57
      kafka-ui-react-app/src/components/Schemas/Details/__test__/Details.spec.tsx
  23. 5 22
      kafka-ui-react-app/src/components/Schemas/Edit/__tests__/Edit.spec.tsx
  24. 17 13
      kafka-ui-react-app/src/components/Schemas/New/__test__/New.spec.tsx
  25. 11 8
      kafka-ui-react-app/src/components/Topics/List/__tests__/TopicTable.spec.tsx
  26. 5 10
      kafka-ui-react-app/src/components/Topics/New/__test__/New.spec.tsx
  27. 9 0
      kafka-ui-react-app/src/components/Topics/Topic/Messages/__test__/Messages.spec.tsx
  28. 19 9
      kafka-ui-react-app/src/components/Topics/Topic/Messages/__test__/MessagesTable.spec.tsx
  29. 1 1
      kafka-ui-react-app/src/components/Topics/Topic/Overview/Overview.tsx
  30. 10 4
      kafka-ui-react-app/src/components/Topics/Topic/Overview/__test__/Overview.spec.tsx
  31. 7 4
      kafka-ui-react-app/src/components/Topics/Topic/__test__/Topic.spec.tsx
  32. 4 2
      kafka-ui-react-app/src/components/common/NewTable/Table.tsx
  33. 0 0
      kafka-ui-react-app/src/components/globalCss.ts
  34. 1 2
      kafka-ui-react-app/vite.config.ts

+ 8 - 8
.github/workflows/e2e-checks.yaml

@@ -52,14 +52,14 @@ jobs:
           gh_pages: allure-results
           allure_report: allure-report
           subfolder: allure-results
-      - name: Deploy allure report to Github Pages
+      - uses: jakejarvis/s3-sync-action@master
         if: always()
-        uses: peaceiris/actions-gh-pages@v3
-        with:
-          github_token: ${{ secrets.GITHUB_TOKEN }}
-          publish_dir: allure-history
-          publish_branch: gh-pages
-          destination_dir: ./allure
+        env:
+          AWS_S3_BUCKET: 'kafkaui-allure-reports'
+          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+          AWS_REGION: 'eu-central-1'
+          SOURCE_DIR: 'allure-history/allure-results'
       - name: Post the link to allure report
         if: always()
         uses: Sibz/github-status-action@v1.1.6
@@ -68,7 +68,7 @@ jobs:
           context: "Test report"
           state: "success"
           sha: ${{ github.event.pull_request.head.sha  || github.sha }}
-          target_url: https://${{ github.repository_owner }}.github.io/kafka-ui/allure/allure-results/${{ github.run_number }}
+          target_url: http://kafkaui-allure-reports.s3-website.eu-central-1.amazonaws.com/${{ github.run_number }}
       - name: Dump docker logs on failure
         if: failure()
         uses: jwalton/gh-docker-logs@v2.2.1

+ 10 - 1
kafka-ui-api/src/main/java/com/provectus/kafka/ui/config/auth/OAuthPropertiesConverter.java

@@ -8,12 +8,14 @@ import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties;
+import org.springframework.security.config.oauth2.client.CommonOAuth2Provider;
 
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
 public final class OAuthPropertiesConverter {
 
   private static final String TYPE = "type";
   private static final String GOOGLE = "google";
+  public static final String DUMMY = "dummy";
 
   public static OAuth2ClientProperties convertProperties(final OAuthProperties properties) {
     final var result = new OAuth2ClientProperties();
@@ -57,7 +59,14 @@ public final class OAuthPropertiesConverter {
       return;
     }
 
-    final String newUri = provider.getAuthorizationUri() + "?hd=" + allowedDomain;
+    String authorizationUri = CommonOAuth2Provider.GOOGLE
+        .getBuilder(DUMMY)
+        .clientId(DUMMY)
+        .build()
+        .getProviderDetails()
+        .getAuthorizationUri();
+
+    final String newUri = authorizationUri + "?hd=" + allowedDomain;
     provider.setAuthorizationUri(newUri);
   }
 

+ 10 - 5
kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/ReactiveAdminClient.java

@@ -43,6 +43,7 @@ import org.apache.kafka.clients.admin.ConfigEntry;
 import org.apache.kafka.clients.admin.ConsumerGroupDescription;
 import org.apache.kafka.clients.admin.ConsumerGroupListing;
 import org.apache.kafka.clients.admin.DescribeClusterOptions;
+import org.apache.kafka.clients.admin.DescribeClusterResult;
 import org.apache.kafka.clients.admin.DescribeConfigsOptions;
 import org.apache.kafka.clients.admin.ListConsumerGroupOffsetsOptions;
 import org.apache.kafka.clients.admin.ListOffsetsResult;
@@ -80,7 +81,8 @@ public class ReactiveAdminClient implements Closeable {
 
   private enum SupportedFeature {
     INCREMENTAL_ALTER_CONFIGS(2.3f),
-    CONFIG_DOCUMENTATION_RETRIEVAL(2.6f);
+    CONFIG_DOCUMENTATION_RETRIEVAL(2.6f),
+    DESCRIBE_CLUSTER_INCLUDE_AUTHORIZED_OPERATIONS(2.3f);
 
     private final float sinceVersion;
 
@@ -300,11 +302,14 @@ public class ReactiveAdminClient implements Closeable {
   }
 
   public Mono<ClusterDescription> describeCluster() {
-    return describeClusterImpl(client);
+    return describeClusterImpl(client, features);
   }
 
-  private static Mono<ClusterDescription> describeClusterImpl(AdminClient client) {
-    var result = client.describeCluster(new DescribeClusterOptions().includeAuthorizedOperations(true));
+  private static Mono<ClusterDescription> describeClusterImpl(AdminClient client, Set<SupportedFeature> features) {
+    boolean includeAuthorizedOperations =
+        features.contains(SupportedFeature.DESCRIBE_CLUSTER_INCLUDE_AUTHORIZED_OPERATIONS);
+    DescribeClusterResult result = client.describeCluster(
+        new DescribeClusterOptions().includeAuthorizedOperations(includeAuthorizedOperations));
     var allOfFuture = KafkaFuture.allOf(
         result.controller(), result.clusterId(), result.nodes(), result.authorizedOperations());
     return toMono(allOfFuture).then(
@@ -320,7 +325,7 @@ public class ReactiveAdminClient implements Closeable {
   }
 
   private static Mono<String> getClusterVersion(AdminClient client) {
-    return describeClusterImpl(client)
+    return describeClusterImpl(client, Set.of())
         // choosing node from which we will get configs (starting with controller)
         .flatMap(descr -> descr.controller != null
             ? Mono.just(descr.controller)

+ 0 - 3
kafka-ui-e2e-checks/.env.example

@@ -1,3 +0,0 @@
-USE_LOCAL_BROWSER=true
-SHOULD_START_SELENOID=false
-TURN_OFF_SCREENSHOTS=true

+ 1 - 1
kafka-ui-e2e-checks/src/main/java/com/provectus/kafka/ui/pages/NaviSideBar.java

@@ -1,7 +1,7 @@
 package com.provectus.kafka.ui.pages;
 
 import static com.codeborne.selenide.Selenide.$x;
-import static com.provectus.kafka.ui.settings.Source.CLUSTER_NAME;
+import static com.provectus.kafka.ui.settings.BaseSource.CLUSTER_NAME;
 
 import com.codeborne.selenide.Condition;
 import com.codeborne.selenide.SelenideElement;

+ 4 - 4
kafka-ui-e2e-checks/src/main/java/com/provectus/kafka/ui/helpers/ApiHelper.java → kafka-ui-e2e-checks/src/main/java/com/provectus/kafka/ui/services/ApiService.java

@@ -1,4 +1,4 @@
-package com.provectus.kafka.ui.helpers;
+package com.provectus.kafka.ui.services;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.provectus.kafka.ui.api.ApiClient;
@@ -13,7 +13,7 @@ import com.provectus.kafka.ui.api.model.TopicCreation;
 import com.provectus.kafka.ui.models.Connector;
 import com.provectus.kafka.ui.models.Schema;
 import com.provectus.kafka.ui.models.Topic;
-import com.provectus.kafka.ui.settings.Source;
+import com.provectus.kafka.ui.settings.BaseSource;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.reactive.function.client.WebClientResponseException;
@@ -26,11 +26,11 @@ import static com.provectus.kafka.ui.utilities.FileUtils.fileToString;
 
 
 @Slf4j
-public class ApiHelper {
+public class ApiService {
 
     int partitions = 1;
     int replicationFactor = 1;
-    String baseURL = Source.BASE_API_URL;
+    String baseURL = BaseSource.BASE_API_URL;
 
 
     @SneakyThrows

+ 1 - 1
kafka-ui-e2e-checks/src/main/java/com/provectus/kafka/ui/settings/Source.java → kafka-ui-e2e-checks/src/main/java/com/provectus/kafka/ui/settings/BaseSource.java

@@ -1,6 +1,6 @@
 package com.provectus.kafka.ui.settings;
 
-public abstract class Source {
+public abstract class BaseSource {
 
   public static String BASE_API_URL = System.getProperty("BASE_URL", "http://localhost:8080");
   public static String BASE_WEB_URL = System.getProperty("BASE_DOCKER_URL", "http://host.testcontainers.internal:8080");

+ 30 - 52
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/base/BaseTest.java

@@ -1,18 +1,27 @@
 package com.provectus.kafka.ui.base;
 
+import static com.codeborne.selenide.Selenide.clearBrowserCookies;
+import static com.codeborne.selenide.Selenide.clearBrowserLocalStorage;
+import static com.codeborne.selenide.Selenide.refresh;
+import static com.provectus.kafka.ui.pages.NaviSideBar.SideMenuOption.TOPICS;
+import static com.provectus.kafka.ui.settings.BaseSource.BASE_WEB_URL;
+
 import com.codeborne.selenide.Condition;
 import com.codeborne.selenide.Selenide;
 import com.codeborne.selenide.SelenideElement;
 import com.codeborne.selenide.WebDriverRunner;
 import com.provectus.kafka.ui.utilities.qaseIoUtils.DisplayNameGenerator;
-import com.provectus.kafka.ui.utilities.qaseIoUtils.TestCaseGenerator;
-import io.github.cdimascio.dotenv.Dotenv;
 import io.qameta.allure.Allure;
 import io.qase.api.annotation.Step;
+import java.io.ByteArrayInputStream;
+import java.util.List;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.io.FileUtils;
 import org.assertj.core.api.SoftAssertions;
-import org.junit.jupiter.api.*;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayNameGeneration;
 import org.openqa.selenium.Dimension;
 import org.openqa.selenium.OutputType;
 import org.openqa.selenium.TakesScreenshot;
@@ -23,15 +32,6 @@ import org.testcontainers.containers.BrowserWebDriverContainer;
 import org.testcontainers.containers.output.Slf4jLogConsumer;
 import org.testcontainers.utility.DockerImageName;
 
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-
-import static com.provectus.kafka.ui.base.Setup.*;
-import static com.provectus.kafka.ui.pages.NaviSideBar.SideMenuOption.TOPICS;
-import static com.provectus.kafka.ui.settings.Source.BASE_WEB_URL;
-
 @Slf4j
 @DisplayNameGeneration(DisplayNameGenerator.class)
 public class BaseTest extends Facade {
@@ -44,22 +44,12 @@ public class BaseTest extends Facade {
     return System.getProperty("os.arch").equals("aarch64");
   }
 
-  @BeforeEach
-  public void setWebDriver() {
-    RemoteWebDriver remoteWebDriver = webDriverContainer.getWebDriver();
-    WebDriverRunner.setWebDriver(remoteWebDriver);
-    remoteWebDriver.manage().window().setSize(new Dimension(1440, 1024));
-    Selenide.open(BASE_WEB_URL);
-    naviSideBar.waitUntilScreenReady();
-  }
-
   @BeforeAll
   public static void start() {
     DockerImageName image = isARM64()
         ? DockerImageName.parse(SELENIARM_STANDALONE_CHROMIUM).asCompatibleSubstituteFor(SELENIUM_IMAGE_NAME)
         : DockerImageName.parse(SELENIUM_IMAGE_NAME);
     log.info("Using [{}] as image name for chrome", image.getUnversionedPart());
-
     webDriverContainer = new BrowserWebDriverContainer<>(image)
         .withEnv("JAVA_OPTS", "-Dwebdriver.chrome.whitelistedIps=")
         .withCapabilities(new ChromeOptions()
@@ -68,7 +58,7 @@ public class BaseTest extends Facade {
             .addArguments("--no-sandbox")
             .addArguments("--verbose")
         )
-            .withLogConsumer(new Slf4jLogConsumer(log).withPrefix("[CHROME]: "));
+        .withLogConsumer(new Slf4jLogConsumer(log).withPrefix("[CHROME]: "));
     try {
       Testcontainers.exposeHostPorts(8080);
       log.info("Starting browser container");
@@ -78,29 +68,6 @@ public class BaseTest extends Facade {
     }
   }
 
-  static {
-    if (!new File("./.env").exists()) {
-      try {
-        FileUtils.copyFile(new File(".env.example"), new File(".env"));
-      } catch (IOException e) {
-        log.error("couldn't copy .env.example to .env. Please add .env");
-        e.printStackTrace();
-      }
-    }
-    Dotenv.load().entries().forEach(env -> System.setProperty(env.getKey(), env.getValue()));
-    if (Config.CLEAR_REPORTS_DIR) {
-      clearReports();
-    }
-    setup();
-    Runtime.getRuntime().addShutdownHook(new Thread(() -> {
-      if (TestCaseGenerator.FAILED) {
-        log.error(
-                "Tests FAILED because some problem with @CaseId annotation. Verify that all tests annotated with @CaseId and Id is correct!");
-        Runtime.getRuntime().halt(100500);
-      }
-    }));
-  }
-
   @AfterAll
   public static void tearDown() {
     if (webDriverContainer.isRunning()) {
@@ -109,16 +76,27 @@ public class BaseTest extends Facade {
     }
   }
 
+  @BeforeEach
+  public void beforeMethod() {
+    RemoteWebDriver remoteWebDriver = webDriverContainer.getWebDriver();
+    WebDriverRunner.setWebDriver(remoteWebDriver);
+    remoteWebDriver.manage()
+        .window().setSize(new Dimension(1440, 1024));
+    Selenide.open(BASE_WEB_URL);
+    naviSideBar.waitUntilScreenReady();
+  }
+
   @AfterEach
   public void afterMethod() {
-    Allure.addAttachment("Screenshot",
-        new ByteArrayInputStream(
-            ((TakesScreenshot) webDriverContainer.getWebDriver()).getScreenshotAs(OutputType.BYTES)));
-    browserClear();
+    Allure.addAttachment("Screenshot", new ByteArrayInputStream(((TakesScreenshot)
+        webDriverContainer.getWebDriver()).getScreenshotAs(OutputType.BYTES)));
+    clearBrowserLocalStorage();
+    clearBrowserCookies();
+    refresh();
   }
 
   @Step
-  protected void navigateToTopics(){
+  protected void navigateToTopics() {
     naviSideBar
         .openSideMenu(TOPICS);
     topicsList

+ 0 - 19
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/base/Config.java

@@ -1,19 +0,0 @@
-package com.provectus.kafka.ui.base;
-
-public abstract class Config {
-
-  public static boolean CLEAR_REPORTS_DIR =
-          Boolean.parseBoolean(System.getProperty("CLEAR_REPORTS_DIR", "true"));
-  public static boolean USE_LOCAL_BROWSER =
-          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", "true"));
-  public static Boolean SAVE_PAGE_SOURCE =
-          Boolean.parseBoolean(System.getProperty("SAVE_PAGE_SOURCE", "false"));
-  public static Boolean REOPEN_BROWSER_ON_FAIL =
-          Boolean.parseBoolean(System.getProperty("REOPEN_BROWSER_ON_FAIL", "true"));
-  public static String BROWSER = System.getProperty("BROWSER", "chromium");
-  public static String BROWSER_SIZE = System.getProperty("BROWSER_SIZE", "1920x1080");
-  public static Boolean ENABLE_VNC = Boolean.parseBoolean(System.getProperty("ENABLE_VNC", "true"));
-}

+ 2 - 2
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/base/Facade.java

@@ -1,6 +1,6 @@
 package com.provectus.kafka.ui.base;
 
-import com.provectus.kafka.ui.helpers.ApiHelper;
+import com.provectus.kafka.ui.services.ApiService;
 import com.provectus.kafka.ui.pages.NaviSideBar;
 import com.provectus.kafka.ui.pages.TopPanel;
 import com.provectus.kafka.ui.pages.brokers.BrokersConfigTab;
@@ -21,7 +21,7 @@ import com.provectus.kafka.ui.pages.topic.TopicDetails;
 import com.provectus.kafka.ui.pages.topic.TopicsList;
 
 public abstract class Facade {
-    protected ApiHelper apiHelper = new ApiHelper();
+    protected ApiService apiService = new ApiService();
     protected ConnectorCreateForm connectorCreateForm = new ConnectorCreateForm();
     protected KafkaConnectList kafkaConnectList = new KafkaConnectList();
     protected ConnectorDetails connectorDetails = new ConnectorDetails();

+ 0 - 53
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/base/Setup.java

@@ -1,53 +0,0 @@
-package com.provectus.kafka.ui.base;
-
-import com.codeborne.selenide.Configuration;
-import com.codeborne.selenide.logevents.SelenideLogger;
-import io.qameta.allure.Step;
-import io.qameta.allure.selenide.AllureSelenide;
-import lombok.SneakyThrows;
-import lombok.extern.slf4j.Slf4j;
-
-import java.io.File;
-import java.util.Arrays;
-
-import static com.codeborne.selenide.Selenide.*;
-
-@Slf4j
-public abstract class Setup {
-
-    @SneakyThrows
-    static void setup() {
-        Configuration.reportsFolder = Config.REPORTS_FOLDER;
-        Configuration.screenshots = Config.SCREENSHOTS;
-        Configuration.savePageSource = Config.SAVE_PAGE_SOURCE;
-        Configuration.reopenBrowserOnFail = Config.REOPEN_BROWSER_ON_FAIL;
-        Configuration.browser = Config.BROWSER;
-        Configuration.timeout = 10000;
-        Configuration.pageLoadTimeout = 180000;
-        Configuration.browserSize = Config.BROWSER_SIZE;
-        SelenideLogger.addListener("allure", new AllureSelenide().savePageSource(false));
-    }
-
-    public static void clearReports() {
-        log.info(String.format("Clearing reports dir [%s]...", Config.REPORTS_FOLDER));
-        File allureResults = new File(Config.REPORTS_FOLDER);
-        if (allureResults.isDirectory()) {
-            File[] list = allureResults.listFiles();
-            if (list != null) {
-                Arrays.stream(list)
-                        .sequential()
-                        .filter(e -> !e.getName().equals("categories.json"))
-                        .forEach(File::delete);
-            }
-        }
-    }
-
-    @Step
-    public static void browserClear() {
-        log.debug("browserClear");
-        clearBrowserLocalStorage();
-        clearBrowserCookies();
-        refresh();
-        log.debug("=> DONE");
-    }
-}

+ 6 - 6
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/suite/connectors/ConnectorsTests.java

@@ -2,7 +2,7 @@ package com.provectus.kafka.ui.suite.connectors;
 
 import static com.provectus.kafka.ui.pages.BasePage.AlertHeader.SUCCESS;
 import static com.provectus.kafka.ui.pages.NaviSideBar.SideMenuOption.KAFKA_CONNECT;
-import static com.provectus.kafka.ui.settings.Source.CLUSTER_NAME;
+import static com.provectus.kafka.ui.settings.BaseSource.CLUSTER_NAME;
 import static com.provectus.kafka.ui.utilities.FileUtils.getResourceAsString;
 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
 
@@ -52,11 +52,11 @@ public class ConnectorsTests extends BaseTest {
     public void beforeAll() {
         TOPIC_LIST.addAll(List.of(TOPIC_FOR_CREATE, TOPIC_FOR_DELETE, TOPIC_FOR_UPDATE));
         TOPIC_LIST.forEach(topic -> {
-            apiHelper.createTopic(CLUSTER_NAME, topic.getName());
-            apiHelper.sendMessage(CLUSTER_NAME, topic);
+            apiService.createTopic(CLUSTER_NAME, topic.getName());
+            apiService.sendMessage(CLUSTER_NAME, topic);
         });
         CONNECTOR_LIST.addAll(List.of(CONNECTOR_FOR_DELETE, CONNECTOR_FOR_UPDATE));
-        CONNECTOR_LIST.forEach(connector -> apiHelper
+        CONNECTOR_LIST.forEach(connector -> apiService
                 .createConnector(CLUSTER_NAME, CONNECT_NAME, connector));
     }
 
@@ -120,8 +120,8 @@ public class ConnectorsTests extends BaseTest {
     @AfterAll
     public void afterAll() {
         CONNECTOR_LIST.forEach(connector ->
-                apiHelper.deleteConnector(CLUSTER_NAME, CONNECT_NAME, connector.getName()));
-        TOPIC_LIST.forEach(topic -> apiHelper.deleteTopic(CLUSTER_NAME, topic.getName()));
+                apiService.deleteConnector(CLUSTER_NAME, CONNECT_NAME, connector.getName()));
+        TOPIC_LIST.forEach(topic -> apiService.deleteTopic(CLUSTER_NAME, topic.getName()));
     }
 
     @Step

+ 3 - 3
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/suite/schemas/SchemasTests.java

@@ -1,7 +1,7 @@
 package com.provectus.kafka.ui.suite.schemas;
 
 import static com.provectus.kafka.ui.pages.NaviSideBar.SideMenuOption.SCHEMA_REGISTRY;
-import static com.provectus.kafka.ui.settings.Source.CLUSTER_NAME;
+import static com.provectus.kafka.ui.settings.BaseSource.CLUSTER_NAME;
 import static com.provectus.kafka.ui.utilities.FileUtils.fileToString;
 
 import com.codeborne.selenide.Condition;
@@ -41,7 +41,7 @@ public class SchemasTests extends BaseTest {
     @SneakyThrows
     public void beforeAll() {
         SCHEMA_LIST.addAll(List.of(AVRO_API, JSON_API, PROTOBUF_API));
-        SCHEMA_LIST.forEach(schema -> apiHelper.createSchema(CLUSTER_NAME, schema));
+        SCHEMA_LIST.forEach(schema -> apiService.createSchema(CLUSTER_NAME, schema));
     }
 
     @DisplayName("should create AVRO schema")
@@ -228,7 +228,7 @@ public class SchemasTests extends BaseTest {
 
     @AfterAll
     public void afterAll() {
-        SCHEMA_LIST.forEach(schema -> apiHelper.deleteSchema(CLUSTER_NAME, schema.getName()));
+        SCHEMA_LIST.forEach(schema -> apiService.deleteSchema(CLUSTER_NAME, schema.getName()));
     }
 
     @Step

+ 3 - 3
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/suite/topics/TopicMessagesTests.java

@@ -2,7 +2,7 @@ package com.provectus.kafka.ui.suite.topics;
 
 import static com.provectus.kafka.ui.pages.BasePage.AlertHeader.SUCCESS;
 import static com.provectus.kafka.ui.pages.topic.TopicDetails.TopicMenu.MESSAGES;
-import static com.provectus.kafka.ui.settings.Source.CLUSTER_NAME;
+import static com.provectus.kafka.ui.settings.BaseSource.CLUSTER_NAME;
 import static com.provectus.kafka.ui.utilities.FileUtils.fileToString;
 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
 
@@ -38,7 +38,7 @@ public class TopicMessagesTests extends BaseTest {
   @BeforeAll
   public void beforeAll() {
     TOPIC_LIST.addAll(List.of(TOPIC_FOR_MESSAGES));
-    TOPIC_LIST.forEach(topic -> apiHelper.createTopic(CLUSTER_NAME, topic.getName()));
+    TOPIC_LIST.forEach(topic -> apiService.createTopic(CLUSTER_NAME, topic.getName()));
   }
 
   @DisplayName("produce message")
@@ -136,6 +136,6 @@ public class TopicMessagesTests extends BaseTest {
 
   @AfterAll
   public void afterAll() {
-    TOPIC_LIST.forEach(topic -> apiHelper.deleteTopic(CLUSTER_NAME, topic.getName()));
+    TOPIC_LIST.forEach(topic -> apiService.deleteTopic(CLUSTER_NAME, topic.getName()));
   }
 }

+ 3 - 4
kafka-ui-e2e-checks/src/test/java/com/provectus/kafka/ui/suite/topics/TopicsTests.java

@@ -9,12 +9,11 @@ import static com.provectus.kafka.ui.pages.topic.enums.CustomParameterType.COMPR
 import static com.provectus.kafka.ui.pages.topic.enums.MaxSizeOnDisk.NOT_SET;
 import static com.provectus.kafka.ui.pages.topic.enums.MaxSizeOnDisk.SIZE_1_GB;
 import static com.provectus.kafka.ui.pages.topic.enums.MaxSizeOnDisk.SIZE_20_GB;
-import static com.provectus.kafka.ui.settings.Source.CLUSTER_NAME;
+import static com.provectus.kafka.ui.settings.BaseSource.CLUSTER_NAME;
 import static com.provectus.kafka.ui.utilities.FileUtils.fileToString;
 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.apache.commons.lang3.RandomUtils.nextInt;
-import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
 
 import com.codeborne.selenide.Condition;
 import com.provectus.kafka.ui.base.BaseTest;
@@ -70,7 +69,7 @@ public class TopicsTests extends BaseTest {
   @BeforeAll
   public void beforeAll() {
     TOPIC_LIST.addAll(List.of(TOPIC_TO_UPDATE, TOPIC_FOR_DELETE));
-    TOPIC_LIST.forEach(topic -> apiHelper.createTopic(CLUSTER_NAME, topic.getName()));
+    TOPIC_LIST.forEach(topic -> apiService.createTopic(CLUSTER_NAME, topic.getName()));
   }
 
   @DisplayName("should create a topic")
@@ -474,6 +473,6 @@ public class TopicsTests extends BaseTest {
 
   @AfterAll
   public void afterAll() {
-    TOPIC_LIST.forEach(topic -> apiHelper.deleteTopic(CLUSTER_NAME, topic.getName()));
+    TOPIC_LIST.forEach(topic -> apiService.deleteTopic(CLUSTER_NAME, topic.getName()));
   }
 }

+ 1 - 1
kafka-ui-react-app/jest.config.ts

@@ -19,7 +19,7 @@ export default {
   ],
   testEnvironment: 'jsdom',
   transform: {
-    '\\.[jt]sx?$': 'babel-jest',
+    '\\.[jt]sx?$': '@swc/jest',
     '^.+\\.css$': '<rootDir>/.jest/cssTransform.js',
   },
   transformIgnorePatterns: [

+ 5 - 5
kafka-ui-react-app/package.json

@@ -17,10 +17,8 @@
     "@tanstack/react-table": "^8.5.10",
     "@testing-library/react": "^13.2.0",
     "@types/testing-library__jest-dom": "^5.14.5",
-    "@vitejs/plugin-react": "^2.0.0",
     "ace-builds": "^1.7.1",
     "ajv": "^8.6.3",
-    "babel-jest": "^29.0.3",
     "classnames": "^2.2.6",
     "fetch-mock": "^9.11.0",
     "jest": "^29.0.3",
@@ -43,8 +41,8 @@
     "sass": "^1.52.3",
     "styled-components": "^5.3.1",
     "use-debounce": "^8.0.1",
-    "vite": "^3.0.2",
-    "vite-tsconfig-paths": "^3.5.0",
+    "vite": "^4.0.0",
+    "vite-tsconfig-paths": "^4.0.2",
     "whatwg-fetch": "^3.6.2",
     "yup": "^0.32.11",
     "zustand": "^4.1.1"
@@ -80,6 +78,8 @@
     "@babel/preset-typescript": "^7.17.12",
     "@jest/types": "^29.0.3",
     "@openapitools/openapi-generator-cli": "^2.5.1",
+    "@swc/core": "^1.3.22",
+    "@swc/jest": "^0.2.24",
     "@testing-library/dom": "^8.11.1",
     "@testing-library/jest-dom": "^5.16.4",
     "@testing-library/user-event": "^14.4.3",
@@ -94,6 +94,7 @@
     "@types/styled-components": "^5.1.13",
     "@typescript-eslint/eslint-plugin": "^5.29.0",
     "@typescript-eslint/parser": "^5.29.0",
+    "@vitejs/plugin-react-swc": "^3.0.0",
     "dotenv": "^16.0.1",
     "eslint": "^8.3.0",
     "eslint-config-airbnb": "^19.0.4",
@@ -115,7 +116,6 @@
     "lint-staged": "^13.0.2",
     "prettier": "^2.3.1",
     "rimraf": "^3.0.2",
-    "ts-jest": "^29.0.0",
     "ts-node": "^10.8.1",
     "ts-prune": "^0.10.3",
     "typescript": "^4.7.4"

File diff suppressed because it is too large
+ 369 - 349
kafka-ui-react-app/pnpm-lock.yaml


+ 1 - 1
kafka-ui-react-app/src/components/App.tsx

@@ -14,7 +14,7 @@ import theme from 'theme/theme';
 import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
 import { showServerError } from 'lib/errorHandling';
 import { Toaster } from 'react-hot-toast';
-import GlobalCSS from 'components/global.css';
+import GlobalCSS from 'components/globalCss';
 import * as S from 'components/App.styled';
 
 import ConfirmationModal from './common/ConfirmationModal/ConfirmationModal';

+ 1 - 1
kafka-ui-react-app/src/components/Connect/New/New.tsx

@@ -147,7 +147,7 @@ const New: React.FC = () => {
             control={control}
             name="config"
             render={({ field }) => (
-              <Editor {...field} readOnly={isSubmitting} />
+              <Editor {...field} readOnly={isSubmitting} ref={null} />
             )}
           />
           <FormError>

+ 0 - 1
kafka-ui-react-app/src/components/ConsumerGroups/Details/__tests__/Details.spec.tsx

@@ -77,7 +77,6 @@ describe('Details component', () => {
     });
 
     it('renders search input', async () => {
-      await renderComponent();
       expect(
         screen.getByPlaceholderText('Search by Topic Name')
       ).toBeInTheDocument();

+ 12 - 57
kafka-ui-react-app/src/components/Schemas/Details/__test__/Details.spec.tsx

@@ -2,7 +2,7 @@ import React from 'react';
 import Details from 'components/Schemas/Details/Details';
 import { render, WithRoute } from 'lib/testHelpers';
 import { clusterSchemaPath } from 'lib/paths';
-import { screen, waitFor } from '@testing-library/dom';
+import { screen } from '@testing-library/dom';
 import {
   schemasInitialState,
   schemaVersion,
@@ -50,44 +50,17 @@ describe('Details', () => {
   afterEach(() => fetchMock.reset());
 
   describe('fetch failed', () => {
-    beforeEach(async () => {
+    it('renders pageloader', async () => {
       const schemasAPILatestMock = fetchMock.getOnce(schemasAPILatestUrl, 404);
       const schemasAPIVersionsMock = fetchMock.getOnce(
         schemasAPIVersionsUrl,
         404
       );
-      await renderComponent();
-
-      await waitFor(() => {
-        expect(schemasAPILatestMock.called()).toBeTruthy();
-      });
-      await waitFor(() => {
-        expect(schemasAPIVersionsMock.called()).toBeTruthy();
-      });
-    });
-
-    it('handles [Delete schema] click', async () => {
-      const deleteSchemaMock = fetchMock.deleteOnce(
-        `/api/clusters/${clusterName}/schemas/${schemaVersion.subject}`,
-        200
-      );
-
       await act(() => {
         renderComponent();
       });
-
-      try {
-        expect(deleteSchemaMock.called()).toBeTruthy();
-        expect(mockHistoryPush).toHaveBeenCalledTimes(1);
-        expect(mockHistoryPush).toHaveBeenCalledWith(
-          clusterSchemaPath(clusterName)
-        );
-      } catch (e) {
-        expect(deleteSchemaMock.called()).toBeTruthy();
-      }
-    });
-
-    it('renders pageloader', () => {
+      expect(schemasAPILatestMock.called(schemasAPILatestUrl)).toBeTruthy();
+      expect(schemasAPIVersionsMock.called(schemasAPIVersionsUrl)).toBeTruthy();
       expect(screen.getByRole('progressbar')).toBeInTheDocument();
       expect(screen.queryByText(schemaVersion.subject)).not.toBeInTheDocument();
       expect(screen.queryByText('Edit Schema')).not.toBeInTheDocument();
@@ -97,7 +70,7 @@ describe('Details', () => {
 
   describe('fetch success', () => {
     describe('has schema versions', () => {
-      beforeEach(async () => {
+      it('renders component with schema info', async () => {
         const schemasAPILatestMock = fetchMock.getOnce(
           schemasAPILatestUrl,
           schemaVersion
@@ -109,15 +82,8 @@ describe('Details', () => {
         await act(() => {
           renderComponent();
         });
-        await waitFor(() => {
-          expect(schemasAPILatestMock.called()).toBeTruthy();
-        });
-        await waitFor(() => {
-          expect(schemasAPIVersionsMock.called()).toBeTruthy();
-        });
-      });
-
-      it('renders component with schema info', () => {
+        expect(schemasAPILatestMock.called()).toBeTruthy();
+        expect(schemasAPIVersionsMock.called()).toBeTruthy();
         expect(screen.getByText('Edit Schema')).toBeInTheDocument();
         expect(screen.queryByRole('progressbar')).not.toBeInTheDocument();
         expect(screen.getByRole('table')).toBeInTheDocument();
@@ -126,7 +92,7 @@ describe('Details', () => {
 
     describe('fetch success schema with non ascii characters', () => {
       describe('has schema versions', () => {
-        beforeEach(async () => {
+        it('renders component with schema info', async () => {
           const schemasAPILatestMock = fetchMock.getOnce(
             schemasAPILatestUrl,
             schemaVersionWithNonAsciiChars
@@ -138,15 +104,8 @@ describe('Details', () => {
           await act(() => {
             renderComponent();
           });
-          await waitFor(() => {
-            expect(schemasAPILatestMock.called()).toBeTruthy();
-          });
-          await waitFor(() => {
-            expect(schemasAPIVersionsMock.called()).toBeTruthy();
-          });
-        });
-
-        it('renders component with schema info', () => {
+          expect(schemasAPILatestMock.called()).toBeTruthy();
+          expect(schemasAPIVersionsMock.called()).toBeTruthy();
           expect(screen.getByText('Edit Schema')).toBeInTheDocument();
           expect(screen.queryByRole('progressbar')).not.toBeInTheDocument();
           expect(screen.getByRole('table')).toBeInTheDocument();
@@ -167,12 +126,8 @@ describe('Details', () => {
         await act(() => {
           renderComponent();
         });
-        await waitFor(() => {
-          expect(schemasAPILatestMock.called()).toBeTruthy();
-        });
-        await waitFor(() => {
-          expect(schemasAPIVersionsMock.called()).toBeTruthy();
-        });
+        expect(schemasAPILatestMock.called()).toBeTruthy();
+        expect(schemasAPIVersionsMock.called()).toBeTruthy();
       });
 
       // seems like incorrect behaviour

+ 5 - 22
kafka-ui-react-app/src/components/Schemas/Edit/__tests__/Edit.spec.tsx

@@ -7,7 +7,7 @@ import {
   schemaVersion,
   schemaVersionWithNonAsciiChars,
 } from 'redux/reducers/schemas/__test__/fixtures';
-import { screen, waitFor } from '@testing-library/dom';
+import { screen } from '@testing-library/dom';
 import ClusterContext, {
   ContextProps,
   initialValue as contextInitialValue,
@@ -42,28 +42,14 @@ const renderComponent = (
 describe('Edit', () => {
   afterEach(() => fetchMock.reset());
 
-  describe('fetch failed', () => {
-    it('renders page loader', async () => {
-      const schemasAPILatestMock = fetchMock.getOnce(schemasAPILatestUrl, 404);
-      await renderComponent();
-      await waitFor(() => expect(schemasAPILatestMock.called()).toBeTruthy());
-      expect(screen.getByRole('progressbar')).toBeInTheDocument();
-      expect(screen.queryByText(schemaVersion.subject)).not.toBeInTheDocument();
-      expect(screen.queryByText('Submit')).not.toBeInTheDocument();
-    });
-  });
-
   describe('fetch success', () => {
     describe('has schema versions', () => {
       it('renders component with schema info', async () => {
-        const schemasAPILatestMock = fetchMock.getOnce(
-          schemasAPILatestUrl,
-          schemaVersion
-        );
+        fetchMock.getOnce(schemasAPILatestUrl, schemaVersion);
         await act(() => {
           renderComponent();
         });
-        await waitFor(() => expect(schemasAPILatestMock.called()).toBeTruthy());
+        expect(fetchMock.called(schemasAPILatestUrl)).toBeTruthy();
         expect(screen.getByText('Submit')).toBeInTheDocument();
         expect(screen.queryByRole('progressbar')).not.toBeInTheDocument();
       });
@@ -73,14 +59,11 @@ describe('Edit', () => {
   describe('fetch success schema with non ascii characters', () => {
     describe('has schema versions', () => {
       it('renders component with schema info', async () => {
-        const schemasAPILatestMock = fetchMock.getOnce(
-          schemasAPILatestUrl,
-          schemaVersionWithNonAsciiChars
-        );
+        fetchMock.getOnce(schemasAPILatestUrl, schemaVersionWithNonAsciiChars);
         await act(() => {
           renderComponent();
         });
-        await waitFor(() => expect(schemasAPILatestMock.called()).toBeTruthy());
+        expect(fetchMock.called(schemasAPILatestUrl)).toBeTruthy();
         expect(screen.getByText('Submit')).toBeInTheDocument();
         expect(screen.queryByRole('progressbar')).not.toBeInTheDocument();
       });

+ 17 - 13
kafka-ui-react-app/src/components/Schemas/New/__test__/New.spec.tsx

@@ -2,7 +2,7 @@ import React from 'react';
 import New from 'components/Schemas/New/New';
 import { render, WithRoute } from 'lib/testHelpers';
 import { clusterSchemaNewPath } from 'lib/paths';
-import { screen, waitFor } from '@testing-library/react';
+import { act, screen } from '@testing-library/react';
 import userEvent from '@testing-library/user-event';
 
 const clusterName = 'local';
@@ -10,26 +10,30 @@ const subjectValue = 'subject';
 const schemaValue = 'schema';
 
 describe('New Component', () => {
-  beforeEach(() => {
-    waitFor(() => {
-      render(
-        <WithRoute path={clusterSchemaNewPath()}>
-          <New />
-        </WithRoute>,
-        {
-          initialEntries: [clusterSchemaNewPath(clusterName)],
-        }
-      );
-    });
+  const renderComponent = async () => {
+    render(
+      <WithRoute path={clusterSchemaNewPath()}>
+        <New />
+      </WithRoute>,
+      {
+        initialEntries: [clusterSchemaNewPath(clusterName)],
+      }
+    );
+  };
+
+  beforeEach(async () => {
+    await act(renderComponent);
   });
 
-  it('renders component', () => {
+  it('renders component', async () => {
     expect(screen.getByText('Create')).toBeInTheDocument();
   });
+
   it('submit button will be disabled while form fields are not filled', () => {
     const submitBtn = screen.getByRole('button', { name: /submit/i });
     expect(submitBtn).toBeDisabled();
   });
+
   it('submit button will be enabled when form fields are filled', async () => {
     const subject = screen.getByPlaceholderText('Schema Name');
     const schema = screen.getAllByRole('textbox')[1];

+ 11 - 8
kafka-ui-react-app/src/components/Topics/List/__tests__/TopicTable.spec.tsx

@@ -12,18 +12,18 @@ import {
 } from 'lib/hooks/api/topics';
 import TopicTable from 'components/Topics/List/TopicTable';
 import { clusterTopicsPath } from 'lib/paths';
+import { useAppDispatch } from 'lib/hooks/redux';
 
 const clusterName = 'test-cluster';
-const mockUnwrap = jest.fn();
-const useDispatchMock = () => jest.fn(() => ({ unwrap: mockUnwrap }));
-
-const getButtonByName = (name: string) => screen.getByRole('button', { name });
+const unwrapMock = jest.fn();
 
 jest.mock('lib/hooks/redux', () => ({
   ...jest.requireActual('lib/hooks/redux'),
-  useAppDispatch: useDispatchMock,
+  useAppDispatch: jest.fn(),
 }));
 
+const getButtonByName = (name: string) => screen.getByRole('button', { name });
+
 jest.mock('lib/hooks/api/topics', () => ({
   ...jest.requireActual('lib/hooks/api/topics'),
   useDeleteTopic: jest.fn(),
@@ -42,6 +42,9 @@ describe('TopicTable Components', () => {
     (useRecreateTopic as jest.Mock).mockImplementation(() => ({
       mutateAsync: recreateTopicMock,
     }));
+    (useAppDispatch as jest.Mock).mockImplementation(() => () => ({
+      unwrap: unwrapMock,
+    }));
   });
 
   const renderComponent = (
@@ -182,9 +185,9 @@ describe('TopicTable Components', () => {
             ).toBeInTheDocument();
             const confirmBtn = getButtonByName('Confirm');
             expect(confirmBtn).toBeInTheDocument();
-            expect(mockUnwrap).not.toHaveBeenCalled();
+            expect(unwrapMock).not.toHaveBeenCalled();
             await userEvent.click(confirmBtn);
-            expect(mockUnwrap).toHaveBeenCalledTimes(2);
+            expect(unwrapMock).toHaveBeenCalledTimes(2);
             expect(screen.getAllByRole('checkbox')[1]).not.toBeChecked();
             expect(screen.getAllByRole('checkbox')[2]).not.toBeChecked();
           });
@@ -279,7 +282,7 @@ describe('TopicTable Components', () => {
           await userEvent.click(
             screen.getByRole('button', { name: 'Confirm' })
           );
-          expect(mockUnwrap).toHaveBeenCalled();
+          expect(unwrapMock).toHaveBeenCalled();
         });
       });
 

+ 5 - 10
kafka-ui-react-app/src/components/Topics/New/__test__/New.spec.tsx

@@ -34,7 +34,6 @@ const renderComponent = (path: string) => {
     { initialEntries: [path] }
   );
 };
-
 const createTopicMock = jest.fn();
 describe('New', () => {
   beforeEach(() => {
@@ -42,9 +41,6 @@ describe('New', () => {
       createResource: createTopicMock,
     }));
   });
-  afterEach(() => {
-    mockNavigate.mockClear();
-  });
   it('checks header for create new', async () => {
     await act(() => {
       renderComponent(clusterTopicNewPath(clusterName));
@@ -52,19 +48,20 @@ describe('New', () => {
     expect(screen.getByRole('heading', { name: 'Create' })).toBeInTheDocument();
   });
 
-  it('checks header for copy', () => {
-    renderComponent(`${clusterTopicCopyPath(clusterName)}?name=test`);
+  it('checks header for copy', async () => {
+    await act(() => {
+      renderComponent(`${clusterTopicCopyPath(clusterName)}?name=test`);
+    });
     expect(screen.getByRole('heading', { name: 'Copy' })).toBeInTheDocument();
   });
   it('validates form', async () => {
-    await renderComponent(clusterTopicNewPath(clusterName));
+    renderComponent(clusterTopicNewPath(clusterName));
     await userEvent.type(screen.getByPlaceholderText('Topic Name'), topicName);
     await userEvent.clear(screen.getByPlaceholderText('Topic Name'));
     await userEvent.tab();
     await expect(
       screen.getByText('name is a required field')
     ).toBeInTheDocument();
-
     await userEvent.type(
       screen.getByLabelText('Number of partitions *'),
       minValue
@@ -78,7 +75,6 @@ describe('New', () => {
     expect(createTopicMock).not.toHaveBeenCalled();
     expect(mockNavigate).not.toHaveBeenCalled();
   });
-
   it('validates form invalid name', async () => {
     renderComponent(clusterTopicNewPath(clusterName));
     await userEvent.type(
@@ -89,7 +85,6 @@ describe('New', () => {
       screen.getByText('Only alphanumeric, _, -, and . allowed')
     ).toBeInTheDocument();
   });
-
   it('submits valid form', async () => {
     renderComponent(clusterTopicNewPath(clusterName));
     await userEvent.type(screen.getByPlaceholderText('Topic Name'), topicName);

+ 9 - 0
kafka-ui-react-app/src/components/Topics/Topic/Messages/__test__/Messages.spec.tsx

@@ -10,11 +10,17 @@ import userEvent from '@testing-library/user-event';
 import { clusterTopicMessagesPath } from 'lib/paths';
 import { useSerdes } from 'lib/hooks/api/topicMessages';
 import { serdesPayload } from 'lib/fixtures/topicMessages';
+import { useTopicDetails } from 'lib/hooks/api/topics';
+import { externalTopicPayload } from 'lib/fixtures/topics';
 
 jest.mock('lib/hooks/api/topicMessages', () => ({
   useSerdes: jest.fn(),
 }));
 
+jest.mock('lib/hooks/api/topics', () => ({
+  useTopicDetails: jest.fn(),
+}));
+
 describe('Messages', () => {
   const searchParams = `?filterQueryType=STRING_CONTAINS&attempt=0&limit=100&seekDirection=${SeekDirection.FORWARD}&seekType=${SeekType.OFFSET}&seekTo=0::9`;
   const renderComponent = (param: string = searchParams) => {
@@ -37,6 +43,9 @@ describe('Messages', () => {
     (useSerdes as jest.Mock).mockImplementation(() => ({
       data: serdesPayload,
     }));
+    (useTopicDetails as jest.Mock).mockImplementation(() => ({
+      data: externalTopicPayload,
+    }));
   });
   describe('component rendering default behavior with the search params', () => {
     beforeEach(() => {

+ 19 - 9
kafka-ui-react-app/src/components/Topics/Topic/Messages/__test__/MessagesTable.spec.tsx

@@ -21,16 +21,21 @@ jest.mock('react-router-dom', () => ({
 }));
 
 describe('MessagesTable', () => {
-  const seekToResult = '&seekTo=0::9';
-  const searchParamsValue = `?filterQueryType=STRING_CONTAINS&attempt=0&limit=100&seekDirection=${SeekDirection.FORWARD}&seekType=${SeekType.OFFSET}${seekToResult}`;
-  const searchParams = new URLSearchParams(searchParamsValue);
+  const searchParams = new URLSearchParams({
+    filterQueryType: 'STRING_CONTAINS',
+    attempt: '0',
+    limit: '100',
+    seekDirection: SeekDirection.FORWARD,
+    seekType: SeekType.OFFSET,
+    seekTo: '0::9',
+  });
   const contextValue: ContextProps = {
     isLive: false,
     seekDirection: SeekDirection.FORWARD,
     changeSeekDirection: jest.fn(),
   };
 
-  const setUpComponent = (
+  const renderComponent = (
     params: URLSearchParams = searchParams,
     ctx: ContextProps = contextValue,
     messages: TopicMessage[] = [],
@@ -43,7 +48,7 @@ describe('MessagesTable', () => {
         <MessagesTable />
       </TopicMessagesContext.Provider>,
       {
-        initialEntries: [customPath],
+        initialEntries: [`/messages?${customPath}`],
         preloadedState: {
           topicMessages: {
             messages,
@@ -59,7 +64,7 @@ describe('MessagesTable', () => {
 
   describe('Default props Setup for MessagesTable component', () => {
     beforeEach(() => {
-      setUpComponent();
+      renderComponent();
     });
 
     it('should check the render', () => {
@@ -86,20 +91,25 @@ describe('MessagesTable', () => {
 
   describe('Custom Setup with different props value', () => {
     it('should check if next button and previous is disabled isLive Param', () => {
-      setUpComponent(searchParams, { ...contextValue, isLive: true });
+      renderComponent(searchParams, { ...contextValue, isLive: true });
       expect(screen.queryByText(/next/i)).toBeDisabled();
       expect(screen.queryByText(/back/i)).toBeDisabled();
     });
 
     it('should check the display of the loader element', () => {
-      setUpComponent(searchParams, { ...contextValue, isLive: true }, [], true);
+      renderComponent(
+        searchParams,
+        { ...contextValue, isLive: true },
+        [],
+        true
+      );
       expect(screen.getByRole('progressbar')).toBeInTheDocument();
     });
   });
 
   describe('should render Messages table with data', () => {
     beforeEach(() => {
-      setUpComponent(searchParams, { ...contextValue }, mockTopicsMessages);
+      renderComponent(searchParams, { ...contextValue }, mockTopicsMessages);
     });
 
     it('should check the rendering of the messages', () => {

+ 1 - 1
kafka-ui-react-app/src/components/Topics/Topic/Overview/Overview.tsx

@@ -1,5 +1,5 @@
 import React from 'react';
-import { Partition, Replica } from 'generated-sources';
+import type { Partition, Replica } from 'generated-sources';
 import BytesFormatted from 'components/common/BytesFormatted/BytesFormatted';
 import Table from 'components/common/NewTable';
 import * as Metrics from 'components/common/Metrics';

+ 10 - 4
kafka-ui-react-app/src/components/Topics/Topic/Overview/__test__/Overview.spec.tsx

@@ -9,6 +9,7 @@ import userEvent from '@testing-library/user-event';
 import { clusterTopicPath } from 'lib/paths';
 import { Replica } from 'components/Topics/Topic/Overview/Overview.styled';
 import { useTopicDetails } from 'lib/hooks/api/topics';
+import { useAppDispatch } from 'lib/hooks/redux';
 import {
   externalTopicPayload,
   internalTopicPayload,
@@ -27,12 +28,11 @@ jest.mock('lib/hooks/api/topics', () => ({
   useTopicDetails: jest.fn(),
 }));
 
-const uwrapMock = jest.fn();
-const useDispatchMock = () => jest.fn(() => ({ unwrap: uwrapMock }));
+const unwrapMock = jest.fn();
 
 jest.mock('lib/hooks/redux', () => ({
   ...jest.requireActual('lib/hooks/redux'),
-  useAppDispatch: useDispatchMock,
+  useAppDispatch: jest.fn(),
 }));
 
 describe('Overview', () => {
@@ -54,6 +54,12 @@ describe('Overview', () => {
     );
   };
 
+  beforeEach(() => {
+    (useAppDispatch as jest.Mock).mockImplementation(() => () => ({
+      unwrap: unwrapMock,
+    }));
+  });
+
   it('at least one replica was rendered', () => {
     renderComponent();
     expect(screen.getByLabelText('replica-info')).toBeInTheDocument();
@@ -117,7 +123,7 @@ describe('Overview', () => {
 
       const clearMessagesButton = screen.getByText('Clear Messages');
       await userEvent.click(clearMessagesButton);
-      expect(uwrapMock).toHaveBeenCalledTimes(1);
+      expect(unwrapMock).toHaveBeenCalledTimes(1);
     });
   });
 

+ 7 - 4
kafka-ui-react-app/src/components/Topics/Topic/__test__/Topic.spec.tsx

@@ -20,6 +20,7 @@ import {
   useRecreateTopic,
   useTopicDetails,
 } from 'lib/hooks/api/topics';
+import { useAppDispatch } from 'lib/hooks/redux';
 
 const mockNavigate = jest.fn();
 jest.mock('react-router-dom', () => ({
@@ -32,12 +33,11 @@ jest.mock('lib/hooks/api/topics', () => ({
   useRecreateTopic: jest.fn(),
 }));
 
-const mockUnwrap = jest.fn();
-const useDispatchMock = () => jest.fn(() => ({ unwrap: mockUnwrap }));
+const unwrapMock = jest.fn();
 
 jest.mock('lib/hooks/redux', () => ({
   ...jest.requireActual('lib/hooks/redux'),
-  useAppDispatch: useDispatchMock,
+  useAppDispatch: jest.fn(),
 }));
 
 jest.mock('components/Topics/Topic/Overview/Overview', () => () => (
@@ -98,6 +98,9 @@ describe('Details', () => {
     (useRecreateTopic as jest.Mock).mockImplementation(() => ({
       mutateAsync: mockRecreate,
     }));
+    (useAppDispatch as jest.Mock).mockImplementation(() => () => ({
+      unwrap: unwrapMock,
+    }));
   });
   describe('Action Bar', () => {
     describe('when it has readonly flag', () => {
@@ -142,7 +145,7 @@ describe('Details', () => {
           name: 'Confirm',
         })[0];
         await waitFor(() => userEvent.click(submitButton));
-        expect(mockUnwrap).toHaveBeenCalledTimes(1);
+        expect(unwrapMock).toHaveBeenCalledTimes(1);
       });
 
       it('closes the modal when cancel button is clicked', async () => {

+ 4 - 2
kafka-ui-react-app/src/components/common/NewTable/Table.tsx

@@ -5,12 +5,14 @@ import {
   getExpandedRowModel,
   getSortedRowModel,
   useReactTable,
-  ColumnDef,
+  getPaginationRowModel,
+} from '@tanstack/react-table';
+import type {
   Row,
   SortingState,
   OnChangeFn,
   PaginationState,
-  getPaginationRowModel,
+  ColumnDef,
 } from '@tanstack/react-table';
 import { useSearchParams } from 'react-router-dom';
 import { PER_PAGE } from 'lib/constants';

+ 0 - 0
kafka-ui-react-app/src/components/global.css.ts → kafka-ui-react-app/src/components/globalCss.ts


+ 1 - 2
kafka-ui-react-app/vite.config.ts

@@ -4,7 +4,7 @@ import {
   UserConfigExport,
   splitVendorChunkPlugin,
 } from 'vite';
-import react from '@vitejs/plugin-react';
+import react from '@vitejs/plugin-react-swc';
 import tsconfigPaths from 'vite-tsconfig-paths';
 
 export default defineConfig(({ mode }) => {
@@ -25,7 +25,6 @@ export default defineConfig(({ mode }) => {
     },
   };
   const proxy = process.env.VITE_DEV_PROXY;
-
   if (mode === 'development' && proxy) {
     return {
       ...defaultConfig,

Some files were not shown because too many files changed in this diff