diff --git a/cmd/channel.go b/cmd/channel.go index af0621a..09e5ad2 100644 --- a/cmd/channel.go +++ b/cmd/channel.go @@ -124,9 +124,9 @@ func init() { channelCmd.AddCommand(channelListCmd, channelNewCmd, channelInviteCmd) channelListCmd.Flags().String("user", "", "User ID, @handle, or email") - channelListCmd.Flags().Bool("all", false, "List all workspace conversations (auto-paginates unless --cursor is set)") + channelListCmd.Flags().Bool("all", false, "List all workspace conversations instead of just the ones the bot is a member of") channelListCmd.Flags().Int("limit", 100, "Conversations per page fetched from Slack") - channelListCmd.Flags().String("cursor", "", "Resume from this pagination cursor instead of auto-paginating") + channelListCmd.Flags().String("cursor", "", "Resume from this pagination cursor instead of auto-paginating (applies with or without --all)") channelNewCmd.Flags().String("name", "", "Channel name") _ = channelNewCmd.MarkFlagRequired("name") diff --git a/internal/slack/channels.go b/internal/slack/channels.go index 12fb991..e2caa45 100644 --- a/internal/slack/channels.go +++ b/internal/slack/channels.go @@ -50,7 +50,7 @@ func ListChannels(ctx context.Context, client *api.Client, opts ListChannelsOpts method = "conversations.list" } - autoPaginate := opts.All && opts.Cursor == "" + autoPaginate := opts.Cursor == "" result := &ChannelListResult{} cursor := opts.Cursor diff --git a/internal/slack/channels_test.go b/internal/slack/channels_test.go index af2d390..04a7f0a 100644 --- a/internal/slack/channels_test.go +++ b/internal/slack/channels_test.go @@ -85,6 +85,26 @@ func TestListChannels_AllAutoPaginatesAcrossShardedPages(t *testing.T) { } } +func TestListChannels_MemberOnlyAlsoAutoPaginates(t *testing.T) { + srv := fakeConversationsList(t, [][]string{ + {"general"}, + {"nul-team", "internal-acme"}, + }) + defer srv.Close() + + result, err := ListChannels(context.Background(), testClient(srv.URL), ListChannelsOpts{}) + if err != nil { + t.Fatalf("ListChannels: %v", err) + } + + if len(result.Channels) != 3 { + t.Fatalf("expected 3 channels merged across pages, got %d: %+v", len(result.Channels), result.Channels) + } + if result.NextCursor != "" { + t.Fatalf("expected no next_cursor after exhausting pages, got %q", result.NextCursor) + } +} + func TestListChannels_ExplicitCursorFetchesSinglePage(t *testing.T) { srv := fakeConversationsList(t, [][]string{ {"general"}, @@ -102,6 +122,23 @@ func TestListChannels_ExplicitCursorFetchesSinglePage(t *testing.T) { } } +func TestListChannels_ExplicitCursorFetchesSinglePageWithoutAll(t *testing.T) { + srv := fakeConversationsList(t, [][]string{ + {"general"}, + {"internal-acme"}, + }) + defer srv.Close() + + result, err := ListChannels(context.Background(), testClient(srv.URL), ListChannelsOpts{Cursor: "some-cursor"}) + if err != nil { + t.Fatalf("ListChannels: %v", err) + } + + if len(result.Channels) != 1 { + t.Fatalf("expected exactly 1 page of channels with explicit cursor, got %d", len(result.Channels)) + } +} + func TestListChannels_TruncatesAtPageCap(t *testing.T) { old := maxAutoPaginatePages maxAutoPaginatePages = 2