From f0804add5af026433563ec2c2b08a992fdcab0d0 Mon Sep 17 00:00:00 2001 From: Dave Shoup Date: Tue, 27 Jan 2026 19:26:59 -0500 Subject: [PATCH 01/12] add command function for refreshing consumer group container --- src/commands/consumerGroups.ts | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/commands/consumerGroups.ts diff --git a/src/commands/consumerGroups.ts b/src/commands/consumerGroups.ts new file mode 100644 index 000000000..a16e6104a --- /dev/null +++ b/src/commands/consumerGroups.ts @@ -0,0 +1,33 @@ +import type { Disposable } from "vscode"; +import { registerCommandWithLogging } from "."; +import { Logger } from "../logging"; +import type { ConsumerGroupContainer } from "../models/consumerGroup"; +import { TopicViewProvider } from "../viewProviders/topics"; + +const logger = new Logger("commands.consumerGroups"); + +/** + * Refresh the consumer groups container in the Topics view. + * @param container The ConsumerGroupContainer tree item that was clicked. + */ +async function refreshConsumerGroupsContainer(container: ConsumerGroupContainer): Promise { + if (!container) { + logger.error("No container provided to refreshConsumerGroupsContainer"); + return; + } + + const provider = TopicViewProvider.getInstance(); + const cluster = provider.kafkaCluster; + if (!cluster) { + logger.error("No Kafka cluster selected when attempting to refresh consumer groups container."); + return; + } + + await provider.refreshConsumerGroups(cluster, true); +} + +export function registerConsumerGroupCommands(): Disposable[] { + return [ + registerCommandWithLogging("confluent.consumerGroups.refresh", refreshConsumerGroupsContainer), + ]; +} From 6b1c616c4504d46c99e89c4da2770b3ad4a99fec Mon Sep 17 00:00:00 2001 From: Dave Shoup Date: Tue, 27 Jan 2026 19:29:35 -0500 Subject: [PATCH 02/12] update models for copy commands --- src/models/consumerGroup.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/models/consumerGroup.ts b/src/models/consumerGroup.ts index 492af9e5e..1be31ea63 100644 --- a/src/models/consumerGroup.ts +++ b/src/models/consumerGroup.ts @@ -79,7 +79,8 @@ export class ConsumerGroup implements IResourceBase, ISearchable, IdItem { } get id(): string { - return `${this.clusterId}-${this.consumerGroupId}`; + // this can't include the cluster ID since this will be used in Copy commands + return this.consumerGroupId; } get hasMembers(): boolean { @@ -147,7 +148,8 @@ export class Consumer implements IResourceBase, ISearchable, IdItem { } get id(): string { - return `${this.clusterId}-${this.consumerGroupId}-${this.consumerId}`; + // this can't include the cluster ID since this will be used in Copy commands + return this.consumerId; } searchableText(): string { @@ -169,7 +171,7 @@ export class ConsumerGroupTreeItem extends vscode.TreeItem { constructor(resource: ConsumerGroup) { super(resource.consumerGroupId); - this.id = resource.id; + this.id = `${resource.clusterId}-${resource.consumerGroupId}`; this.resource = resource; // includes state for conditional menu visibility, like: // "ccloud-consumer-group-STABLE" or "local-consumer-group-EMPTY" @@ -231,7 +233,7 @@ export class ConsumerTreeItem extends vscode.TreeItem { : resource.consumerId; super(label); - this.id = resource.id; + this.id = `${resource.clusterId}-${resource.consumerGroupId}`; this.resource = resource; this.contextValue = `${resource.connectionType.toLowerCase()}-consumer-group-member`; From e222aa5995479987a4c1d843f237db07f552b064 Mon Sep 17 00:00:00 2001 From: Dave Shoup Date: Tue, 27 Jan 2026 19:29:53 -0500 Subject: [PATCH 03/12] add consumer group commands to activation --- src/extension.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/extension.ts b/src/extension.ts index 6a33b0e20..ce3d38998 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -23,6 +23,7 @@ import { registerChatTools } from "./chat/tools/registration"; import { FlinkSqlCodelensProvider } from "./codelens/flinkSqlProvider"; import { registerCommandWithLogging } from "./commands"; import { registerConnectionCommands } from "./commands/connections"; +import { registerConsumerGroupCommands } from "./commands/consumerGroups"; import { registerDebugCommands } from "./commands/debugtools"; import { registerDiffCommands } from "./commands/diffs"; import { registerDockerCommands } from "./commands/docker"; @@ -263,6 +264,7 @@ async function _activateExtension( ...registerSchemaRegistryCommands(), ...registerSchemaCommands(), ...registerTopicCommands(), + ...registerConsumerGroupCommands(), ...registerDiffCommands(), ...registerExtraCommands(), ...registerDockerCommands(), From e9630823336e4a4970e3dde2c10fbc743833e377 Mon Sep 17 00:00:00 2001 From: Dave Shoup Date: Tue, 27 Jan 2026 19:37:21 -0500 Subject: [PATCH 04/12] fix ConsumerTreeItem id --- src/models/consumerGroup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/consumerGroup.ts b/src/models/consumerGroup.ts index 1be31ea63..fd542b69c 100644 --- a/src/models/consumerGroup.ts +++ b/src/models/consumerGroup.ts @@ -233,7 +233,7 @@ export class ConsumerTreeItem extends vscode.TreeItem { : resource.consumerId; super(label); - this.id = `${resource.clusterId}-${resource.consumerGroupId}`; + this.id = `${resource.clusterId}-${resource.clientId}-${resource.consumerId}`; this.resource = resource; this.contextValue = `${resource.connectionType.toLowerCase()}-consumer-group-member`; From 54d69c8cdd8fe047917a7cd1c0f0ec53908169f2 Mon Sep 17 00:00:00 2001 From: Dave Shoup Date: Tue, 27 Jan 2026 19:40:36 -0500 Subject: [PATCH 05/12] register commands and update menus view/item/context --- package.json | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/package.json b/package.json index 50adedd13..07b203671 100644 --- a/package.json +++ b/package.json @@ -336,6 +336,12 @@ "title": "Set Kerberos krb5.conf Path", "category": "Confluent: Connections" }, + { + "command": "confluent.consumerGroups.refresh", + "icon": "$(sync)", + "title": "Refresh Consumer Groups", + "category": "Confluent: Consumer Groups" + }, { "command": "confluent.copyOrganizationId", "title": "Copy Organization ID", @@ -1370,6 +1376,10 @@ "command": "confluent.connections.setKrb5ConfigPath", "when": "true" }, + { + "command": "confluent.consumerGroups.refresh", + "when": "false" + }, { "command": "confluent.copyOrganizationId", "when": "false" @@ -2192,6 +2202,21 @@ "when": "view == confluent-topics && viewItem =~ /ccloud-kafka-topic.*-flinkable.*/", "group": "z_openInCloud" }, + { + "command": "confluent.consumerGroups.refresh", + "when": "view == confluent-topics && viewItem =~ /consumerGroups-container.*/", + "group": "inline" + }, + { + "command": "confluent.copyResourceId", + "when": "view == confluent-topics && viewItem =~ /.*-consumerGroup-.*/", + "group": "2_copy@1" + }, + { + "command": "confluent.openCCloudLink", + "when": "view == confluent-topics && viewItem =~ /ccloud-consumerGroup-.*/", + "group": "z_openInCloud" + }, { "command": "confluent.artifacts.createUdfRegistrationDocument", "when": "view == confluent-flink-database && viewItem =~ /.*-flink-artifact/", From e4c6ae869c91f3a74d14778987979c0ed76b2fa7 Mon Sep 17 00:00:00 2001 From: Dave Shoup Date: Fri, 27 Feb 2026 20:20:23 -0500 Subject: [PATCH 06/12] set up topicsView commands similar to flinkDatabaseView.ts --- src/commands/consumerGroups.ts | 33 -------- src/commands/topicsView.test.ts | 135 ++++++++++++++++++++++++++++++++ src/commands/topicsView.ts | 54 +++++++++++++ 3 files changed, 189 insertions(+), 33 deletions(-) delete mode 100644 src/commands/consumerGroups.ts create mode 100644 src/commands/topicsView.test.ts create mode 100644 src/commands/topicsView.ts diff --git a/src/commands/consumerGroups.ts b/src/commands/consumerGroups.ts deleted file mode 100644 index a16e6104a..000000000 --- a/src/commands/consumerGroups.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { Disposable } from "vscode"; -import { registerCommandWithLogging } from "."; -import { Logger } from "../logging"; -import type { ConsumerGroupContainer } from "../models/consumerGroup"; -import { TopicViewProvider } from "../viewProviders/topics"; - -const logger = new Logger("commands.consumerGroups"); - -/** - * Refresh the consumer groups container in the Topics view. - * @param container The ConsumerGroupContainer tree item that was clicked. - */ -async function refreshConsumerGroupsContainer(container: ConsumerGroupContainer): Promise { - if (!container) { - logger.error("No container provided to refreshConsumerGroupsContainer"); - return; - } - - const provider = TopicViewProvider.getInstance(); - const cluster = provider.kafkaCluster; - if (!cluster) { - logger.error("No Kafka cluster selected when attempting to refresh consumer groups container."); - return; - } - - await provider.refreshConsumerGroups(cluster, true); -} - -export function registerConsumerGroupCommands(): Disposable[] { - return [ - registerCommandWithLogging("confluent.consumerGroups.refresh", refreshConsumerGroupsContainer), - ]; -} diff --git a/src/commands/topicsView.test.ts b/src/commands/topicsView.test.ts new file mode 100644 index 000000000..b134ad556 --- /dev/null +++ b/src/commands/topicsView.test.ts @@ -0,0 +1,135 @@ +import * as assert from "assert"; +import * as sinon from "sinon"; + +import * as indexModule from "."; + +import { refreshResourceContainerCommand, registerTopicsViewCommands } from "./topicsView"; + +import { ConnectionType } from "../clients/sidecar"; +import { + KafkaClusterContainerLabel, + KafkaClusterResourceContainer, +} from "../models/containers/kafkaClusterResourceContainer"; +import type { ConsumerGroup } from "../models/consumerGroup"; +import type { KafkaTopic } from "../models/topic"; +import { TopicViewProvider } from "../viewProviders/topics"; +import { TEST_CCLOUD_KAFKA_CLUSTER } from "../../tests/unit/testResources/kafkaCluster"; + +describe("commands/topicsView.ts", () => { + let sandbox: sinon.SinonSandbox; + + beforeEach(() => { + sandbox = sinon.createSandbox(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + describe("registerTopicsViewCommands", () => { + let registerCommandWithLoggingStub: sinon.SinonStub; + + beforeEach(() => { + registerCommandWithLoggingStub = sandbox.stub(indexModule, "registerCommandWithLogging"); + }); + + it("should register the expected commands", () => { + registerTopicsViewCommands(); + + assert.strictEqual(registerCommandWithLoggingStub.callCount, 1); + + sinon.assert.calledWithExactly( + registerCommandWithLoggingStub, + "confluent.topics.refreshResourceContainer", + refreshResourceContainerCommand, + ); + }); + }); + + describe("refreshResourceContainerCommand", () => { + let provider: TopicViewProvider; + let refreshTopicsStub: sinon.SinonStub; + let refreshConsumerGroupsStub: sinon.SinonStub; + + beforeEach(() => { + provider = TopicViewProvider.getInstance(); + provider["resource"] = TEST_CCLOUD_KAFKA_CLUSTER; + + refreshTopicsStub = sandbox.stub(provider, "refreshTopics").resolves(); + refreshConsumerGroupsStub = sandbox.stub(provider, "refreshConsumerGroups").resolves(); + }); + + afterEach(() => { + provider.dispose(); + TopicViewProvider["instanceMap"].clear(); + }); + + it("should bail early if no container is provided", async () => { + await refreshResourceContainerCommand(undefined as any); + + sinon.assert.notCalled(refreshTopicsStub); + sinon.assert.notCalled(refreshConsumerGroupsStub); + }); + + it("should bail early if no Kafka cluster is selected", async () => { + provider["resource"] = null; + const container = new KafkaClusterResourceContainer( + TEST_CCLOUD_KAFKA_CLUSTER.connectionId, + ConnectionType.Ccloud, + KafkaClusterContainerLabel.CONSUMER_GROUPS, + [], + ); + + await refreshResourceContainerCommand(container); + + sinon.assert.notCalled(refreshTopicsStub); + sinon.assert.notCalled(refreshConsumerGroupsStub); + }); + + it("should call refreshTopics when the Topics container is provided", async () => { + const container = new KafkaClusterResourceContainer( + TEST_CCLOUD_KAFKA_CLUSTER.connectionId, + ConnectionType.Ccloud, + KafkaClusterContainerLabel.TOPICS, + [], + ); + + await refreshResourceContainerCommand(container); + + sinon.assert.calledOnceWithExactly(refreshTopicsStub, TEST_CCLOUD_KAFKA_CLUSTER, true); + sinon.assert.notCalled(refreshConsumerGroupsStub); + }); + + it("should call refreshConsumerGroups when the Consumer Groups container is provided", async () => { + const container = new KafkaClusterResourceContainer( + TEST_CCLOUD_KAFKA_CLUSTER.connectionId, + ConnectionType.Ccloud, + KafkaClusterContainerLabel.CONSUMER_GROUPS, + [], + ); + + await refreshResourceContainerCommand(container); + + sinon.assert.notCalled(refreshTopicsStub); + sinon.assert.calledOnceWithExactly( + refreshConsumerGroupsStub, + TEST_CCLOUD_KAFKA_CLUSTER, + true, + ); + }); + + it("should log an error for an unknown container label", async () => { + const container = new KafkaClusterResourceContainer( + TEST_CCLOUD_KAFKA_CLUSTER.connectionId, + ConnectionType.Ccloud, + "Unknown Label" as any, + [], + ); + + await refreshResourceContainerCommand(container); + + sinon.assert.notCalled(refreshTopicsStub); + sinon.assert.notCalled(refreshConsumerGroupsStub); + }); + }); +}); diff --git a/src/commands/topicsView.ts b/src/commands/topicsView.ts new file mode 100644 index 000000000..981a4063e --- /dev/null +++ b/src/commands/topicsView.ts @@ -0,0 +1,54 @@ +import type { Disposable } from "vscode"; +import { registerCommandWithLogging } from "."; +import { Logger } from "../logging"; +import type { ISearchable } from "../models/resource"; +import { + KafkaClusterContainerLabel, + type KafkaClusterResourceContainer, +} from "../models/containers/kafkaClusterResourceContainer"; +import { TopicViewProvider } from "../viewProviders/topics"; + +const logger = new Logger("commands.topicsView"); + +/** + * Refresh a resource container (Topics or Consumer Groups) in the Topics view. + * @param container The {@link KafkaClusterResourceContainer} tree item that was clicked. + */ +export async function refreshResourceContainerCommand( + container: KafkaClusterResourceContainer, +): Promise { + if (!container) { + logger.error("No container provided to refreshResourceContainerCommand"); + return; + } + + const provider = TopicViewProvider.getInstance(); + const cluster = provider.kafkaCluster; + if (!cluster) { + logger.error("No Kafka cluster selected when attempting to refresh resource container."); + return; + } + + switch (container.label) { + case KafkaClusterContainerLabel.TOPICS: + await provider.refreshTopics(cluster, true); + break; + case KafkaClusterContainerLabel.CONSUMER_GROUPS: + await provider.refreshConsumerGroups(cluster, true); + break; + default: + logger.error( + `Unknown container label "${container.label}" in refreshResourceContainerCommand`, + ); + } +} + +/** Register commands for the Topics view's container-level actions. */ +export function registerTopicsViewCommands(): Disposable[] { + return [ + registerCommandWithLogging( + "confluent.topics.refreshResourceContainer", + refreshResourceContainerCommand, + ), + ]; +} From 22b631cc15c75b25ed508e4604cf14a8560dc57f Mon Sep 17 00:00:00 2001 From: Dave Shoup Date: Fri, 27 Feb 2026 20:25:25 -0500 Subject: [PATCH 07/12] update context values and groupings for commands --- package.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 07b203671..6b63305b3 100644 --- a/package.json +++ b/package.json @@ -337,10 +337,10 @@ "category": "Confluent: Connections" }, { - "command": "confluent.consumerGroups.refresh", + "command": "confluent.topics.refreshResourceContainer", "icon": "$(sync)", - "title": "Refresh Consumer Groups", - "category": "Confluent: Consumer Groups" + "title": "Refresh Group", + "category": "Confluent: Topics View" }, { "command": "confluent.copyOrganizationId", @@ -1377,7 +1377,7 @@ "when": "true" }, { - "command": "confluent.consumerGroups.refresh", + "command": "confluent.topics.refreshResourceContainer", "when": "false" }, { @@ -2203,18 +2203,18 @@ "group": "z_openInCloud" }, { - "command": "confluent.consumerGroups.refresh", - "when": "view == confluent-topics && viewItem =~ /consumerGroups-container.*/", - "group": "inline" + "command": "confluent.topics.refreshResourceContainer", + "when": "view == confluent-topics && viewItem =~ /.*-container/", + "group": "inline@2" }, { "command": "confluent.copyResourceId", - "when": "view == confluent-topics && viewItem =~ /.*-consumerGroup-.*/", + "when": "view == confluent-topics && viewItem =~ /.*-consumer-group-.*/", "group": "2_copy@1" }, { "command": "confluent.openCCloudLink", - "when": "view == confluent-topics && viewItem =~ /ccloud-consumerGroup-.*/", + "when": "view == confluent-topics && viewItem =~ /ccloud-consumer-group-.*/", "group": "z_openInCloud" }, { From f54112028e444f0758da612b9280e456d95f1d8b Mon Sep 17 00:00:00 2001 From: Dave Shoup Date: Fri, 27 Feb 2026 20:26:01 -0500 Subject: [PATCH 08/12] register topics view commands during extension activation --- src/extension.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index ce3d38998..e1752e1ae 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -23,7 +23,7 @@ import { registerChatTools } from "./chat/tools/registration"; import { FlinkSqlCodelensProvider } from "./codelens/flinkSqlProvider"; import { registerCommandWithLogging } from "./commands"; import { registerConnectionCommands } from "./commands/connections"; -import { registerConsumerGroupCommands } from "./commands/consumerGroups"; +import { registerTopicsViewCommands } from "./commands/topicsView"; import { registerDebugCommands } from "./commands/debugtools"; import { registerDiffCommands } from "./commands/diffs"; import { registerDockerCommands } from "./commands/docker"; @@ -264,7 +264,7 @@ async function _activateExtension( ...registerSchemaRegistryCommands(), ...registerSchemaCommands(), ...registerTopicCommands(), - ...registerConsumerGroupCommands(), + ...registerTopicsViewCommands(), ...registerDiffCommands(), ...registerExtraCommands(), ...registerDockerCommands(), From 3a419e5118072534eb037c1c93f4a1c6cfff9564 Mon Sep 17 00:00:00 2001 From: Dave Shoup Date: Fri, 27 Feb 2026 20:26:18 -0500 Subject: [PATCH 09/12] add consumer group container context value to enable group refresh command visibility --- src/viewProviders/topics.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/viewProviders/topics.ts b/src/viewProviders/topics.ts index cb43195d7..8379e6bf1 100644 --- a/src/viewProviders/topics.ts +++ b/src/viewProviders/topics.ts @@ -216,7 +216,7 @@ export class TopicViewProvider extends ParentedBaseViewProvider< cluster.connectionType, KafkaClusterContainerLabel.CONSUMER_GROUPS, [], - undefined, // no context value for now since no commands are needed yet for this container + "consumer-groups-container", new ThemeIcon(IconNames.CONSUMER_GROUP), ); From 08006cdd425d4148118ca4a8bd58a58d46730246 Mon Sep 17 00:00:00 2001 From: Dave Shoup Date: Fri, 27 Feb 2026 20:32:04 -0500 Subject: [PATCH 10/12] fix tests from updated getter methods --- src/models/consumerGroup.test.ts | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/models/consumerGroup.test.ts b/src/models/consumerGroup.test.ts index 664bb9778..a866a5bca 100644 --- a/src/models/consumerGroup.test.ts +++ b/src/models/consumerGroup.test.ts @@ -21,11 +21,8 @@ import { ConsumerGroupState, ConsumerGroupTreeItem, ConsumerTreeItem } from "./c describe("models/consumerGroup.ts", () => { describe("ConsumerGroup", () => { describe("id", () => { - it("should return clusterId-consumerGroupId", () => { - assert.strictEqual( - TEST_CCLOUD_CONSUMER_GROUP.id, - `${TEST_CCLOUD_CONSUMER_GROUP.clusterId}-${TEST_CCLOUD_CONSUMER_GROUP_ID}`, - ); + it("should return consumerGroupId", () => { + assert.strictEqual(TEST_CCLOUD_CONSUMER_GROUP.id, TEST_CCLOUD_CONSUMER_GROUP_ID); }); }); @@ -111,12 +108,8 @@ describe("models/consumerGroup.ts", () => { describe("Consumer", () => { describe("id", () => { - it("should return clusterId-consumerGroupId-consumerId", () => { - const consumer = TEST_CCLOUD_CONSUMER; - assert.strictEqual( - consumer.id, - `${consumer.clusterId}-${consumer.consumerGroupId}-${consumer.consumerId}`, - ); + it("should return consumerId", () => { + assert.strictEqual(TEST_CCLOUD_CONSUMER.id, TEST_CCLOUD_CONSUMER.consumerId); }); }); @@ -179,10 +172,11 @@ describe("models/consumerGroup.ts", () => { assert.strictEqual(treeItem.label, TEST_CCLOUD_CONSUMER_GROUP.consumerGroupId); }); - it("should set id from the resource", () => { + it("should set id as clusterId-consumerGroupId", () => { const treeItem = new ConsumerGroupTreeItem(TEST_CCLOUD_CONSUMER_GROUP); + const group = TEST_CCLOUD_CONSUMER_GROUP; - assert.strictEqual(treeItem.id, TEST_CCLOUD_CONSUMER_GROUP.id); + assert.strictEqual(treeItem.id, `${group.clusterId}-${group.consumerGroupId}`); }); it("should include connection type and state in contextValue", () => { @@ -340,9 +334,14 @@ describe("models/consumerGroup.ts", () => { assert.strictEqual(treeItem.label, consumer.consumerId); }); - it("should set id from the resource", () => { + it("should set id as clusterId-clientId-consumerId", () => { const treeItem = new ConsumerTreeItem(TEST_CCLOUD_CONSUMER); - assert.strictEqual(treeItem.id, TEST_CCLOUD_CONSUMER.id); + const consumer = TEST_CCLOUD_CONSUMER; + + assert.strictEqual( + treeItem.id, + `${consumer.clusterId}-${consumer.clientId}-${consumer.consumerId}`, + ); }); it("should include connection type in contextValue", () => { From 797ba11edbb2869f26d56e96bda08583a3a536e0 Mon Sep 17 00:00:00 2001 From: Dave Shoup Date: Fri, 27 Feb 2026 21:15:28 -0500 Subject: [PATCH 11/12] fix command sort order --- package.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 6b63305b3..defc51779 100644 --- a/package.json +++ b/package.json @@ -336,12 +336,6 @@ "title": "Set Kerberos krb5.conf Path", "category": "Confluent: Connections" }, - { - "command": "confluent.topics.refreshResourceContainer", - "icon": "$(sync)", - "title": "Refresh Group", - "category": "Confluent: Topics View" - }, { "command": "confluent.copyOrganizationId", "title": "Copy Organization ID", @@ -841,6 +835,12 @@ "title": "Refresh", "category": "Confluent: Topics" }, + { + "command": "confluent.topics.refreshResourceContainer", + "icon": "$(sync)", + "title": "Refresh Group", + "category": "Confluent: Topics View" + }, { "command": "confluent.topics.search", "icon": "$(search)", @@ -1376,10 +1376,6 @@ "command": "confluent.connections.setKrb5ConfigPath", "when": "true" }, - { - "command": "confluent.topics.refreshResourceContainer", - "when": "false" - }, { "command": "confluent.copyOrganizationId", "when": "false" @@ -1732,6 +1728,10 @@ "command": "confluent.topics.refresh", "when": "true" }, + { + "command": "confluent.topics.refreshResourceContainer", + "when": "false" + }, { "command": "confluent.topics.search", "when": "true" From 2e58c9aa14465f89bb45bc7dc5a707c59a8979d6 Mon Sep 17 00:00:00 2001 From: Dave Shoup Date: Thu, 12 Mar 2026 08:40:02 -0400 Subject: [PATCH 12/12] add tests for ConsumerGroupTreeItem.isSimple and null .coordinatorId --- src/models/consumerGroup.test.ts | 40 +++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/models/consumerGroup.test.ts b/src/models/consumerGroup.test.ts index a866a5bca..45945ae7d 100644 --- a/src/models/consumerGroup.test.ts +++ b/src/models/consumerGroup.test.ts @@ -16,7 +16,12 @@ import { TEST_CCLOUD_KAFKA_CLUSTER } from "../../tests/unit/testResources/kafkaC import { ConnectionType } from "../clients/sidecar"; import { CCLOUD_BASE_PATH, CCLOUD_CONNECTION_ID } from "../constants"; import { IconNames } from "../icons"; -import { ConsumerGroupState, ConsumerGroupTreeItem, ConsumerTreeItem } from "./consumerGroup"; +import { + ConsumerGroup, + ConsumerGroupState, + ConsumerGroupTreeItem, + ConsumerTreeItem, +} from "./consumerGroup"; describe("models/consumerGroup.ts", () => { describe("ConsumerGroup", () => { @@ -309,6 +314,39 @@ describe("models/consumerGroup.ts", () => { assert.ok(text.includes("currently rebalancing")); }); + + it("should show 'Yes' for simple consumer groups", () => { + const group = createConsumerGroup({ + connectionId: CCLOUD_CONNECTION_ID, + connectionType: ConnectionType.Ccloud, + environmentId: TEST_CCLOUD_KAFKA_CLUSTER.environmentId, + clusterId: TEST_CCLOUD_KAFKA_CLUSTER.id, + isSimple: true, + }); + const item = new ConsumerGroupTreeItem(group); + const tooltip = (item.tooltip as MarkdownString).value; + + assert.ok(tooltip.includes("Yes")); + }); + + it("should omit coordinator when coordinatorId is null", () => { + const group = new ConsumerGroup({ + connectionId: CCLOUD_CONNECTION_ID, + connectionType: ConnectionType.Ccloud, + environmentId: TEST_CCLOUD_KAFKA_CLUSTER.environmentId, + clusterId: TEST_CCLOUD_KAFKA_CLUSTER.id, + consumerGroupId: "test-group", + state: ConsumerGroupState.Stable, + isSimple: false, + partitionAssignor: "range", + coordinatorId: null, + members: [], + }); + const item = new ConsumerGroupTreeItem(group); + const tooltip = (item.tooltip as MarkdownString).value; + + assert.ok(!tooltip.includes("Coordinator Broker")); + }); }); });