This is an automated email from the ASF dual-hosted git repository.
lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git
The following commit(s) were added to refs/heads/rocketmq-studio by this push:
new 2002d3d6 fix: normalize service search filters (#635)
2002d3d6 is described below
commit 2002d3d6683f8f5fc567193cdae465cab07bf805
Author: aias00 <[email protected]>
AuthorDate: Tue Jul 28 07:10:24 2026 -0700
fix: normalize service search filters (#635)
* [Studio] Normalize service search filters
* fix: make group search case insensitive
---
.../studio/cluster/client/ClientService.java | 6 +-
.../cluster/client/ProducerConnectionService.java | 8 ++-
.../rocketmq/studio/instance/InstanceService.java | 9 +--
.../instance/group/ConsumerDiagnosticsService.java | 15 ++--
.../studio/instance/topic/MetadataService.java | 11 ++-
.../studio/ops/audit/InMemoryAuditRepository.java | 20 ++++--
.../studio/cluster/client/ClientServiceTest.java | 63 ++++++++++++++++
.../client/ProducerConnectionServiceTest.java | 19 +++++
.../studio/instance/InstanceServiceTest.java | 26 +++++++
.../group/ConsumerDiagnosticsServiceTest.java | 18 +++++
.../studio/instance/topic/MetadataServiceTest.java | 34 +++++++++
.../ops/audit/InMemoryAuditRepositoryTest.java | 83 ++++++++++++++++++++++
web/src/pages/studio/GroupManagement.tsx | 7 +-
.../studio/__tests__/GroupManagement.test.tsx | 2 +-
14 files changed, 301 insertions(+), 20 deletions(-)
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ClientService.java
b/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ClientService.java
index 60469a0d..7f39325a 100644
---
a/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ClientService.java
+++
b/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ClientService.java
@@ -31,6 +31,10 @@ public class ClientService {
public List<ClientConnectionVO> listConnections(String clusterId, String
type) {
log.info("Listing client connections, clusterId={}, type={}",
clusterId, type);
- return clientProvider.findConnections(clusterId, type);
+ return clientProvider.findConnections(normalizeFilter(clusterId),
normalizeFilter(type));
+ }
+
+ private String normalizeFilter(String value) {
+ return value == null || value.isBlank() ? null : value.trim();
}
}
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionService.java
b/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionService.java
index 9709db00..bce19e91 100644
---
a/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionService.java
+++
b/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionService.java
@@ -32,8 +32,10 @@ public class ProducerConnectionService {
public List<ProducerConnectionVO> listConnections(String topic, String
producerGroup) {
log.info("Listing producer connections, topic={}, producerGroup={}",
topic, producerGroup);
+ String normalizedTopic = normalizeFilter(topic);
+ String normalizedProducerGroup = normalizeFilter(producerGroup);
return clientService.listConnections(null,
ClientType.Producer.name()).stream()
- .filter(connection -> matchesFilter(connection, topic,
producerGroup))
+ .filter(connection -> matchesFilter(connection,
normalizedTopic, normalizedProducerGroup))
.map(this::toProducerConnection)
.toList();
}
@@ -60,4 +62,8 @@ public class ProducerConnectionService {
private boolean hasText(String value) {
return value != null && !value.trim().isEmpty();
}
+
+ private String normalizeFilter(String value) {
+ return hasText(value) ? value.trim() : null;
+ }
}
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/instance/InstanceService.java
b/server/src/main/java/org/apache/rocketmq/studio/instance/InstanceService.java
index f9abb650..eb4c5aec 100644
---
a/server/src/main/java/org/apache/rocketmq/studio/instance/InstanceService.java
+++
b/server/src/main/java/org/apache/rocketmq/studio/instance/InstanceService.java
@@ -36,13 +36,14 @@ public class InstanceService {
public List<InstanceVO> listInstances(InstanceType type, String search) {
log.debug("Listing instances, type={}, search={}", type, search);
+ String normalizedSearch = search == null || search.isBlank() ? null :
search.trim();
- if (type != null && search != null && !search.isBlank()) {
- return instanceRepository.findByTypeAndSearch(type, search);
+ if (type != null && normalizedSearch != null) {
+ return instanceRepository.findByTypeAndSearch(type,
normalizedSearch);
} else if (type != null) {
return instanceRepository.findByType(type);
- } else if (search != null && !search.isBlank()) {
- return instanceRepository.search(search);
+ } else if (normalizedSearch != null) {
+ return instanceRepository.search(normalizedSearch);
}
return instanceRepository.findAll();
}
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsService.java
b/server/src/main/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsService.java
index 4c4def1f..87e8f1db 100644
---
a/server/src/main/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsService.java
+++
b/server/src/main/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsService.java
@@ -30,12 +30,15 @@ public class ConsumerDiagnosticsService {
private final ConsumerDiagnosticsProvider diagnosticsProvider;
public ConsumerStackTraceVO getConsumerStack(String groupName, String
clientId) {
- if (!StringUtils.hasText(groupName)) {
- throw new BusinessException(HttpStatus.BAD_REQUEST.value(),
"groupName is required");
- }
- if (!StringUtils.hasText(clientId)) {
- throw new BusinessException(HttpStatus.BAD_REQUEST.value(),
"clientId is required");
+ String normalizedGroupName = normalizeRequired(groupName, "groupName");
+ String normalizedClientId = normalizeRequired(clientId, "clientId");
+ return diagnosticsProvider.getConsumerStack(normalizedGroupName,
normalizedClientId);
+ }
+
+ private String normalizeRequired(String value, String fieldName) {
+ if (!StringUtils.hasText(value)) {
+ throw new BusinessException(HttpStatus.BAD_REQUEST.value(),
fieldName + " is required");
}
- return diagnosticsProvider.getConsumerStack(groupName, clientId);
+ return value.trim();
}
}
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/instance/topic/MetadataService.java
b/server/src/main/java/org/apache/rocketmq/studio/instance/topic/MetadataService.java
index 33f53642..f2c4e541 100644
---
a/server/src/main/java/org/apache/rocketmq/studio/instance/topic/MetadataService.java
+++
b/server/src/main/java/org/apache/rocketmq/studio/instance/topic/MetadataService.java
@@ -38,7 +38,10 @@ public class MetadataService {
public List<TopicVO> listTopics(String clusterId, String type, String
search) {
- return metadataProvider.listTopics(clusterId, type, search);
+ return metadataProvider.listTopics(
+ normalizeFilter(clusterId),
+ normalizeFilter(type),
+ normalizeFilter(search));
}
@@ -75,7 +78,7 @@ public class MetadataService {
public List<ConsumerGroupVO> listConsumerGroups(String clusterId, String
search) {
- return metadataProvider.listConsumerGroups(clusterId, search);
+ return metadataProvider.listConsumerGroups(normalizeFilter(clusterId),
normalizeFilter(search));
}
@@ -114,4 +117,8 @@ public class MetadataService {
public List<NamespaceVO> listNamespaces() {
throw new UnsupportedOperationException("Not implemented");
}
+
+ private String normalizeFilter(String value) {
+ return value == null || value.isBlank() ? null : value.trim();
+ }
}
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/ops/audit/InMemoryAuditRepository.java
b/server/src/main/java/org/apache/rocketmq/studio/ops/audit/InMemoryAuditRepository.java
index 37b430c9..02740375 100644
---
a/server/src/main/java/org/apache/rocketmq/studio/ops/audit/InMemoryAuditRepository.java
+++
b/server/src/main/java/org/apache/rocketmq/studio/ops/audit/InMemoryAuditRepository.java
@@ -35,11 +35,12 @@ public class InMemoryAuditRepository implements
AuditRepository {
public List<AuditRecordVO> findAll(String search, String operationType,
LocalDateTime startDate, LocalDateTime
endDate,
String result) {
+ String normalizedSearch = normalize(search);
return records.values().stream()
- .filter(r -> search == null || search.isEmpty()
- ||
r.getDetail().toLowerCase().contains(search.toLowerCase())
- ||
r.getOperator().toLowerCase().contains(search.toLowerCase())
- ||
r.getTarget().toLowerCase().contains(search.toLowerCase()))
+ .filter(r -> normalizedSearch == null
+ || containsIgnoreCase(r.getDetail(), normalizedSearch)
+ || containsIgnoreCase(r.getOperator(),
normalizedSearch)
+ || containsIgnoreCase(r.getTarget(), normalizedSearch))
.filter(r -> operationType == null || operationType.isEmpty()
|| operationType.equals(r.getOperationType()))
.filter(r -> startDate == null || r.getTimestamp() != null &&
!r.getTimestamp().isBefore(startDate))
@@ -54,6 +55,17 @@ public class InMemoryAuditRepository implements
AuditRepository {
.collect(Collectors.toList());
}
+ private String normalize(String value) {
+ if (value == null || value.isBlank()) {
+ return null;
+ }
+ return value.toLowerCase();
+ }
+
+ private boolean containsIgnoreCase(String value, String normalizedSearch) {
+ return value != null && value.toLowerCase().contains(normalizedSearch);
+ }
+
@Override
public int deleteBefore(LocalDateTime cutoff) {
List<String> toRemove = records.values().stream()
diff --git
a/server/src/test/java/org/apache/rocketmq/studio/cluster/client/ClientServiceTest.java
b/server/src/test/java/org/apache/rocketmq/studio/cluster/client/ClientServiceTest.java
new file mode 100644
index 00000000..6825cbf1
--- /dev/null
+++
b/server/src/test/java/org/apache/rocketmq/studio/cluster/client/ClientServiceTest.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.cluster.client;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class ClientServiceTest {
+
+ @Mock
+ private ClientProvider clientProvider;
+
+ @InjectMocks
+ private ClientService clientService;
+
+ @Test
+ void listConnectionsShouldTrimFiltersBeforeQueryingProvider() {
+ ClientConnectionVO connection = ClientConnectionVO.builder()
+ .clientId("client-1")
+ .clusterName("production-cluster")
+ .build();
+ when(clientProvider.findConnections("production-cluster",
"Producer")).thenReturn(List.of(connection));
+
+ List<ClientConnectionVO> result = clientService.listConnections("
production-cluster ", " Producer ");
+
+ assertThat(result).containsExactly(connection);
+ verify(clientProvider).findConnections("production-cluster",
"Producer");
+ }
+
+ @Test
+ void listConnectionsShouldTreatBlankFiltersAsUnspecified() {
+ when(clientProvider.findConnections(null, null)).thenReturn(List.of());
+
+ List<ClientConnectionVO> result = clientService.listConnections(" ",
"\t");
+
+ assertThat(result).isEmpty();
+ verify(clientProvider).findConnections(null, null);
+ }
+}
diff --git
a/server/src/test/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionServiceTest.java
b/server/src/test/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionServiceTest.java
index 5bce6134..489f43cc 100644
---
a/server/src/test/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionServiceTest.java
+++
b/server/src/test/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionServiceTest.java
@@ -91,6 +91,25 @@ class ProducerConnectionServiceTest {
assertThat(result.get(0).getClientId()).isEqualTo("producer-1");
}
+ @Test
+ void listConnectionsShouldTrimFilterValues() {
+ ClientConnectionVO producer = ClientConnectionVO.builder()
+ .clientId("producer-1")
+ .type(ClientType.Producer)
+ .groupOrTopic("order-topic")
+ .producerGroup("pg-order")
+ .address("10.0.0.1:38888")
+ .language(ClientLanguage.Java)
+ .version("5.1.0")
+ .build();
+ when(clientService.listConnections(null,
ClientType.Producer.name())).thenReturn(List.of(producer));
+
+ List<ProducerConnectionVO> result =
producerConnectionService.listConnections(" order-topic ", " pg-order ");
+
+ assertThat(result).hasSize(1);
+ assertThat(result.get(0).getClientId()).isEqualTo("producer-1");
+ }
+
@Test
void listConnectionsShouldRequireProducerGroupWhenBothFiltersAreProvided()
{
ClientConnectionVO producer = ClientConnectionVO.builder()
diff --git
a/server/src/test/java/org/apache/rocketmq/studio/instance/InstanceServiceTest.java
b/server/src/test/java/org/apache/rocketmq/studio/instance/InstanceServiceTest.java
index 9fab45f6..c59644fd 100644
---
a/server/src/test/java/org/apache/rocketmq/studio/instance/InstanceServiceTest.java
+++
b/server/src/test/java/org/apache/rocketmq/studio/instance/InstanceServiceTest.java
@@ -83,6 +83,19 @@ class InstanceServiceTest {
verify(instanceRepository).search("prod");
}
+ @Test
+ void listInstancesShouldTrimSearchKeyword() {
+ List<InstanceVO> instances = List.of(
+ InstanceVO.builder().name("production").build()
+ );
+ when(instanceRepository.search("prod")).thenReturn(instances);
+
+ List<InstanceVO> result = instanceService.listInstances(null, " prod
");
+
+ assertThat(result).hasSize(1);
+ verify(instanceRepository).search("prod");
+ }
+
@Test
void listInstancesShouldFilterByTypeAndSearch() {
List<InstanceVO> instances = List.of(
@@ -96,6 +109,19 @@ class InstanceServiceTest {
verify(instanceRepository).findByTypeAndSearch(InstanceType.PROXY,
"prod");
}
+ @Test
+ void listInstancesShouldTrimSearchKeywordWhenFilteringByType() {
+ List<InstanceVO> instances = List.of(
+
InstanceVO.builder().name("production-proxy").type(InstanceType.PROXY).build()
+ );
+ when(instanceRepository.findByTypeAndSearch(InstanceType.PROXY,
"prod")).thenReturn(instances);
+
+ List<InstanceVO> result =
instanceService.listInstances(InstanceType.PROXY, " prod ");
+
+ assertThat(result).hasSize(1);
+ verify(instanceRepository).findByTypeAndSearch(InstanceType.PROXY,
"prod");
+ }
+
@Test
void listInstancesShouldIgnoreBlankSearch() {
List<InstanceVO> instances =
List.of(InstanceVO.builder().name("inst").build());
diff --git
a/server/src/test/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsServiceTest.java
b/server/src/test/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsServiceTest.java
index 034c1acd..6867871b 100644
---
a/server/src/test/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsServiceTest.java
+++
b/server/src/test/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsServiceTest.java
@@ -60,6 +60,24 @@ class ConsumerDiagnosticsServiceTest {
verify(diagnosticsProvider).getConsumerStack("cg-orders", "client-1");
}
+ @Test
+ void getConsumerStackShouldTrimInputsBeforeDelegatingToProvider() {
+ ConsumerStackTraceVO stackTrace = ConsumerStackTraceVO.builder()
+ .groupName("cg-orders")
+ .clientId("client-1")
+ .capturedAt(LocalDateTime.now())
+ .threadCount(0)
+ .threads(List.of())
+ .build();
+ when(diagnosticsProvider.getConsumerStack("cg-orders",
"client-1")).thenReturn(stackTrace);
+
+ ConsumerStackTraceVO result = diagnosticsService.getConsumerStack("
cg-orders ", " client-1 ");
+
+ assertThat(result.getGroupName()).isEqualTo("cg-orders");
+ assertThat(result.getClientId()).isEqualTo("client-1");
+ verify(diagnosticsProvider).getConsumerStack("cg-orders", "client-1");
+ }
+
@Test
void getConsumerStackShouldRejectBlankGroupName() {
assertThatThrownBy(() -> diagnosticsService.getConsumerStack(" ",
"client-1"))
diff --git
a/server/src/test/java/org/apache/rocketmq/studio/instance/topic/MetadataServiceTest.java
b/server/src/test/java/org/apache/rocketmq/studio/instance/topic/MetadataServiceTest.java
index 21d30799..554335b7 100644
---
a/server/src/test/java/org/apache/rocketmq/studio/instance/topic/MetadataServiceTest.java
+++
b/server/src/test/java/org/apache/rocketmq/studio/instance/topic/MetadataServiceTest.java
@@ -68,6 +68,28 @@ class MetadataServiceTest {
assertThat(result).isEmpty();
}
+ @Test
+ void listTopicsShouldNormalizeFiltersBeforeQueryingProvider() {
+ TopicVO topic = new TopicVO();
+ topic.setName("order-topic");
+ when(metadataProvider.listTopics("cluster-1", "FIFO",
"order")).thenReturn(List.of(topic));
+
+ List<TopicVO> result = metadataService.listTopics(" cluster-1 ", "
FIFO ", " order ");
+
+ assertThat(result).containsExactly(topic);
+ verify(metadataProvider).listTopics("cluster-1", "FIFO", "order");
+ }
+
+ @Test
+ void listTopicsShouldTreatBlankFiltersAsUnspecified() {
+ when(metadataProvider.listTopics(null, null,
null)).thenReturn(List.of());
+
+ List<TopicVO> result = metadataService.listTopics(" ", "\t", "");
+
+ assertThat(result).isEmpty();
+ verify(metadataProvider).listTopics(null, null, null);
+ }
+
@Test
void createTopicShouldDelegateToAdminClient() {
TopicVO input = new TopicVO();
@@ -141,4 +163,16 @@ class MetadataServiceTest {
assertThat(result).isEmpty();
verify(metadataProvider).listConsumerGroups(null, "order");
}
+
+ @Test
+ void listConsumerGroupsShouldNormalizeFiltersBeforeQueryingProvider() {
+ ConsumerGroupVO group = new ConsumerGroupVO();
+ group.setName("cg-order");
+ when(metadataProvider.listConsumerGroups("cluster-1",
"order")).thenReturn(List.of(group));
+
+ List<ConsumerGroupVO> result = metadataService.listConsumerGroups("
cluster-1 ", " order ");
+
+ assertThat(result).containsExactly(group);
+ verify(metadataProvider).listConsumerGroups("cluster-1", "order");
+ }
}
diff --git
a/server/src/test/java/org/apache/rocketmq/studio/ops/audit/InMemoryAuditRepositoryTest.java
b/server/src/test/java/org/apache/rocketmq/studio/ops/audit/InMemoryAuditRepositoryTest.java
new file mode 100644
index 00000000..25516302
--- /dev/null
+++
b/server/src/test/java/org/apache/rocketmq/studio/ops/audit/InMemoryAuditRepositoryTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.ops.audit;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import java.time.LocalDateTime;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class InMemoryAuditRepositoryTest {
+
+ private final InMemoryAuditRepository repository = new
InMemoryAuditRepository();
+
+ @Test
+ void findAllShouldSearchAcrossNullableFields() {
+ AuditRecordVO missingTextFields = AuditRecordVO.builder()
+ .timestamp(LocalDateTime.now())
+ .operationType("CREATE")
+ .result("SUCCESS")
+ .build();
+ missingTextFields.setId("record-null-fields");
+ AuditRecordVO targetMatch = AuditRecordVO.builder()
+ .timestamp(LocalDateTime.now().minusMinutes(1))
+ .operator("admin")
+ .operationType("UPDATE")
+ .target("Topic-Order")
+ .detail(null)
+ .result("SUCCESS")
+ .build();
+ targetMatch.setId("record-target-match");
+
+ putRecords(missingTextFields, targetMatch);
+
+ assertThat(repository.findAll("order", null, null, null, null))
+ .extracting(AuditRecordVO::getId)
+ .containsExactly("record-target-match");
+ }
+
+ @Test
+ void findAllShouldTreatBlankSearchAsNoSearchFilter() {
+ AuditRecordVO record = AuditRecordVO.builder()
+ .timestamp(LocalDateTime.now())
+ .operationType("DELETE")
+ .result("FAILURE")
+ .build();
+ record.setId("record-blank-search");
+
+ putRecords(record);
+
+ assertThat(repository.findAll(" ", null, null, null, null))
+ .extracting(AuditRecordVO::getId)
+ .containsExactly("record-blank-search");
+ }
+
+ @SafeVarargs
+ @SuppressWarnings("unchecked")
+ private final void putRecords(AuditRecordVO... records) {
+ Map<String, AuditRecordVO> store =
+ (Map<String, AuditRecordVO>)
ReflectionTestUtils.getField(repository, "records");
+ assertThat(store).isNotNull();
+ store.clear();
+ for (AuditRecordVO record : records) {
+ store.put(record.getId(), record);
+ }
+ }
+}
diff --git a/web/src/pages/studio/GroupManagement.tsx
b/web/src/pages/studio/GroupManagement.tsx
index 4c4976af..47102e16 100644
--- a/web/src/pages/studio/GroupManagement.tsx
+++ b/web/src/pages/studio/GroupManagement.tsx
@@ -227,6 +227,11 @@ const GroupManagementPage = () => {
setModalVisible(true);
};
+ const normalizedSearchText = searchText.trim().toLowerCase();
+ const filteredGroupData = groupData.filter(
+ (record) => !normalizedSearchText ||
record.group.toLowerCase().includes(normalizedSearchText),
+ );
+
const columns = [
{
title: t('groupMgmt.groupName'),
@@ -390,7 +395,7 @@ const GroupManagementPage = () => {
<Card bordered={false} style={{ borderRadius: 8, boxShadow: '0 1px 6px
rgba(0,0,0,0.04)' }}>
<Table
columns={columns}
- dataSource={groupData.filter((d) => !searchText ||
d.group.includes(searchText))}
+ dataSource={filteredGroupData}
pagination={{
pageSize: 10,
showTotal: (total) => `${t('common.total')} ${total} Group`,
diff --git a/web/src/pages/studio/__tests__/GroupManagement.test.tsx
b/web/src/pages/studio/__tests__/GroupManagement.test.tsx
index 3ac9fbbe..3b93a966 100644
--- a/web/src/pages/studio/__tests__/GroupManagement.test.tsx
+++ b/web/src/pages/studio/__tests__/GroupManagement.test.tsx
@@ -90,7 +90,7 @@ describe('GroupManagement Page', () => {
const user = userEvent.setup();
renderWithProviders(<GroupManagement />);
const searchInput = screen.getByPlaceholderText('搜索消费组');
- await user.type(searchInput, 'order');
+ await user.type(searchInput, 'ORDER');
expect(screen.getByText('order-consumer-group')).toBeInTheDocument();
expect(screen.queryByText('payment-consumer-group')).not.toBeInTheDocument();
});