From 4539cf73fb17e634253d429c7d24969aca62bc62 Mon Sep 17 00:00:00 2001 From: Sudheer Date: Fri, 12 Jun 2026 20:11:21 +0530 Subject: [PATCH 1/3] Fix: Scroll pop caused because of delayed correction. (#36879) * Fix: Scroll pop caused because of delayed correction. * Debounce on resize Observer is causing a delayed scroll correction. causing scroll pop. Can be seen on a recurring visit to channel or on opening RHS. * Remove debounce from test * Remove the function of debounce * Refactor comment in list_item.tsx Removed debounce comment about the observer's functionality. --- .../list_item.test.tsx | 9 ------- .../dynamic_virtualized_list/list_item.tsx | 26 +++++-------------- 2 files changed, 6 insertions(+), 29 deletions(-) diff --git a/webapp/channels/src/components/dynamic_virtualized_list/list_item.test.tsx b/webapp/channels/src/components/dynamic_virtualized_list/list_item.test.tsx index 8d2de193937..71c2cae463a 100644 --- a/webapp/channels/src/components/dynamic_virtualized_list/list_item.test.tsx +++ b/webapp/channels/src/components/dynamic_virtualized_list/list_item.test.tsx @@ -18,15 +18,6 @@ jest.mock('./list_item_size_observer', () => { }; }); -jest.mock('lodash/debounce', () => { - return jest.fn((fn) => { - const debouncedFn = (...args: any[]) => fn(...args); - debouncedFn.cancel = jest.fn(); - debouncedFn.flush = jest.fn(); - return debouncedFn; - }); -}); - import ListItem from './list_item'; describe('ListItem', () => { diff --git a/webapp/channels/src/components/dynamic_virtualized_list/list_item.tsx b/webapp/channels/src/components/dynamic_virtualized_list/list_item.tsx index e6cad5bccfc..6003309f1f1 100644 --- a/webapp/channels/src/components/dynamic_virtualized_list/list_item.tsx +++ b/webapp/channels/src/components/dynamic_virtualized_list/list_item.tsx @@ -1,14 +1,11 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import debounce from 'lodash/debounce'; import type {ReactNode} from 'react'; import React, {memo, useLayoutEffect, useRef} from 'react'; import {ListItemSizeObserver} from './list_item_size_observer'; -const RESIZE_DEBOUNCE_TIME = 200; // in ms - const listItemSizeObserver = ListItemSizeObserver.getInstance(); export interface Props { @@ -47,31 +44,21 @@ const ListItem = (props: Props) => { props.onHeightChange(props.itemId, newHeight, false); }, [props.itemId]); - // This effects adds the observer which calls height change callback debounced + // This effects adds the observer which calls height change callback useLayoutEffect(() => { - const debouncedOnHeightChange = debounce((changedHeight: number) => { - // Check if component is still mounted as it may have been - // unmounted by the time the debounced function is called + function itemRowSizeObserverCallback(changedHeight: number) { if (!rowRef.current) { return; } + if (changedHeight !== heightRef.current) { // If width of container has changed then scroll bar position will be out of sync // so we need to force a scroll correction - const forceScrollCorrection = rowRef.current.offsetWidth !== widthRef.current; - - heightRef.current = changedHeight; - - props.onHeightChange(props.itemId, changedHeight, forceScrollCorrection); - }, RESIZE_DEBOUNCE_TIME); + const forceScrollCorrection = rowRef.current.offsetWidth !== widthRef.current; - function itemRowSizeObserverCallback(changedHeight: number) { - if (!rowRef.current) { - return; - } + heightRef.current = changedHeight; - if (changedHeight !== heightRef.current) { - debouncedOnHeightChange(changedHeight); + props.onHeightChange(props.itemId, changedHeight, forceScrollCorrection); } } @@ -85,7 +72,6 @@ const ListItem = (props: Props) => { return () => { // We remove the observer here from a row cleanupSizeObserver?.(); - debouncedOnHeightChange?.cancel(); props.onUnmount(props.itemId, indexRef.current); }; }, [props.itemId]); From aad6c8afe846a9e3c3709fdea57dd7706ea605d4 Mon Sep 17 00:00:00 2001 From: Jesse Hallam Date: Fri, 12 Jun 2026 12:03:42 -0300 Subject: [PATCH 2/3] [MM-69228] Default the CJKSearch feature flag to true (#37032) --- e2e-tests/playwright/lib/src/server/default_config.ts | 2 +- server/public/model/feature_flags.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e-tests/playwright/lib/src/server/default_config.ts b/e2e-tests/playwright/lib/src/server/default_config.ts index 89c4de9f2a9..99337eb3cbd 100644 --- a/e2e-tests/playwright/lib/src/server/default_config.ts +++ b/e2e-tests/playwright/lib/src/server/default_config.ts @@ -788,7 +788,7 @@ const defaultServerConfig: AdminConfig = { EnableAIRecaps: false, ClassificationMarkings: true, IntegratedBoards: false, - CJKSearch: false, + CJKSearch: true, ManagedChannelCategories: false, MobileEphemeralMode: true, }, diff --git a/server/public/model/feature_flags.go b/server/public/model/feature_flags.go index c840e8c650a..d1a1c55ed68 100644 --- a/server/public/model/feature_flags.go +++ b/server/public/model/feature_flags.go @@ -202,7 +202,7 @@ func (f *FeatureFlags) SetDefaults() { f.IntegratedBoards = false - f.CJKSearch = false + f.CJKSearch = true f.AggregatePluginMetrics = false From 20c4cc42b2ee5b33b463189503ec146b550665bf Mon Sep 17 00:00:00 2001 From: Maria A Nunez Date: Fri, 12 Jun 2026 11:45:21 -0400 Subject: [PATCH 3/3] Seed display names for session attribute fields (#37033) * Seed display names for session attribute fields Co-authored-by: maria.nunez * Extract session attribute display names into named constants Co-authored-by: maria.nunez --------- Co-authored-by: Cursor Agent --- server/channels/api4/user_test.go | 41 ++++++++++++ server/channels/app/migrations.go | 1 + server/channels/app/migrations_test.go | 2 + server/public/model/session_attributes.go | 67 +++++++++++++------ .../public/model/session_attributes_test.go | 30 +++++++++ 5 files changed, 119 insertions(+), 22 deletions(-) diff --git a/server/channels/api4/user_test.go b/server/channels/api4/user_test.go index 708abb31994..c185f00bf38 100644 --- a/server/channels/api4/user_test.go +++ b/server/channels/api4/user_test.go @@ -10693,6 +10693,47 @@ func TestGetSessionAttributesManifest(t *testing.T) { CheckOKStatus(t, resp) require.Empty(t, manifest) }) + + t.Run("enabled field carries its seeded display name", func(t *testing.T) { + const desktopUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Mattermost/3.7.1 Chrome/56.0.2924.87 Electron/1.6.11 Safari/537.36" + + group, appErr := th.App.GetPropertyGroup(th.Context, model.SessionAttributesPropertyGroupName) + require.Nil(t, appErr) + fields, appErr := th.App.SearchPropertyFields(th.Context, group.ID, model.PropertyFieldSearchOpts{PerPage: 100}) + require.Nil(t, appErr) + + var hardwareField *model.PropertyField + for _, field := range fields { + if field.Name == model.SessionAttributesPropertyFieldHardwareID { + hardwareField = field + break + } + } + require.NotNil(t, hardwareField) + if hardwareField.Attrs == nil { + hardwareField.Attrs = model.StringInterface{} + } + hardwareField.Attrs["enabled"] = true + _, _, appErr = th.App.UpdatePropertyFields(th.Context, group.ID, []*model.PropertyField{hardwareField}, true, "") + require.Nil(t, appErr) + + th.Client.HTTPHeader = map[string]string{"User-Agent": desktopUserAgent} + defer func() { th.Client.HTTPHeader = nil }() + + manifest, resp, err := th.Client.GetSessionAttributesManifest(context.Background()) + require.NoError(t, err) + CheckOKStatus(t, resp) + + var hardwareEntry *model.SessionAttributeManifestEntry + for _, entry := range manifest { + if entry.Name == model.SessionAttributesPropertyFieldHardwareID { + hardwareEntry = entry + break + } + } + require.NotNil(t, hardwareEntry) + require.Equal(t, model.SessionAttributesDisplayNameHardwareID, hardwareEntry.DisplayName) + }) } // setSessionAttributeDeviceID configures the test client to send a desktop diff --git a/server/channels/app/migrations.go b/server/channels/app/migrations.go index 906a323bf16..abbaa17b589 100644 --- a/server/channels/app/migrations.go +++ b/server/channels/app/migrations.go @@ -892,6 +892,7 @@ func (s *Server) seedSessionAttributeFields(groupID string) error { if current, ok := existingByName[expected.Name]; ok { current.Type = expected.Type current.Attrs["platforms"] = expected.Attrs["platforms"] + current.Attrs[model.SAAttrDisplayName] = expected.Attrs[model.SAAttrDisplayName] current.ObjectType = expected.ObjectType current.TargetType = expected.TargetType current.Protected = expected.Protected diff --git a/server/channels/app/migrations_test.go b/server/channels/app/migrations_test.go index a0ca8e4a87f..789d6bd3817 100644 --- a/server/channels/app/migrations_test.go +++ b/server/channels/app/migrations_test.go @@ -387,6 +387,7 @@ func TestDoSetupSessionAttributesProperties(t *testing.T) { require.NotNil(t, field.PermissionValues) require.Equal(t, model.PermissionLevelSysadmin, *field.PermissionValues, "field %q permission_values", field.Name) require.Equal(t, false, field.Attrs["enabled"], "field %q must seed disabled", field.Name) + require.NotEmpty(t, field.Attrs[model.SAAttrDisplayName], "field %q must seed a display name", field.Name) } ipField := fieldsByName[model.SessionAttributesPropertyFieldIPAddress] @@ -401,6 +402,7 @@ func TestDoSetupSessionAttributesProperties(t *testing.T) { // The typed attrs must survive the DB round trip so the app reads back what it seeded. saField, err := model.SAFieldFromPropertyField(networkField) require.NoError(t, err) + require.Equal(t, model.SessionAttributesDisplayNameNetworkInterfaceType, saField.Attrs.DisplayName) require.Equal(t, model.SessionAttributeDefaultTTLNetworkIdentity, saField.Attrs.TTLSeconds) require.Equal(t, model.SessionAttributeDefaultGraceNetworkIdentity, saField.Attrs.GracePeriodSeconds) require.ElementsMatch(t, diff --git a/server/public/model/session_attributes.go b/server/public/model/session_attributes.go index c4a24c8fad6..e3796ea4b96 100644 --- a/server/public/model/session_attributes.go +++ b/server/public/model/session_attributes.go @@ -40,6 +40,28 @@ const ( SessionAttributesPropertyFieldIPAddress = "ip_address" ) +const ( + SessionAttributesDisplayNameClientIPAddress = "Client IP address" + SessionAttributesDisplayNameNetworkInterfaceType = "Network interface type" + SessionAttributesDisplayNameVPNActive = "VPN active" + SessionAttributesDisplayNameSSID = "SSID" + SessionAttributesDisplayNameTLSDDeviceID = "TLS device ID" + SessionAttributesDisplayNameClientDeviceID = "Device ID" + SessionAttributesDisplayNameMDMEnrolled = "MDM enrolled" + SessionAttributesDisplayNameHardwareID = "Hardware ID" + SessionAttributesDisplayNameOSPlatform = "OS platform" + SessionAttributesDisplayNameOSVersion = "OS version" + SessionAttributesDisplayNameClientVersion = "Client version" + SessionAttributesDisplayNameJailbreakDetected = "Jailbreak detected" + SessionAttributesDisplayNameServerFQDN = "Server FQDN" + SessionAttributesDisplayNameClientFQDN = "Client FQDN" + SessionAttributesDisplayNameUserAgentPlatform = "User agent platform" + SessionAttributesDisplayNameUserAgentOS = "User agent OS" + SessionAttributesDisplayNameUserAgentBrowserName = "User agent browser name" + SessionAttributesDisplayNameUserAgentBrowserVersion = "User agent browser version" + SessionAttributesDisplayNameIPAddress = "IP address" +) + const ( SAAttrEnabled = "enabled" SAAttrPlatforms = "platforms" @@ -184,8 +206,9 @@ func sessionAttributeFieldAttrs(platforms []string, ttl, grace int) StringInterf } } -func sessionAttributeField(groupID, name string, fieldType PropertyFieldType, platforms []string, ttl, grace int, extraAttrs StringInterface) *PropertyField { +func sessionAttributeField(groupID, name, displayName string, fieldType PropertyFieldType, platforms []string, ttl, grace int, extraAttrs StringInterface) *PropertyField { attrs := sessionAttributeFieldAttrs(platforms, ttl, grace) + attrs[SAAttrDisplayName] = displayName maps.Copy(attrs, extraAttrs) return &PropertyField{ GroupID: groupID, @@ -217,9 +240,9 @@ func SessionAttributeSystemFields(groupID string) []*PropertyField { } return []*PropertyField{ - sessionAttributeField(groupID, SessionAttributesPropertyFieldIPAddress, PropertyFieldTypeText, allPlatforms, SessionAttributeDefaultTTLNetworkIdentity, SessionAttributeDefaultGraceNetworkIdentity, nil), - sessionAttributeField(groupID, SessionAttributesPropertyFieldClientIPAddress, PropertyFieldTypeText, clientsOnly, SessionAttributeDefaultTTLNetworkIdentity, SessionAttributeDefaultGraceNetworkIdentity, nil), - sessionAttributeField(groupID, SessionAttributesPropertyFieldNetworkInterfaceType, PropertyFieldTypeSelect, clientsOnly, SessionAttributeDefaultTTLNetworkIdentity, SessionAttributeDefaultGraceNetworkIdentity, StringInterface{ + sessionAttributeField(groupID, SessionAttributesPropertyFieldIPAddress, SessionAttributesDisplayNameIPAddress, PropertyFieldTypeText, allPlatforms, SessionAttributeDefaultTTLNetworkIdentity, SessionAttributeDefaultGraceNetworkIdentity, nil), + sessionAttributeField(groupID, SessionAttributesPropertyFieldClientIPAddress, SessionAttributesDisplayNameClientIPAddress, PropertyFieldTypeText, clientsOnly, SessionAttributeDefaultTTLNetworkIdentity, SessionAttributeDefaultGraceNetworkIdentity, nil), + sessionAttributeField(groupID, SessionAttributesPropertyFieldNetworkInterfaceType, SessionAttributesDisplayNameNetworkInterfaceType, PropertyFieldTypeSelect, clientsOnly, SessionAttributeDefaultTTLNetworkIdentity, SessionAttributeDefaultGraceNetworkIdentity, StringInterface{ PropertyFieldAttributeOptions: []map[string]string{ {"name": "wifi"}, {"name": "ethernet"}, @@ -229,23 +252,23 @@ func SessionAttributeSystemFields(groupID string) []*PropertyField { {"name": "other"}, }, }), - sessionAttributeField(groupID, SessionAttributesPropertyFieldVPNActive, PropertyFieldTypeSelect, clientsOnly, SessionAttributeDefaultTTLNetworkIdentity, SessionAttributeDefaultGraceNetworkIdentity, boolSelectOptions), - sessionAttributeField(groupID, SessionAttributesPropertyFieldSSID, PropertyFieldTypeText, clientsOnly, SessionAttributeDefaultTTLNetworkIdentity, SessionAttributeDefaultGraceNetworkIdentity, nil), - - sessionAttributeField(groupID, SessionAttributesPropertyFieldMDMEnrolled, PropertyFieldTypeSelect, clientsOnly, SessionAttributeDefaultTTLPosture, SessionAttributeDefaultGracePosture, boolSelectOptions), - sessionAttributeField(groupID, SessionAttributesPropertyFieldJailbreakDetected, PropertyFieldTypeSelect, mobileOnly, SessionAttributeDefaultTTLPosture, SessionAttributeDefaultGracePosture, boolSelectOptions), - sessionAttributeField(groupID, SessionAttributesPropertyFieldOSPlatform, PropertyFieldTypeText, clientsOnly, SessionAttributeDefaultTTLPosture, SessionAttributeDefaultGracePosture, nil), - sessionAttributeField(groupID, SessionAttributesPropertyFieldOSVersion, PropertyFieldTypeText, clientsOnly, SessionAttributeDefaultTTLPosture, SessionAttributeDefaultGracePosture, nil), - sessionAttributeField(groupID, SessionAttributesPropertyFieldClientVersion, PropertyFieldTypeText, clientsOnly, SessionAttributeDefaultTTLPosture, SessionAttributeDefaultGracePosture, nil), - - sessionAttributeField(groupID, SessionAttributesPropertyFieldUserAgentPlatform, PropertyFieldTypeText, allPlatforms, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), - sessionAttributeField(groupID, SessionAttributesPropertyFieldUserAgentOS, PropertyFieldTypeText, allPlatforms, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), - sessionAttributeField(groupID, SessionAttributesPropertyFieldUserAgentBrowserName, PropertyFieldTypeText, allPlatforms, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), - sessionAttributeField(groupID, SessionAttributesPropertyFieldUserAgentBrowserVersion, PropertyFieldTypeText, allPlatforms, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), - sessionAttributeField(groupID, SessionAttributesPropertyFieldTLSDDeviceID, PropertyFieldTypeText, desktopBrowser, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), - sessionAttributeField(groupID, SessionAttributesPropertyFieldClientDeviceID, PropertyFieldTypeText, mobileOnly, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), - sessionAttributeField(groupID, SessionAttributesPropertyFieldHardwareID, PropertyFieldTypeText, desktopOnly, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), - sessionAttributeField(groupID, SessionAttributesPropertyFieldServerFQDN, PropertyFieldTypeText, clientsOnly, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), - sessionAttributeField(groupID, SessionAttributesPropertyFieldClientFQDN, PropertyFieldTypeText, desktopOnly, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), + sessionAttributeField(groupID, SessionAttributesPropertyFieldVPNActive, SessionAttributesDisplayNameVPNActive, PropertyFieldTypeSelect, clientsOnly, SessionAttributeDefaultTTLNetworkIdentity, SessionAttributeDefaultGraceNetworkIdentity, boolSelectOptions), + sessionAttributeField(groupID, SessionAttributesPropertyFieldSSID, SessionAttributesDisplayNameSSID, PropertyFieldTypeText, clientsOnly, SessionAttributeDefaultTTLNetworkIdentity, SessionAttributeDefaultGraceNetworkIdentity, nil), + + sessionAttributeField(groupID, SessionAttributesPropertyFieldMDMEnrolled, SessionAttributesDisplayNameMDMEnrolled, PropertyFieldTypeSelect, clientsOnly, SessionAttributeDefaultTTLPosture, SessionAttributeDefaultGracePosture, boolSelectOptions), + sessionAttributeField(groupID, SessionAttributesPropertyFieldJailbreakDetected, SessionAttributesDisplayNameJailbreakDetected, PropertyFieldTypeSelect, mobileOnly, SessionAttributeDefaultTTLPosture, SessionAttributeDefaultGracePosture, boolSelectOptions), + sessionAttributeField(groupID, SessionAttributesPropertyFieldOSPlatform, SessionAttributesDisplayNameOSPlatform, PropertyFieldTypeText, clientsOnly, SessionAttributeDefaultTTLPosture, SessionAttributeDefaultGracePosture, nil), + sessionAttributeField(groupID, SessionAttributesPropertyFieldOSVersion, SessionAttributesDisplayNameOSVersion, PropertyFieldTypeText, clientsOnly, SessionAttributeDefaultTTLPosture, SessionAttributeDefaultGracePosture, nil), + sessionAttributeField(groupID, SessionAttributesPropertyFieldClientVersion, SessionAttributesDisplayNameClientVersion, PropertyFieldTypeText, clientsOnly, SessionAttributeDefaultTTLPosture, SessionAttributeDefaultGracePosture, nil), + + sessionAttributeField(groupID, SessionAttributesPropertyFieldUserAgentPlatform, SessionAttributesDisplayNameUserAgentPlatform, PropertyFieldTypeText, allPlatforms, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), + sessionAttributeField(groupID, SessionAttributesPropertyFieldUserAgentOS, SessionAttributesDisplayNameUserAgentOS, PropertyFieldTypeText, allPlatforms, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), + sessionAttributeField(groupID, SessionAttributesPropertyFieldUserAgentBrowserName, SessionAttributesDisplayNameUserAgentBrowserName, PropertyFieldTypeText, allPlatforms, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), + sessionAttributeField(groupID, SessionAttributesPropertyFieldUserAgentBrowserVersion, SessionAttributesDisplayNameUserAgentBrowserVersion, PropertyFieldTypeText, allPlatforms, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), + sessionAttributeField(groupID, SessionAttributesPropertyFieldTLSDDeviceID, SessionAttributesDisplayNameTLSDDeviceID, PropertyFieldTypeText, desktopBrowser, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), + sessionAttributeField(groupID, SessionAttributesPropertyFieldClientDeviceID, SessionAttributesDisplayNameClientDeviceID, PropertyFieldTypeText, mobileOnly, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), + sessionAttributeField(groupID, SessionAttributesPropertyFieldHardwareID, SessionAttributesDisplayNameHardwareID, PropertyFieldTypeText, desktopOnly, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), + sessionAttributeField(groupID, SessionAttributesPropertyFieldServerFQDN, SessionAttributesDisplayNameServerFQDN, PropertyFieldTypeText, clientsOnly, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), + sessionAttributeField(groupID, SessionAttributesPropertyFieldClientFQDN, SessionAttributesDisplayNameClientFQDN, PropertyFieldTypeText, desktopOnly, SessionAttributeDefaultTTLIdentity, SessionAttributeDefaultGraceIdentity, nil), } } diff --git a/server/public/model/session_attributes_test.go b/server/public/model/session_attributes_test.go index 5a971fd4db3..395d1557dd3 100644 --- a/server/public/model/session_attributes_test.go +++ b/server/public/model/session_attributes_test.go @@ -33,6 +33,36 @@ func TestSAFieldFromPropertyField(t *testing.T) { assert.Equal(t, "VPN Active", saField.Attrs.DisplayName) } +func TestSessionAttributeSystemFieldsDisplayNames(t *testing.T) { + fields := SessionAttributeSystemFields("group-id") + require.NotEmpty(t, fields) + + displayNamesByName := make(map[string]string, len(fields)) + for _, field := range fields { + saField, err := SAFieldFromPropertyField(field) + require.NoError(t, err) + require.NotEmpty(t, saField.Attrs.DisplayName, "field %q must have a display name", field.Name) + displayNamesByName[field.Name] = saField.Attrs.DisplayName + } + + expected := map[string]string{ + SessionAttributesPropertyFieldClientIPAddress: SessionAttributesDisplayNameClientIPAddress, + SessionAttributesPropertyFieldNetworkInterfaceType: SessionAttributesDisplayNameNetworkInterfaceType, + SessionAttributesPropertyFieldVPNActive: SessionAttributesDisplayNameVPNActive, + SessionAttributesPropertyFieldSSID: SessionAttributesDisplayNameSSID, + SessionAttributesPropertyFieldClientDeviceID: SessionAttributesDisplayNameClientDeviceID, + SessionAttributesPropertyFieldHardwareID: SessionAttributesDisplayNameHardwareID, + SessionAttributesPropertyFieldMDMEnrolled: SessionAttributesDisplayNameMDMEnrolled, + SessionAttributesPropertyFieldClientVersion: SessionAttributesDisplayNameClientVersion, + SessionAttributesPropertyFieldOSPlatform: SessionAttributesDisplayNameOSPlatform, + SessionAttributesPropertyFieldOSVersion: SessionAttributesDisplayNameOSVersion, + SessionAttributesPropertyFieldJailbreakDetected: SessionAttributesDisplayNameJailbreakDetected, + } + for name, displayName := range expected { + assert.Equal(t, displayName, displayNamesByName[name], "display name for %q", name) + } +} + func TestSAFieldEnabledForPlatform(t *testing.T) { field := &PropertyField{ Name: SessionAttributesPropertyFieldVPNActive,