diff --git a/app/utils/server/index.test.ts b/app/utils/server/index.test.ts new file mode 100644 index 0000000000..9aa08ef7d2 --- /dev/null +++ b/app/utils/server/index.test.ts @@ -0,0 +1,268 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {Alert} from 'react-native'; + +import {Preferences, Screens, Sso} from '@constants'; +import {dismissBottomSheet, showModal} from '@screens/navigation'; +import {getIntlShape} from '@utils/general'; +import {isMinimumServerVersion} from '@utils/helpers'; + +import { + addNewServer, + alertServerAlreadyConnected, + alertServerError, + alertServerLogout, + alertServerRemove, + editServer, + isSupportedServer, + loginOptions, + loginToServer, + semverFromServerVersion, + sortServersByDisplayName, + unsupportedServer, +} from './index'; + +import type {ServersModel} from '@database/models/app'; +import type {DeepLinkWithData} from '@typings/launch'; + +jest.mock('@utils/helpers', () => ({ + isMinimumServerVersion: jest.fn(), + isTablet: jest.fn(() => true), +})); + +jest.mock('@screens/navigation', () => ({ + dismissBottomSheet: jest.fn(), + showModal: jest.fn(), +})); + +jest.mock('@components/compass_icon', () => ({ + getImageSourceSync: jest.fn(), +})); + +jest.mock('@utils/url', () => ({ + tryOpenURL: jest.fn(), +})); + +describe('unsupportedServer', () => { + const intl = getIntlShape(); + + it('should show the alert for sysadmin', () => { + const alert = jest.spyOn(Alert, 'alert'); + unsupportedServer('Default Server', true, intl); + expect(alert?.mock?.calls?.[0]?.[2]?.length).toBe(2); + }); + + it('should not show the alert for team admin / user', () => { + const alert = jest.spyOn(Alert, 'alert'); + unsupportedServer('Default Server', false, intl); + expect(alert).not.toHaveBeenCalled(); + }); +}); + +describe('isSupportedServer', () => { + it('should return true for supported server version', () => { + (isMinimumServerVersion as jest.Mock).mockReturnValue(true); + const result = isSupportedServer('5.0.0'); + expect(result).toBe(true); + }); + + it('should return false for unsupported server version', () => { + (isMinimumServerVersion as jest.Mock).mockReturnValue(false); + const result = isSupportedServer('4.0.0'); + expect(result).toBe(false); + }); +}); + +describe('semverFromServerVersion', () => { + it('should return semver string for valid version', () => { + const result = semverFromServerVersion('5.0.0'); + expect(result).toBe('5.0.0'); + }); + + it('should return undefined for invalid version', () => { + const result = semverFromServerVersion(''); + expect(result).toBeUndefined(); + }); +}); + +describe('addNewServer', () => { + it('should call dismissBottomSheet and showModal', async () => { + const theme = Preferences.THEMES.denim; + const serverUrl = 'https://server.com'; + const displayName = 'Server'; + const deepLinkProps = {type: 'channel', url: 'https://mattermost.com'} as DeepLinkWithData; + + await addNewServer(theme, serverUrl, displayName, deepLinkProps); + + expect(dismissBottomSheet).toHaveBeenCalled(); + expect(showModal).toHaveBeenCalledWith(Screens.SERVER, '', expect.any(Object), expect.any(Object)); + }); +}); + +describe('loginOptions', () => { + it('should return correct login options', () => { + const config = { + EnableSaml: 'true', + EnableSignUpWithGitLab: 'true', + EnableSignUpWithGoogle: 'true', + EnableSignUpWithOffice365: 'true', + EnableSignUpWithOpenId: 'true', + EnableLdap: 'true', + EnableSignInWithEmail: 'true', + EnableSignInWithUsername: 'true', + Version: '5.0.0', + } as ClientConfig; + const license = { + IsLicensed: 'true', + SAML: 'true', + Office365OAuth: 'true', + LDAP: 'true', + } as ClientLicense; + + const result = loginOptions(config, license); + + expect(result).toEqual({ + hasLoginForm: true, + ssoOptions: { + [Sso.SAML]: {enabled: true, text: undefined}, + [Sso.GITLAB]: {enabled: true}, + [Sso.GOOGLE]: {enabled: true}, + [Sso.OFFICE365]: {enabled: true}, + [Sso.OPENID]: {enabled: true, text: undefined}, + }, + enabledSSOs: [Sso.SAML, Sso.GITLAB, Sso.GOOGLE, Sso.OFFICE365, Sso.OPENID], + numberSSOs: 5, + }); + }); +}); +describe('loginToServer', () => { + const theme = Preferences.THEMES.denim; + const serverUrl = 'https://server.com'; + const displayName = 'Server'; + const config = { + EnableSaml: 'true', + EnableSignUpWithGitLab: 'false', + EnableSignUpWithGoogle: 'false', + EnableSignUpWithOffice365: 'false', + EnableSignUpWithOpenId: 'false', + EnableLdap: 'false', + EnableSignInWithEmail: 'true', + EnableSignInWithUsername: 'true', + Version: '5.0.0', + } as ClientConfig; + const license = { + IsLicensed: 'true', + SAML: 'true', + Office365OAuth: 'true', + LDAP: 'true', + } as ClientLicense; + + it('should call dismissBottomSheet and showModal with LOGIN screen', async () => { + await loginToServer(theme, serverUrl, displayName, config, license); + + expect(dismissBottomSheet).toHaveBeenCalled(); + expect(showModal).toHaveBeenCalledWith(Screens.LOGIN, '', expect.any(Object), expect.any(Object)); + }); + + /* Commented out for now as the test is failing potentially due to incorrect logic in the function + + it('should call showModal with SSO screen if redirectSSO is true', async () => { + const configWithSingleSSO = {...config, EnableSignInWithEmail: 'false', EnableSignInWithUsername: 'false'}; + await loginToServer(theme, serverUrl, displayName, configWithSingleSSO, license); + + expect(showModal).toHaveBeenCalledWith(Screens.SSO, '', expect.any(Object), expect.any(Object)); + });*/ +}); + +describe('editServer', () => { + const theme = Preferences.THEMES.denim; + const server = {url: 'https://server.com', displayName: 'Server'} as ServersModel; + + it('should call showModal with EDIT_SERVER screen', async () => { + await editServer(theme, server); + + expect(showModal).toHaveBeenCalledWith(Screens.EDIT_SERVER, '', expect.any(Object), expect.any(Object)); + }); +}); + +describe('alertServerLogout', () => { + const intl = getIntlShape(); + const displayName = 'Server'; + const onPress = jest.fn(); + + it('should show an alert with the correct title and message', () => { + const alert = jest.spyOn(Alert, 'alert'); + + alertServerLogout(displayName, onPress, intl); + + expect(alert).toHaveBeenCalledWith( + `Are you sure you want to log out of ${displayName}?`, + 'All associated data will be removed', + expect.any(Array), + ); + }); +}); + +describe('alertServerRemove', () => { + const intl = getIntlShape(); + const displayName = 'Server'; + const onPress = jest.fn(); + + it('should show an alert with the correct title and message', () => { + const alert = jest.spyOn(Alert, 'alert'); + alertServerRemove(displayName, onPress, intl); + + expect(alert).toHaveBeenCalledWith( + `Are you sure you want to remove ${displayName}?`, + 'This will remove it from your list of servers. All associated data will be removed', + expect.any(Array), + ); + }); +}); + +describe('alertServerError', () => { + const intl = getIntlShape(); + const error = new Error('Test error'); + + it('should show an alert with the correct title and message', () => { + const alert = jest.spyOn(Alert, 'alert'); + alertServerError(intl, error); + + expect(alert).toHaveBeenCalledWith( + 'Server is unreachable.', + 'Test error', + ); + }); +}); + +describe('alertServerAlreadyConnected', () => { + const intl = getIntlShape(); + + it('should show an alert with the correct message', () => { + const alert = jest.spyOn(Alert, 'alert'); + alertServerAlreadyConnected(intl); + + expect(alert).toHaveBeenCalledWith( + '', + 'You are already connected to this server.', + ); + }); +}); + +describe('sortServersByDisplayName', () => { + const intl = getIntlShape(); + const servers = [ + {url: 'https://server1.com', displayName: 'Server 1'} as ServersModel, + {url: 'https://server2.com', displayName: 'Server 2'} as ServersModel, + {url: 'https://server3.com', displayName: 'https://server3.com'} as ServersModel, + ]; + + it('should sort servers by display name', () => { + const sortedServers = sortServersByDisplayName(servers, intl); + + expect(sortedServers[0].url).toBe('https://server3.com'); // Display name treated as 'Default Server' + expect(sortedServers[1].url).toBe('https://server1.com'); + expect(sortedServers[2].url).toBe('https://server2.com'); + }); +}); diff --git a/app/utils/server/server.test.ts b/app/utils/server/server.test.ts deleted file mode 100644 index a3178d9d95..0000000000 --- a/app/utils/server/server.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {Alert} from 'react-native'; - -import {getIntlShape} from '@utils/general'; - -import {unsupportedServer} from '.'; - -describe('Unsupported Server Alert', () => { - const intl = getIntlShape(); - - it('should show the alert for sysadmin', () => { - const alert = jest.spyOn(Alert, 'alert'); - unsupportedServer('Default Server', true, intl); - expect(alert?.mock?.calls?.[0]?.[2]?.length).toBe(2); - }); - - it('should not show the alert for team admin / user', () => { - const alert = jest.spyOn(Alert, 'alert'); - unsupportedServer('Default Server', false, intl); - expect(alert).not.toHaveBeenCalled(); - }); -});