mirror of
https://github.com/mattermost/mattermost.git
synced 2026-09-01 15:00:08 +08:00
57fe965ac7
* Add Session Attributes system console page shell Register the gated System Console "Session Attributes" subsection backed by a component page that loads the session_attributes property fields, plus a feature discovery upsell. Removes the former config toggles from the UI. Includes display helpers and unit tests. Co-authored-by: Cursor <cursoragent@cursor.com> * Add Session Attributes listing table Render the read-only session attributes table with Display Name, Name (with server-sourced label), derived Type, platform availability icons, TTL, grace period, and status columns, plus loading and empty states. Includes status chip, platform icon, and table unit tests. Co-authored-by: Cursor <cursoragent@cursor.com> * Add Session Attributes row actions and staged save Add a per-row actions menu to tune TTL and grace period via presets and to disable/enable each attribute, with a destructive disable confirmation modal. Edits stage locally and persist on save via a per-field property patch thunk, with an unsaved-changes guard. Includes the patch thunk and component tests. Co-authored-by: Cursor <cursoragent@cursor.com> * Surface session attributes in permission policy editors only Include session attributes in the permission policy attribute picker (both advanced and table editor modes) and group them under a dedicated section, while excluding them from membership and parent access-rule editors via a shared helper. Surface the server rejection message when a membership rule references session attributes. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix lint formatting in session attributes table test Split single-line renderWithContext JSX in session_attributes_table.test.tsx onto multiple lines to satisfy react/jsx-max-props-per-line, matching the existing test formatting convention. Surfaced by the pre-commit ESLint gate. Co-authored-by: Cursor <cursoragent@cursor.com> * Add Session Attributes E2E specs Add Playwright end-to-end coverage for the Session Attributes console page: listing render, staged TTL/grace/enable edits with save persistence, disable confirmation modal, dirty navigation guard with cancel revert, and permission-versus-membership picker polarity. Includes the page object and sidebar wiring. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix playwright-lib build to resolve @/* tsconfig path alias The lib rollup build (@rollup/plugin-typescript) compiled the @/* tsconfig path alias but never rewrote it, so with preserveModules the emitted dist files still imported the unresolved @/ specifier. Node could not load these, failing Playwright config loading for the entire suite (Cannot find module @/ui/components). Add a minimal inline rollup resolveId plugin that maps @/* to the real src file so emitted dist uses correct relative imports. No new dependency required. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix session attribute group identity to use real group id The webapp conflated the property group NAME (session_attributes) with the group's real DB id. The server keys every field under a 26-char group UUID, so the listing page selected fields under the name and always rendered "No session attributes found." on a real server, and the ABAC editors compared field.group_id against the name, which never matched live data. Resolve the group properly instead: - fetchPropertyFields now also dispatches RECEIVED_PROPERTY_GROUP (mirroring the managed-channel-categories flow) so the group name -> id mapping is available, and the listing page selects fields by the resolved group id via getPropertyGroupByName. - Add isSessionAttributeField, keyed on the session object_type, and use it in the ABAC consumers (attribute picker, excludeSessionAttributes, permission policy picker, simulate-access modal). object_type is intrinsic to the autocomplete fields and avoids the name/UUID conflation entirely. - Relax UserPropertyField.group_id to string since the server returns a UUID; the group name is only ever a client-side placeholder for an unsaved field. Harden the unit tests to use realistic group UUIDs distinct from the group name and correct object_type values, so fixtures can no longer pass with a group_id the server never produces. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix SaveChangesPanel footer Cancel to revert in place The admin SaveChangesPanel rendered its onCancel handler through a BlockableButton, which intercepts clicks while navigation is blocked and defers the action via deferNavigation instead of invoking it. On the Session Attributes page this meant footer Cancel never reverted staged edits directly: it re-opened the Discard Changes guard and only reverted if a deferred navigation was later confirmed. BlockableButton is only appropriate for the cancelLink (navigation) path. For an in-place revert handler, wire onCancel to a plain button so it calls the hook cancel() directly, reverting staged edits, clearing the dirty state, releasing setNavigationBlocked, and never showing the discard modal. Repair the page-level jest test to exercise the real footer Cancel and assert direct revert plus nav-guard release without confirming a deferred navigation. Co-authored-by: Cursor <cursoragent@cursor.com> * Merge enabled session attributes into permission policy editors Inject enabled session attributes into the two permission-policy attribute pickers (CEL and table editors) while keeping membership/parent-policy surfaces restricted to long-lived user attributes via excludeSessionAttributes. Adds a useEnabledSessionAttributeFields hook plus the shared mergeSessionAttributes/celPrefixForField helpers so the editors can build CEL across the user.attributes.* and user.session.* namespaces. Addresses two review nits: - Resolve the picked attribute by its unique field id (not bare name) so a session attribute sharing a name with a CPA attribute still maps to object_type 'session' and emits user.session.<name>; the picker also uses id-based DOM ids to avoid collisions. - Make celPrefixForField the single source of CEL-prefix truth by consuming it in rowToCEL instead of inlining the namespace check. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix Session Attributes E2E spec: id-based picker selectors and per-test state isolation The attribute picker menu items are keyed by field id (#attribute-<id>) rather than name, so the permission/membership picker assertions now resolve session attribute ids from the property-fields API and the Department user-attribute id from the CPA fields API instead of targeting stale name-based ids. Add an afterEach that restores every seeded session attribute to a baseline captured at suite start, replacing the per-test finally restores. This keeps the suite order-independent so the listing test "Disabled by default" assertions no longer depend on whether another test has enabled a field first. Co-authored-by: Cursor <cursoragent@cursor.com> * UX Polish * Linting * Removed styled components * Fix session attributes unit tests Co-authored-by: maria.nunez <maria.nunez@mattermost.com> * Fix invalid Sass '&&&' selector breaking production build Co-authored-by: maria.nunez <maria.nunez@mattermost.com> * Stabilize session attributes duration-preset e2e interaction Co-authored-by: maria.nunez <maria.nunez@mattermost.com> * Fix broken session attributes doc link in feature discovery Co-authored-by: maria.nunez <maria.nunez@mattermost.com> * Fix session attributes test type error from non-union group id Co-authored-by: maria.nunez <maria.nunez@mattermost.com> * Revert unnecessary playwright-lib rollup @/* alias resolver @rollup/plugin-typescript already resolves the @/* tsconfig path alias; building with and without the added resolveSrcAlias plugin produces byte-identical dist JS, so the change was a no-op. Co-authored-by: maria.nunez <maria.nunez@mattermost.com> * Allow session-attribute row defaults and resolve table-editor lookups by namespace findFirstAvailableAttributeFromList now treats session attributes as selectable (mirroring AttributeSelectorMenu), so a session-only attribute set no longer fails addRow. The operator menu reads row.attribute_type and the value options match on name + object_type, so a user/session name collision resolves the correct namespace. Co-authored-by: maria.nunez <maria.nunez@mattermost.com> * Type session-attribute platforms on the shared property attrs Add platforms?: string[] to UserPropertyField.attrs so the attribute picker reads it without an unsafe cast, and narrow the platform filter in getSessionAttrs with a type guard. Co-authored-by: maria.nunez <maria.nunez@mattermost.com> * Session Attributes page: surface load errors, propagate read-only, and improve a11y Handle a failed property-fields fetch with an explicit error state instead of leaving the rejection uncaught and showing the empty state. Thread the page's disabled flag through to the row dot menus so read-only admins cannot stage edits. Convey each platform icon's active/inactive state in its accessible name, and document the table border override. Co-authored-by: maria.nunez <maria.nunez@mattermost.com> * SaveChangesPanel: use shared Button for the in-place cancel control Co-authored-by: maria.nunez <maria.nunez@mattermost.com> * Cover fetchPropertyFields group name to uuid mapping Co-authored-by: maria.nunez <maria.nunez@mattermost.com> * E2E: scope session-attribute submenu trigger to its row and document single-field save Co-authored-by: maria.nunez <maria.nunez@mattermost.com> * Comment linting * scss cleanup * linting * PR feedback * PR Feedback. Removed IP + version icons * PR feedback * PR feedback * Fix session attributes table test after IP/Version display types were removed Co-authored-by: maria.nunez <maria.nunez@mattermost.com> * Session Attributes admin console UX fixes - Reduce table row height and shrink-wrap the panel to the table - Reorder LHS sidebar so Session Attributes follows User Attributes - Cap attribute selector popover at 400px max-height with scroll Co-authored-by: Cursor <cursoragent@cursor.com> * Fix native attribute selection by assigning synthetic field IDs The ABAC editors resolve the selected attribute by field ID, but the synthetic native user attribute fields were created without an ID. Every built-in attribute therefore resolved to the first empty-ID field (Email), so no other built-in could be selected. Assign each native field a stable, unique, non-empty ID so id-based resolution works for all built-ins. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
E2E testing for the Mattermost web client
This directory contains the E2E testing code for the Mattermost web client.
How to run locally
For test case development
Please refer to the dedicated developer documentation for instructions.
For pipeline debugging
The E2E testing pipeline's scripts depend on the following tools being installed on your system: docker, docker-compose, make, git, jq, node, and some common utilities (coreutils, findutils, bash, awk, sed, grep)
Instructions, tl;dr: create a local branch with your E2E test changes, then open a PR to the mattermost-server repo targeting the master branch (so that CI will produce the image that docker-compose needs), then run make in this directory.
Instructions, detailed:
- (optional, undefined variables are set to sane defaults) Create the
.ci/envfile, and populate it with the variables you need out of the following list:
SERVER: eitheronprem(default) orcloud.CWS_URL(mandatory whenSERVER=cloud, only used in such case): when spinning up a cloud-like test server that communicates with a test instance of a customer web server.TEST: eithercypress(default),playwright, ornone(to avoid creating the cypress/playwright sidecar containers, e.g. if you only want to launch a server instance)ENABLED_DOCKER_SERVICES: a space-separated list of services to start alongside the server. Default topostgres inbucket, for smoke test purposes and for lightweight and faster start-up time. Depending on the test requirement being worked on, you may want to override as needed, as such:- Cypress full tests require all services to be running:
postgres inbucket minio openldap elasticsearch keycloak. - Cypress smoke tests require only the following:
postgres inbucket. - Playwright full tests require only the following:
postgres inbucket.
- Cypress full tests require all services to be running:
- The following variables, will be passed over to the server container:
MM_LICENSE(no enterprise features will be available if this is unset; required whenSERVER=cloud), and the explodedMM_ENV(a comma-separated list of env var specifications) - The following variables, which will be passed over to the cypress container:
BRANCH,BUILD_ID,CI_BASE_URL,BROWSER,AUTOMATION_DASHBOARD_URLandAUTOMATION_DASHBOARD_TOKEN - The
SERVER_IMAGEvariable can also be set if you want to select a custom mattermost-server image. If not specified, the value of theSERVER_IMAGE_DEFAULTvariable defined in file.ci/.e2ercis used. - The
TEST_FILTERvariable can also be set, to customize which tests you want Cypress/Playwright to run. If not specified, only the smoke tests will run- Its format depends on which tool is used: for Cypress, please check the
e2e-tests/cypress/run_tests.jsfile for details. For Playwright, it can simply be populated with arguments you want to give to theplaywright testcommand.
- Its format depends on which tool is used: for Cypress, please check the
- More variables may be required to configure reporting and cloud interactions. Check the content of the
.ci/report.*.shand.ci/server.cloud_*.shscripts for reference.
- (optional)
make start-dashboard && make generate-test-cycle: start the automation dashboard in the background, and initiate a test cycle on it, for the givenBUILD_ID
- NB: the
BUILD_IDvalue should stay the same across themake generate-test-cyclecommand, and the subsequentmake(see next step). If you need to initiate a new test cycle on the same dashboard, you'll need to change theBUILD_IDvalue and rerun bothmake generate-test-cycleandmake. - Note that part of the dashboard functionality assumes the
BUILD_IDto have a certain format (see here for details). This is not relevant for local running, but it's important to note in the testing pipelines. - This also automatically sets the
AUTOMATION_DASHBOARD_URLandAUTOMATION_DASHBOARD_TOKENvariables for the cypress container - Note that if you run the dashboard locally, but also specify other
AUTOMATION_DASHBOARD_*variables in your.ci/envfile, the latter variables will take precedence. - The dashboard is used for orchestrating specs with parallel test runs and is typically used in CI.
- Only Cypress is currently using the dashboard; Playwright is not.
make: start and prepare the server, then run the Cypress smoke tests
- You can track the progress of the run in the
http://localhost:4000/cyclesdashboard if you launched it locally - For
SERVER=cloudruns, you'll need to first create a cloud customer against the specifiedCWS_URLservice by runningmake cloud-init. The user isn't automatically removed, and may be reused across multiple runs until you runmake cloud-teardownto delete it. - If you want to run the Playwright tests instead of the Cypress ones, you can run
TEST=playwright make - If you just want to run a local server instance, without any further testing, you can run
TEST=none make - If you're using the automation dashboard, you have the option of sharding the E2E test run: you can launch the
makecommand in parallel on different machines (NB: you must use the sameBUILD_IDandBRANCHvalues that you used formake generate-test-cycle) to distribute running the test cases across them. When doing this, you should also set on each machine theCI_BASE_URLvariable to a value that uniquely identifies the instance wheremakeis running. - This script will also parse the local test results, and write a
e2e-tests/${TEST}/results/summary.jsonfile containing the following keys:passed,failedandfailed_expected(the total number of testcases that were run is the sum of these three numbers)
make stop: tears down the server (and the dashboard, if running)
- This will stop and cleanup all of the E2E testing containers, including the database and its persistent volume.
- This also implicitly runs
make clean, which also removes any generated environment or docker-compose files.
Notes:
- Setting a variable in
.ci/envis functionally equivalent to exporting variables in your current shell's environment, before invoking the makefile. - The
.ci/.env.*files are auto-generated by the pipeline scripts and aren't meant to be modified manually. The only file you should edit to control the containers' environment is.ci/env, as specified in the instructions above. - All of the variables in
.ci/envmust be set before themake generate-servercommand is run (or, if using the dashboard, before themake generate-test-cyclecommand). Modifying that file afterward has no effect because the containers' env files are generated in that step. - If you restart the dashboard at any point, you must also restart the server containers, so that it picks up the new IP of the dashboard from the newly generated
.env.dashboardfile - If new variables need to be passed to any of the containers, here are the general principles to follow when deciding where to populate it:
- If their value is fixed (e.g. a static server configuration), these may be simply added to the
docker_compose_generator.shfile, to the appropriate container. - If you need to introduce variables that you want to control from
.ci/env: you need to update the scripts under the.ci/dir and configure them to write the new variables' values over to the appropriate.env.*file. In particular, avoid defining variables that depend on other variables within the docker-compose override files: this is to ensure uniformity in their availability and simplifies the question of what container has access to which variable considerably. - Exceptions are of course accepted wherever it makes sense (e.g. if you need to group variables based on some common functionality)
- If their value is fixed (e.g. a static server configuration), these may be simply added to the
- The
reportMake target is meant for internal usage. Usage and variables are documented in the respective scripts. make start-serverwon't cleanup containers that don't change across runs. This means that you can use it to emulate a Mattermost server upgrade while retaining your database data by simply changing theSERVER_IMAGEvariable on your machine, and then re-runningmake start-server. But this also means that if you want to run a clean local environment, you may have to manually runmake stopto cleanup any running containers and their volumes, which include e.g. the database.
For code changes:
make fmt-cito format and check yaml files and shell scripts.
For test stressing an E2E testcase
For Cypress:
- Enter the
cypress/subdirectory - Identify which test files you want to run, and how many times each. For instance: suppose you want to run
create_a_team_spec.jsanddemoted_user_spec.js(which you can locate with thefindcommand, undercypress/tests/), each run 3 times - Run the chosen testcases the desired amount of times:
node run_tests.js --include-file=create_a_team_spec.js,demoted_user_spec.js --invert --stress-test-count=3
- Your system needs to be setup for Cypress usage, to be able to run this command. Refer to the E2E testing developer documentation for this.
- The
cypress/results/testPasses.jsonfile will count, for each of the testfiles, how many times it was run, and how many times each of the testcases contained in it passed. If the attempts and passes numbers do not match, that specific testcase may be flaky.
For Playwright: WIP