mattermost-mobile-upstream/detox
Harshil Sharma 4e2a508774
Some checks are pending
ci / lint-typecheck (push) Waiting to run
ci / detox-lint-typecheck (push) Waiting to run
ci / test (push) Waiting to run
Access channel action (#10223)
* MM-68219 - Add redacted files placeholder and related functionality

* add feature flag control and e2e tests

* adjust placeholder design, polish code, fix permalink preview issue

* polish code and add missing test

* use import path with right path

* gate post refetch behind the feature flag, refetch the open thread and avoid observeCount

* restore filesInfo for the permalink files prop added upstream

* fix stale redaction on background servers, consume the flag on every fetch path and share the viewport emitter

* replace the in-memory redaction flag with a persisted per-post epoch so ABAC file decisions survive restarts and stale posts stay hidden

* raise the redaction epoch on every resync, capture the epoch counter, only invalidate channels on role changes, and store the newer epoch when a re-verified post is otherwise unchanged

* store superseded responses unverified instead of dropping them, keep the since-fetch when re-verifying, verify permalink embeds against the linked channel, and capture the websocket epoch on arrival

* nvalidate file decisions when a user attribute field changes or all its values are cleared

* batch channel invalidations, close file viewers only when affected, reset the epoch on unstamped redaction changes, and only  re-verify the newest page's attachment posts

* re-check older channel posts a page at a time instead of one request per post

* skip the unstamped epoch lookup for posts with no files, redacted count or permalink

* MM-70905 - disable and grey out the attachment button when an ABAC permission policy denies uploads in the channel

* First draft of updated read permission handling

* keep the attribute-view retry after later invalidations, retry linked posts unless refused for the current epoch, and stop older payloads from rolling back edits via the redaction check

* improved Data fetches

* fixes

* Fixed test

* Fixed archived channel issue

* Removed re-sync on team switch

* Define message enhancement

* Coderabbit fixes

* React to permission_policy_updated only for the actions it touched

The server now lists the rule actions a permission policy change touched.
Every connected client gets this event, so each step runs only when an
action it depends on changed:

- download_file_attachment raises the redaction epoch, which also
  revalidates the render decisions
- any other cached render-decision action only expires the decisions
- channel_read_access reconciles the channel list

An empty list (an auto-add toggle) does nothing, and a server that
predates the list is treated as having changed every action.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FvkCrND4n9oyehQUa9V5QH

* Handled empty channel list

* Fixed channel access races and tablet kick fallback

Read stored channel IDs before the team channel list request so channels joined or left mid-request are not wrongly purged or restored, and set the fallback channel instead of the kicked one as current on a tablet when the server is not active.

* Minor fix

* Moved pending channel access checks to EphemeralStore

* Moved channel access revoked sheet helpers to navigation utils

* Gated channel access enforcement on the ChannelPermissionActions feature flag

* Reported a channel lost to read access on reconnect as revoked access

* Addressed review comments on channel read access

Jittered the channel list reconcile after a permission policy update, logged
non-request failures in channel access checks as errors, and set the channel
read access version to 12.2.0.

* Implemented write actions (#10224)

* Implemented write actions

* Lint fix

* Test that write and management policy changes only revalidate decisions

A permission_policy_updated event naming channel_write_access or
channel_management_access expires the cached render decisions those gates
read, without raising the redaction epoch or reconciling the channel list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FvkCrND4n9oyehQUa9V5QH

* Shared the channel access enforcement check

* Addressed review comments on channel write access

Hid pinning and the acknowledge button while a write access policy denies
the channel, as the server refuses both, and moved the read-only notice to
app/components since two screens share it.

---------

Co-authored-by: Claude <noreply@anthropic.com>

* Expect no Manage button on archived channel members

The members screen now renders the Manage header button only when the
user can manage and remove members, which is never the case for an
archived channel. MM-T1719_1 still expected the button to render and
failed on detox-ios and detox-android with "Got: was null". Assert that
neither the Manage button nor the remove controls exist instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Fj5x2Znwhwx94X9g76Hny

---------

Co-authored-by: Pablo Andrés Vélez Vidal <pablovv2012@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-11-05 17:56:33 +05:30
..
android_emulator test(detox): re-submit RF→Detox migration without unintended UI changes (#9847) 2026-06-19 22:44:02 +05:30
e2e Access channel action (#10223) 2026-11-05 17:56:33 +05:30
maestro fix(e2e): stabilize CMT and main Detox/Maestro E2E flakes (#10301) 2026-11-04 13:07:51 +05:30
provision E2E: run shared channels tests on CI, demo plugin v0.12.2 on all full-suite servers (#10267) 2026-10-27 11:42:07 +05:30
scripts fix(e2e): stabilize CMT and main Detox/Maestro E2E flakes (#10301) 2026-11-04 13:07:51 +05:30
shared E2E: run shared channels tests on CI, demo plugin v0.12.2 on all full-suite servers (#10267) 2026-10-27 11:42:07 +05:30
utils ci(e2e): enforce triage verdicts on PR and main E2E lanes by default (#10303) 2026-11-05 14:35:43 +05:30
.babelrc Barebones code for v2 2020-11-17 14:20:58 -03:00
.detoxrc.json test(detox): re-submit RF→Detox migration without unintended UI changes (#9847) 2026-06-19 22:44:02 +05:30
CLAUDE.md test(e2e): close manual release-test gaps (#10125) 2026-09-11 09:48:02 +05:30
create_android_emulator.sh E2E: CI flake fixes; bump Maestro 2.11.0 and Detox 20.51.4 (#10257) 2026-10-19 22:58:41 +05:30
generate_unified_report.js test(detox): re-submit RF→Detox migration without unintended UI changes (#9847) 2026-06-19 22:44:02 +05:30
inject-detox-settings.js Revert "e2e(detox): Rainforest to Detox migration (#9790)" (#9834) 2026-06-15 17:57:01 +02:00
package-lock.json E2E: CI flake fixes; bump Maestro 2.11.0 and Detox 20.51.4 (#10257) 2026-10-19 22:58:41 +05:30
package.json Mm 70564 channel labels use in channel creation (#10146) 2026-10-30 15:03:55 +01:00
README.md test(e2e): close manual release-test gaps (#10125) 2026-09-11 09:48:02 +05:30
save_maestro_zephyr.js feat(e2e): Run e2e against different server version when rc branch is pushed (#9800) 2026-07-07 18:02:13 +05:30
save_report.js fix: stabilize server switch, saved posts, favorites, and related runtime races (#10122) 2026-09-09 00:35:15 +05:30
tsconfig.json Fix/detox hittest cluster (#10023) 2026-08-27 08:58:03 +05:30
webhook_server.js FIX: Correct Android minute interval and UTC+offset date display in datetime fields (#10202) 2026-10-22 15:12:27 -05:00

How to Run Detox Tests

This guide will help you set up and run Detox tests for your project.

Install Dependencies

First, navigate to the root directory of your project and install the necessary dependencies by running:

npm install

navigate to the detox folder and run npm install

Configure your server details

detox/e2e/support/test_config.ts defaults to one local server on port 8065. For iOS, both the test runner and simulator use http://localhost:8065. For Android, the test runner uses http://localhost:8065 while the emulator uses http://10.0.2.2:8065.

If you use a remote server, set the logical site variable to a URL reachable from both the host test runner and the device:

  export SITE_1_URL="https://your-server.example.com"
  export ADMIN_USERNAME="your-username"
  export ADMIN_PASSWORD="your-password"
  export ADMIN_EMAIL="your-email"

You can instead create a detox/.env file:

  # detox/.env
  SITE_1_URL=https://your-server.example.com
  ADMIN_USERNAME=your-username
  ADMIN_PASSWORD=your-password
  ADMIN_EMAIL=your-email@example.com

Note: no need to provide all variables, only the ones that differ.

SITE_2_URL and SITE_3_URL are only needed for tests that add distinct Mattermost servers, such as server_login/server_list.e2e.ts. If they are unset, their URL helpers alias site 1 and tests that require distinct servers are skipped. The five-server ANDROID_SITE_* and IOS_SITE_* topology is assigned by CI and is not required for ordinary local runs.

Android

Build Detox Android App

To build the Detox Android app, navigate to the detox folder and run:

npm run e2e:android-build

The debug apk will be built and available at android/app/build/outputs/apk/debug/app-debug.apk

Run Detox Android Tests

Create emulator

./create_android_emulator.sh SDK_VERSION AVD_NAME

# example ./create_android_emulator.sh 34 pixel_5a_avd
# example ./create_android_emulator.sh 34 pixel_5a_avd --headless
# If we want to see the emulator logs. Run it in debug mode example ./create_android_emulator.sh 34 pixel_5a_avd --debug

To execute the Detox tests on Android, navigate to the detox folder and run:

npm run e2e:android-test

# To run a particular tests

npm run e2e:android-test <path to test file>

Local runs now default to a lower-memory setup so they coexist better with other tools:

  • Detox uses 1 worker unless you set DETOX_MAX_WORKERS.
  • Detox caps Node heap at 4096MB unless you already set NODE_OPTIONS.
  • Android Detox builds cap Gradle heap at 3072MB and use at most 2 Gradle workers unless you override MM_GRADLE_XMX_MB or MM_GRADLE_WORKERS_MAX.
  • Android emulator RAM defaults to 3072MB when created or refreshed; override with MM_ANDROID_EMULATOR_RAM_MB.

iOS

Build iOS Simulator

To build the iOS simulator for Detox, from the project folder run:

npm run e2e:ios-build

This will build the Simulator .zip file at the root folder.

Create a folder named mobile-artifacts at the project root. Move the zip file under mobile-artifacts and unzip it there.

# From project root
mkdir mobile-artifacts

Configure your local

Update detox/.detoxrc.json to specify which device you want to run it. Change:

 "device": {
     "type": "__DEVICE_NAME__",
     "os": "__DEVICE_OS_VERSION__"
 },

to something like:

 "device": {
     "type": "iPhone 17 Pro",
     "os": "iOS 26.4"
 },

To get your values run xcrun simctl list devices to find both the device and iOS version.

Run iOS Tests

To execute the Detox tests on iOS, navigate to the detox folder and run:

npm run e2e:ios-test

# To run a particular tests

npm run e2e:android-test path to test file.

Disabling Password Autofill

from iOS v26 password autofill can interfere with login tests by automatically filling credentials. To disable this feature on your simulator:

# Interactive mode - select simulator from list
npm run e2e:ios-disable-autofill

# Or specify simulator ID directly
npm run e2e:ios-disable-autofill -- --simulator-id SIMULATOR_UDID

When to use this:

  • if using iOS 26 or later
  • Before running iOS E2E tests if you notice password fields being auto-filled
  • When login tests fail unexpectedly due to autofill interference
  • After creating a new iOS simulator for testing

Note: CI environments automatically disable this setting, so this is only needed for local development.

Finding your simulator ID:

xcrun simctl list devices | grep Booted

TIP : For iOS, you can download the simulator from ~Mobile: Test build or ~Release: Mobile Apps channel in the community.

Results

The Local Runs generate artifacts under detox/artifacts/ios-debug-** or detox/artifacts/android-debug-**. You can see the html report, failure screenshot under that folder.

Webhook sidecar (mm_blocks / interactive dialog specs)

The mm_blocks_* and interactive-dialog specs register integrations that the Mattermost server calls back into. detox/webhook_server.js serves those callbacks on :3000, and the server must be able to reach it:

  • Local server (SITE_1_URL=http://localhost:8065): no tunnel needed, the server reaches 127.0.0.1:3000 directly.

    cd detox && npm run start:webhook
    
  • Remote/cloud test server: the server cannot reach your machine, so the sidecar needs a public HTTPS origin. detox/scripts/start_webhook_sidecar.sh starts webhook_server.js and resolves that origin, in priority order:

    Env Behaviour
    WEBHOOK_PUBLIC_BASE_URL Use an already-routable HTTPS origin as-is (named tunnel, ngrok, reverse proxy). Preferred.
    WEBHOOK_PUBLIC_BASE_URL + CLOUDFLARED_TUNNEL_TOKEN Run a named Cloudflare tunnel for that hostname. The token is passed via TUNNEL_TOKEN because argv is world-readable.
    neither Fall back to a trycloudflare.com quick tunnel. Time-boxed and DNS-flaky, so treat it as a last resort.
    cd detox
    SITE_1_URL="https://your-test-server" \
    WEBHOOK_PUBLIC_BASE_URL="https://your-tunnel-hostname" \
    bash scripts/start_webhook_sidecar.sh
    

    Pin a different cloudflared with CLOUDFLARED_VERSION; the script defaults to a known-good release rather than latest.

The script always exits 0 — it exports WEBHOOK_SIDECAR_READY and WEBHOOK_CALLBACKS_REACHABLE instead of failing, and specs that need a webhook fail fast on their own health check. A quick tunnel passes outbound health checks but does not reliably deliver server-to-sidecar callbacks, so it reports WEBHOOK_CALLBACKS_REACHABLE=false.