Skip to content

[pull] master from mattermost:master#811

Merged
pull[bot] merged 13 commits into
code:masterfrom
mattermost:master
Jul 2, 2026
Merged

[pull] master from mattermost:master#811
pull[bot] merged 13 commits into
code:masterfrom
mattermost:master

Conversation

@pull

@pull pull Bot commented Jul 2, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

cursor Bot and others added 6 commits July 2, 2026 10:21
* Add --show-ids flag to mmctl channel list

Mirror post list --show-ids so the plain-text channel list output
includes channel IDs.

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* Add unit tests for mmctl channel list --show-ids

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* Assert show-ids flag registration in channel list test

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* chore: re-trigger CodeRabbit review after rate limit

Co-authored-by: mattermost-code <matty-code@mattermost.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: mattermost-code <matty-code@mattermost.com>
…7309)

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: mattermost-code <matty-code@mattermost.com>
…us (#37312)

* Add mmctl user status get/set commands

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* Register local-mode status routes and add mmctl status tests

Expose GET/PUT /users/{user_id}/status on the local socket API so
mmctl --local can read and set statuses, and add unit + e2e coverage
for the new user status commands.

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* Improve mmctl status tests and validate dnd-end-time earlier

Validate --dnd-end-time before resolving the target user, add command
wiring/flag coverage, a GetMe failure case, and stronger e2e assertions
from the test-quality review.

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* Regenerate mmctl docs for user status command

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* Accept RFC3339 UTC timestamps for mmctl status --dnd-end-time

Use time.RFC3339 parsing so --dnd-end-time accepts Z-suffixed UTC
timestamps in addition to numeric offsets, per CodeRabbit review feedback.

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* Show @username in mmctl user status output

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: mattermost-code <matty-code@mattermost.com>
…nsole (#37206)

* [MM-64430] Allow editing team name and description in System Console

Make the Team Profile panel on the System Console team detail page editable
so admins can rename a team and edit its description without switching to the
chat-facing team settings. Changes are saved through the existing
SaveChangesPanel flow via patchTeam.

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* [MM-64430] Widen team profile edit inputs to fit full team name

The Team Name and Team Description inputs inherited the narrow team-desc-col
width, making long values appear visually truncated. Let the edit column grow
to fill the panel so the full value is visible.

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* [MM-64430] Add tests for editing team name and description in System Console

Cover the new editable Team Profile fields and TeamDetails save flow:
team_profile renders/edits the name and description inputs and surfaces the
name validation error; team_details saves the trimmed name and description
via patchTeam and blocks the save when the name is too short.

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* [MM-64430] Strengthen team profile edit tests per review

Scope the name validation error assertion to the name field, and cover error
recovery, whitespace-only names, navigation blocking on edit, and resetting
the fields when a different team is loaded.

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* [MM-64430] Pre-commit fixes: i18n sync, lint and stylelint

Run i18n-extract to drop the now-unused team profile strings, reorder the new
SCSS rule properties, and reformat the new tests to satisfy JSX lint rules.

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* Remove stray comment in TeamProfile cloud guard

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* Retrigger CodeRabbit review after rate limit

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* Address CodeRabbit feedback on team profile save flow

- Only reset editable fields when the selected team changes, not when
  totalGroups updates
- Validate team name before archive/restore operations
- Patch profile fields before archiving so Save and Archive persists edits

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* Retrigger Enterprise CI after transient npm ECONNRESET

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* Validate team name before opening Save and Archive modal

When the team name is invalid (too short) and the team is toggled to be
archived, clicking Save opened the Save and Archive confirm modal and the
validation error rendered behind it, so confirming appeared to do nothing.
Validate the name in onSave before opening the modal so the inline error
fires immediately, and defensively close the archive modal in handleSubmit.

* Add e2e test for editing team name and description in System Console

* Address review: exact URL assertion + archive-invalid-name e2e coverage

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: mattermost-code <matty-code@mattermost.com>
@pull pull Bot locked and limited conversation to collaborators Jul 2, 2026
@pull pull Bot added the ⤵️ pull label Jul 2, 2026
avasconcelos114 and others added 7 commits July 2, 2026 17:00
…tly (#37228)

* Revert "Fix flaky TestUserHasJoinedChannel (#37110)"

This reverts commit f825da5.

* Revert "Fix flaky TestUserHasJoinedChannel (#37052)"

This reverts commit c4b82e5.

* Revert "Fix flaky TestUserHasJoinedChannel (#36985)"

This reverts commit 58022aa.

* Revert "Fix flaky TestUserHasJoinedChannel (#36660)"

This reverts commit 981e534.

* MM-68730 Update TestUserHasJoinedChannel to track hook calls differently

* Revert "Fix flaky TestUserHasJoinedChannel (#37288)"
* feat(docs): move docs-experimental content into monorepo docs/

Co-authored-by: Cursor <cursoragent@cursor.com>

* Remove plan related files and comments

* Cleanup comments, remove generated files

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
* [MM-68421] Frontend: PAT creation UI — expiry picker and status display

Wires the webapp UI to the server-side support added in PR #36706 (and
the MM-68419 model changes):

- Extends UserAccessToken type with expires_at, and ClientConfig with
  EnforcePersonalAccessTokenExpiry / MaximumPersonalAccessTokenLifetimeDays.
- Threads expires_at through Client4.createUserAccessToken and the
  mattermost-redux createUserAccessToken action.
- Adds a date/time picker to the PAT creation form (reuses
  DateTimePickerModal). Honors enforcement and clamps to the
  max-lifetime setting; maps server error ids
  (expires_at_required/in_past/too_far) to localized messages.
- Displays expiry, derived status badge (active/expired/disabled), and
  an approaching-expiry warning (<7 days) in the account settings token
  list. Mirrors expiry + status in the admin Manage Tokens modal.
- Adds the supporting i18n keys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [MM-68421] Address review: i18n, ServerError type, scss, explicit guards

- Inject intl so the "Expires in N days" tooltip and the picker
  ariaLabel are localized instead of hard-coded English.
- Use the canonical ServerError type from @mattermost/types/errors
  instead of an ad-hoc inline cast.
- Dedupe the new i18n ids — keep a single "Expires: " string per
  namespace and drop the duplicates introduced in the first pass.
- Add scss for setting-box__token-expiry / __token-status /
  __token-expiry-warning so the new status pill and warning render
  with the expected styling.
- Replace truthy checks on the numeric expiresAt with explicit
  > 0 comparisons for readability.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [MM-68421] Replace expiry datetime picker with preset chooser + custom date

Per UX discussion: PATs are long-lived so sub-day precision is noise.
Swap the DateTimePickerModal for a native <select> of presets
(No expiry, 7d, 30d, 90d, 1 year, Custom date) with a date-only
<input type="date"> revealed when Custom is selected. Effective time
is end-of-local-day, which matches how users think about expiry.

- Drops the DateTimePickerModal import and the picker open/close
  handlers; removes the moment-timezone import.
- Adds isPresetAllowed() that hides presets exceeding
  MaximumPersonalAccessTokenLifetimeDays, and a defaultExpiryPreset()
  that picks 30d (then 7d, then Custom) when enforcement is on,
  No expiry otherwise.
- The custom <input type="date"> uses min=today and max=now+maxDays
  for native bounds; submit-time validation still maps server error
  ids if the user bypasses the bounds.
- i18n: adds preset labels; drops the now-unused picker/clear/change
  strings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [MM-68421] Fix CI: playwright config and ESLint blank line

- Add EnforcePersonalAccessTokenExpiry / MaximumPersonalAccessTokenLifetimeDays
  to e2e-tests/playwright/lib/src/server/default_config.ts so its tsc -b
  matches the updated ServiceSettings shape.
- Drop a stray double blank line in user_access_token_section.tsx that
  tripped no-multiple-empty-lines.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [MM-68421] Sort i18n keys to match formatjs extract output

ci/i18n-extract diffs en.json against the formatjs extractor's sorted
output and fails on any difference. Re-run the extract so the new
PAT-expiry keys land in alphabetical position.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [MM-68421] Address CodeRabbit findings

- Clamp the default custom-expiry date to maxLifetimeDays when set
  so the form doesn't open in an invalid state when
  defaultExpiryPreset() falls back to 'custom'.
- Reject a cleared/empty custom date with expires_at_required
  instead of silently submitting without an expiry; only forward
  expiresAt to the action when it's > 0.
- Use an explicit undefined check in Client4.createUserAccessToken
  so an intentional 0 isn't dropped from the request body.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [MM-68421] Update manage_tokens_modal snapshot for expiry + status row

The admin token list now renders an Expires row and a status badge per
token; refresh the jest snapshot.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [MM-68421] Add unit tests for PAT expiry helpers

Per the PR Test Analysis advisory: export the pure helpers from
user_access_token_section.tsx and add unit tests covering them.

Coverage:
- deriveTokenStatus: active / expired / inactive branches.
- mapServerErrorIdToMessage: all three server error ids (short and
  api.user.create_user_access_token.*.app_error variants) and the
  default null path.
- endOfLocalDayPlusDays: end-of-day on the Nth future day, 0 days.
- endOfLocalDayFromIsoDate: valid ISO date and malformed inputs.
- PRESET_DAYS: snapshot of the preset durations.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [MM-68421] Freeze time in PAT helper tests to avoid midnight flake

The date arithmetic helpers (Date.now, new Date()) could disagree
across a midnight boundary, making the tests theoretically flaky.
Pin system time to a stable mid-day in 2026 via jest.useFakeTimers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [MM-68421] Add component tests for PAT expiry creation UI

Covers the create-form validation branches (missing description, empty
custom date, past date, beyond maxLifetimeDays), enforceExpiry rendering
(no-expiry option hidden + enforced hint), maxLifetimeDays preset
filtering, and token-list status display (active/expired/disabled, never,
and the "expires soon" warning).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [MM-68421] Add behavioral status/expiry tests for manage_tokens_modal

Covers the admin token modal's derived status display: Active + "Never"
for an active token without expiry, Expired for an active token past its
expiry, Disabled for an inactive token regardless of expiry, and Active
with a rendered date (not "Never") for a token expiring in the future.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [MM-68421] Align PAT expiry UI with shipped server contract

The server (#36706) did not ship a separate EnforcePersonalAccessTokenExpiry
flag — expiry enforcement is implied by MaximumPersonalAccessTokenLifetimeDays
> 0. Two webapp gaps surfaced once the server side merged:

- enforceExpiry was read from the never-sent config.EnforcePersonalAccessToken
  Expiry, so the "hide No-expiry / require expiry" path was dead. Derive it from
  maxLifetimeDays > 0 instead and drop the dead config flag from the component,
  redux props, ClientConfig/ServiceSettings types, and the e2e default config.
- The server returns app.user_access_token.expires_at_{required,in_past,too_far}
  .app_error, but mapServerErrorIdToMessage matched the api.user.create_user_
  access_token.* namespace, so the localized errors never fired. Map the actual
  ids.

Unit tests updated accordingly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [MM-68421] Add Playwright e2e for PAT expiry UI

Covers, against a real server, the personal access token expiry surfaces in
Account Settings > Security:

- the expiry picker renders all presets and reveals the custom-date input
- a custom expiry with no date is blocked client-side
- MaximumPersonalAccessTokenLifetimeDays > 0 hides "No expiry" and oversized
  presets, shows the enforced hint, and rejects an over-the-limit custom date
- the token list shows Active/Never, an "expires in N days" warning, and the
  Disabled badge (seeded via the API)

The expired-status badge is left to the component unit tests since the server
rejects creating a token whose expiry is already in the past.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [MM-68421] Use locator('option') for native select assertions

getByRole('option') does not reliably match the options of a closed native
<select>, which would make the absence assertions (toHaveCount(0)) pass
vacuously. Query option elements by DOM instead, matching the repo's house
pattern for native selects.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [MM-68421] Fix expiry overshoot vs server cap and review nits

Review found that presets/custom dates resolve to end-of-local-day, which can
sit up to ~24h beyond the server cap of "now + MaximumPersonalAccessTokenLife
timeDays" (an exact duration from creation time). With a max configured, the
default preset equals the cap, so accepting the default and saving was rejected
server-side with expires_at_too_far for most of the day.

- Clamp the submitted expiry to the server cap when a maximum lifetime is set.
  Validation still runs on the raw end-of-day value so an explicitly out-of-range
  custom date is still rejected; only the in-range end-of-day overshoot is clamped.
- Count "expires in N days" from the start of today and floor it, so an end-of-day
  expiry no longer over-reports by one (a 7-day token reads "7 days", not "8").
- Add an aria-label to the custom expiry date input.

Tests: unit coverage for clampExpiresAtToMaxLifetime; a Playwright spec that
creates a token with the default preset under a 30-day cap and asserts success.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [MM-68421] Apply prettier formatting to PAT e2e spec

The ci/playwright/npm-check job (lint + prettier + tsc + lint:test-docs) failed
on prettier formatting. eslint and tsc were clean; reformat the spec to satisfy
prettier as well.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [MM-68421] Add PAT max-lifetime System Console setting and creation-form UX fixes

- Add ServiceSettings.MaximumPersonalAccessTokenLifetimeDays number field to
  System Console > Integrations > Integration Management, after Enable Personal
  Access Tokens (disabled when tokens are disabled).
- Disable the token creation Save button until a non-empty description is
  entered (description input is now controlled; whitespace-only rejected).
- Render the token creation form as a distinct "Create New Token" card so it no
  longer blends into the existing token list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Fix stylelint property order in new-token card

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* [MM-68421] Validate PAT expiry inline before submit

Surface the expiry validation error in the create-token form and disable
Save while the selection is invalid, instead of only failing inside the
create-confirmation flow. Previously a system admin had to click Save then
"Yes, Create" before seeing "An expiry date is required." for an empty
custom date.

Extracts the expiry checks into getExpiryValidationError(), reuses it as
the handleCreateToken guard, and renders the result inline + in the Save
button's disabled condition.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [MM-68421] Fix PAT expiry e2e specs for inline validation

The "blocks submitting a custom expiry with no date chosen" and "enforces
expiry when a maximum lifetime is configured" specs clicked the Save button
and expected an inline error afterward. Since 7ccd65e surfaces the expiry
error inline and disables Save while the selection is invalid, the click
timed out on a disabled button.

Assert the inline error is visible and that Save is disabled, instead of
clicking it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* MM-69075: server-side revoke non-compliant PATs

Adds store queries (GetNonCompliantExpiry/CountNonCompliantExpiry),
app methods to count and bulk-revoke (hard-delete) non-compliant PATs in
batches with session-cache invalidation, sysadmin-gated api4 endpoints
with audit logging, Client4 methods, and the OpenAPI spec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* MM-69075: System Console button to revoke non-compliant PATs

Adds a 'Revoke non-compliant tokens' control under Integrations >
Integration Management (next to Maximum Personal Access Token Lifetime).
It shows the current non-compliant count (refreshed on load, save, and
revoke), disables when there is nothing to revoke, and confirms the
irreversible delete with the blast radius. Wires up the TS Client4
methods and i18n strings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* MM-69075: Address PR review feedback

- Rename route from /tokens/revoke_non_compliant to /tokens/non_compliant/revoke for consistency with /tokens/non_compliant/count
- Remove redundant c.LogAudit("") before permission check
- Remove redundant c.LogAudit on success (structured audit record is sufficient)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* MM-69075: Simplify non-compliant token revocation with single store call

- Add DeleteNonCompliantExpiry store method: atomically deletes non-compliant
  tokens and their sessions in a single Postgres CTE, returning affected user
  IDs for session cache clearing
- Replace the get->extract IDs->delete dance in RevokeNonCompliantUserAccessTokens
  with the new single store call per batch
- Switch post-loop partial completion check to CountNonCompliantExpiry
- Add partial completion error i18n string
- Clear stale error banner in refreshCount on successful fetch

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* MM-69075: Remove GetNonCompliantExpiry, migrate tests to DeleteNonCompliantExpiry

GetNonCompliantExpiry is now unused — DeleteNonCompliantExpiry supersedes it.
Remove it from the store interface, sqlstore, retrylayer, timerlayer, and mock.
Migrate the store test to exercise DeleteNonCompliantExpiry instead, adding
session-deletion verification.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* MM-69075: Fix DISTINCT undercounting bug and add multi-token-per-user test

- Remove SELECT DISTINCT from DeleteNonCompliantExpiry CTE so each deleted
  token row is returned, not collapsed per user; totalRevoked now counts
  tokens, not users, and batch-continuation is correct
- Deduplicate userIDs in app layer before ClearSessionCacheForUser calls
- Add multi-token-per-user fixture to store test: two non-compliant tokens
  sharing a UserId verify len(userIDs)==4 and catch any future DISTINCT regression

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* MM-69075: Fix generated store layers and mock ordering

Regenerate retrylayer/timerlayer via make store-layers and fix
DeleteNonCompliantExpiry alphabetical position in mock file.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* MM-69075: Inline nonCompliantExpiryWhere into its sole caller

The helper was extracted to share the predicate between GetNonCompliantExpiry
and CountNonCompliantExpiry. GetNonCompliantExpiry is gone; with a single
call site the extracted function adds no value.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* MM-69075: Fix flaky test — relax global count assertions

Global count assertions (require.Equal against baseline) are fragile when
other concurrent tests hold non-compliant tokens. Replace exact equality
with GreaterOrEqual/LessOrEqual for global counts. The DISTINCT regression
is still caught precisely: sharedUserID must appear exactly twice in the
returned slice (once per token, not once per user).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* MM-69075: Fix false partial-revoke error caused by read-replica lag

After DeleteNonCompliantExpiry writes to master, the post-delete
CountNonCompliantExpiry read targets the replica, which may not have
caught up yet. This made the first revoke call return a spurious HTTP
500 even though all tokens were actually deleted, and a second click
then showed 'Revoked 0' because nothing remained.

Fix: track whether the batch loop exited via a natural break (all done)
vs. exhausted revokeNonCompliantMaxBatches (genuinely incomplete), and
signal the partial-revoke error only in the latter case. This removes
the racy replica read entirely — the loop's own exit conditions prove
completion on master.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* MM-69075: Add Playwright e2e coverage for revoke non-compliant tokens UI

Covers the gap flagged in PR review (#37030): button/disabled states,
AlertBanner states, confirmation modal open/cancel/confirm, count
refresh after policy save, and token auth invalidation (compliant and
bot tokens survive a revoke).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* MM-69075: Fix testid for number-type Maximum PAT Lifetime field

Number-type TextSetting inputs use ${id}number as their test id, not
${id}input (only text-type inputs get the 'input' suffix). Found by
actually running the spec locally against a server built from this
branch - all 4 tests now pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* MM-69075: Fix prettier formatting in e2e spec

CI's prettier --check flagged this file; ran prettier --write to match
project style. The other CI lint warnings (max-lines, no-warning-comments)
are pre-existing, in files this branch never touched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* MM-69075: Fix TS2345 - UserAccessToken.token is optional

The token secret field is only populated on the object returned from
CreateUserAccessToken, so its type is string | undefined. Guard for
that in tokenIsUsable instead of asserting non-null at every call site.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Delay rendering single image content until the thumbnail availability check
finishes, while still reserving the final image dimensions up front. This
prevents media-heavy channels from shifting message row heights when
SizeAwareImage mounts after the plugin thumbnail check completes, which can
move scroll position in permalink views and while loading older posts.

Add a renderPlaceholderOnly mode to SizeAwareImage so callers can mount the
same dimension placeholder without rendering the real image, mini preview,
loader, or preview controls. Use that mode in SingleImageView while the
thumbnail HEAD request is pending. Once the check succeeds, render the image
normally. If the thumbnail is rejected by a plugin, keep the existing collapsed
filename behavior unchanged.

Also cover the pending, accepted, plugin-rejected, and already-rejected paths
with focused tests.
…able (#37336)

* [MM-69656] Paginate bot accounts list to load all bots

The Bot Accounts page requested per_page=10000 in a single call, but the
server clamps per_page to 200, so only the 200 oldest bots (CreateAt ASC)
were ever loaded. Bots beyond the first 200 were absent from the list and
its client-side search even though they existed.

Fetch bots in pages of 200 and accumulate until a short page is returned.

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* [MM-69656] Add test for bot accounts pagination

Verifies the Bot Accounts page requests successive pages of 200 until a
short page is returned and processes bots that live beyond the first page.

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* [MM-69656] Cover pagination boundary and empty cases for bot accounts

Add tests for the exact-multiple page boundary (a full final data page
followed by an empty page) and the zero-bot case.

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* [MM-69656] Fix loadBots mock param types in bot accounts test

Make the mocked loadBots page argument optional to match the action's
signature, and normalize the pagination loop formatting.

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* Fix bots page stuck on loading when first fetch fails

Remove the loaded early-return in loadAllBots so loading is always
cleared after the fetch loop, including when the first loadBots call
fails or returns no data.

Add regression tests for failed and empty first-page responses.

Co-authored-by: mattermost-code <matty-code@mattermost.com>

* Surface bot accounts load errors to the user

Add error handling for failed page fetches in the Bot Accounts list:
a full-failure danger banner when the first page fails (previously an
empty list was shown), and an incomplete-list warning banner when a
later page fails (previously the list was silently truncated).

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: mattermost-code <matty-code@mattermost.com>
)

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
@pull pull Bot merged commit 076370e into code:master Jul 2, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants