diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 978da796fb..8fc3589c3b 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -21,6 +21,9 @@ import { ScrollerLockContext, createScrollerLock, } from '../ts/hooks/useScrollLock'; +import { Environment, setEnvironment } from '../ts/environment.ts'; + +setEnvironment(Environment.Development, true); const i18n = setupI18n('en', messages); @@ -94,7 +97,6 @@ window.SignalContext = { unregisterForChange: noop, }, - isTestOrMockEnvironment: () => false, nativeThemeListener: { getSystemTheme: () => 'light', subscribe: noop, diff --git a/app/config.ts b/app/config.ts index 89b49296a2..f03f644443 100644 --- a/app/config.ts +++ b/app/config.ts @@ -15,9 +15,12 @@ import { // In production mode, NODE_ENV cannot be customized by the user if (app.isPackaged) { - setEnvironment(Environment.Production); + setEnvironment(Environment.Production, false); } else { - setEnvironment(parseEnvironment(process.env.NODE_ENV || 'development')); + setEnvironment( + parseEnvironment(process.env.NODE_ENV || 'development'), + Boolean(process.env.MOCK_TEST) + ); } // Set environment vars to configure node-config before requiring it diff --git a/app/main.ts b/app/main.ts index 23bc75b5db..dffa82c8b0 100644 --- a/app/main.ts +++ b/app/main.ts @@ -2450,6 +2450,7 @@ ipc.on('get-config', async event => { !isTestEnvironment(getEnvironment()) && ciMode ? Environment.Production : getEnvironment(), + isMockTestEnvironment: Boolean(process.env.MOCK_TEST), ciMode, // Should be already computed and cached at this point dnsFallback: await getDNSFallback(), diff --git a/test/setup-test-node.js b/test/setup-test-node.js index da28f83cd2..728b12c7b5 100644 --- a/test/setup-test-node.js +++ b/test/setup-test-node.js @@ -12,7 +12,7 @@ const { HourCyclePreference } = require('../ts/types/I18N'); chai.use(chaiAsPromised); -setEnvironment(Environment.Test); +setEnvironment(Environment.Test, true); const storageMap = new Map(); @@ -32,7 +32,6 @@ global.window = { getHourCyclePreference: () => HourCyclePreference.UnknownPreference, getPreferredSystemLocales: () => ['en'], getLocaleOverride: () => null, - isTestOrMockEnvironment: () => true, }, i18n: key => `i18n(${key})`, storage: { diff --git a/ts/components/conversationList/MessageSearchResult.stories.tsx b/ts/components/conversationList/MessageSearchResult.stories.tsx index d56e3d5868..c9c9fa8579 100644 --- a/ts/components/conversationList/MessageSearchResult.stories.tsx +++ b/ts/components/conversationList/MessageSearchResult.stories.tsx @@ -142,21 +142,20 @@ export function FromSomeoneToGroup(): JSX.Element { } export function LongSearchResult(): JSX.Element { - const snippets = [ - 'This is a really <>detail<>ed long line which will wrap and only be cut off after it gets to three lines. So maybe this will make it in as well?', - "Okay, here are the <>detail<>s:\n\n1355 Ridge Way\nCode: 234\n\nI'm excited!", - ]; - const props1 = useProps({ from: someone, to: me, - snippet: snippets[0], + snippet: + 'This is a really <>detail<>ed long line which will wrap and only be cut off after it gets to three lines. So maybe this will make it in as well?', + body: 'This is a really detailed long line which will wrap and only be cut off after it gets to three lines. So maybe this will make it in as well?', }); const props2 = useProps({ from: someone, to: me, - snippet: snippets[1], + snippet: + "Okay, here are the <>detail<>s:\n\n1355 Ridge Way\nCode: 234\n\nI'm excited!", + body: "Okay, here are the details:\n\n1355 Ridge Way\nCode: 234\n\nI'm excited!", }); return ( diff --git a/ts/context/environment.ts b/ts/context/environment.ts index 5d0c656f23..b29dd2bfa0 100644 --- a/ts/context/environment.ts +++ b/ts/context/environment.ts @@ -4,16 +4,15 @@ import { config } from './config'; import { getEnvironment, - isTestEnvironment, parseEnvironment, setEnvironment, } from '../environment'; -setEnvironment(parseEnvironment(config.environment)); +setEnvironment( + parseEnvironment(config.environment), + config.isMockTestEnvironment +); const environment = getEnvironment(); -const isTestOrMockEnvironment = - isTestEnvironment(environment) || Boolean(process.env.MOCK_TEST); - -export { environment, isTestOrMockEnvironment }; +export { environment }; diff --git a/ts/environment.ts b/ts/environment.ts index 64149e550d..a92249c6e9 100644 --- a/ts/environment.ts +++ b/ts/environment.ts @@ -12,6 +12,7 @@ export enum Environment { } let environment: undefined | Environment; +let isMockTestEnvironment: undefined | boolean; export function getEnvironment(): Environment { if (environment === undefined) { @@ -26,12 +27,16 @@ export function getEnvironment(): Environment { /** * Sets the current environment. Should be called early in a process's life, and can only * be called once. + * + * isMockTestEnv is used when running tests that require a non-"test" environment but + * need to mock certain behaviors. */ -export function setEnvironment(env: Environment): void { +export function setEnvironment(env: Environment, isMockTestEnv: boolean): void { if (environment !== undefined) { throw new Error('Environment has already been set'); } environment = env; + isMockTestEnvironment = isMockTestEnv; } export const parseEnvironment = makeEnumParser( @@ -41,3 +46,10 @@ export const parseEnvironment = makeEnumParser( export const isTestEnvironment = (env: Environment): boolean => env === Environment.Test; + +export const isTestOrMockEnvironment = (): boolean => { + if (isMockTestEnvironment == null) { + throw new Error('Mock test environment not set'); + } + return isTestEnvironment(getEnvironment()) || isMockTestEnvironment; +}; diff --git a/ts/types/RendererConfig.ts b/ts/types/RendererConfig.ts index a691df39fc..5807229185 100644 --- a/ts/types/RendererConfig.ts +++ b/ts/types/RendererConfig.ts @@ -45,6 +45,7 @@ export const rendererConfigSchema = z.object({ dnsFallback: DNSFallbackSchema, ciBackupPath: configOptionalStringSchema, environment: environmentSchema, + isMockTestEnvironment: z.boolean(), homePath: configRequiredStringSchema, hostname: configRequiredStringSchema, installPath: configRequiredStringSchema, diff --git a/ts/util/unicodeBidi.ts b/ts/util/unicodeBidi.ts index 0ffd7e2164..73a24876b5 100644 --- a/ts/util/unicodeBidi.ts +++ b/ts/util/unicodeBidi.ts @@ -1,6 +1,8 @@ // Copyright 2024 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only +import { isTestOrMockEnvironment } from '../environment'; + /** * Left-to-Right Isolate * Sets direction to LTR and isolates the embedded content from the surrounding text @@ -208,7 +210,7 @@ export function _bidiIsolate(text: string): string { * ``` */ export function bidiIsolate(text: string): string { - if (window.SignalContext.isTestOrMockEnvironment()) { + if (isTestOrMockEnvironment()) { // Turn this off in tests to make it easier to compare strings return text; } diff --git a/ts/windows/minimalContext.ts b/ts/windows/minimalContext.ts index 5936bca4db..98341aaa2c 100644 --- a/ts/windows/minimalContext.ts +++ b/ts/windows/minimalContext.ts @@ -12,13 +12,14 @@ import { activeWindowService } from '../context/activeWindowService'; import { config } from '../context/config'; import { createNativeThemeListener } from '../context/createNativeThemeListener'; import { createSetting } from '../util/preload'; -import { environment, isTestOrMockEnvironment } from '../context/environment'; +import { environment } from '../context/environment'; import { localeDisplayNames, countryDisplayNames, localeMessages, } from '../context/localeMessages'; import { waitForSettingsChange } from '../context/waitForSettingsChange'; +import { isTestOrMockEnvironment } from '../environment'; const emojiListCache = new Map(); @@ -71,7 +72,7 @@ export const MinimalSignalContext: MinimalSignalContextType = { getHourCyclePreference: () => config.hourCyclePreference, getPreferredSystemLocales: () => config.preferredSystemLocales, getLocaleOverride: () => config.localeOverride, - isTestOrMockEnvironment: () => isTestOrMockEnvironment, + isTestOrMockEnvironment, nativeThemeListener: createNativeThemeListener(ipcRenderer, window), restartApp: () => ipcRenderer.send('restart'), OS: { diff --git a/ts/windows/settings/app.tsx b/ts/windows/settings/app.tsx index 573992a149..472dae0a07 100644 --- a/ts/windows/settings/app.tsx +++ b/ts/windows/settings/app.tsx @@ -9,6 +9,7 @@ import { i18n } from '../sandboxedInit'; import { Preferences } from '../../components/Preferences'; import { startInteractionMode } from '../../services/InteractionMode'; import { strictAssert } from '../../util/assert'; +import { parseEnvironment, setEnvironment } from '../../environment'; const { SettingsWindowProps } = window.Signal; @@ -16,6 +17,11 @@ strictAssert(SettingsWindowProps, 'window values not provided'); startInteractionMode(); +setEnvironment( + parseEnvironment(window.SignalContext.getEnvironment()), + window.SignalContext.isTestOrMockEnvironment() +); + SettingsWindowProps.onRender( ({ addCustomColor,