diff --git a/app/actions/websocket/index.test.ts b/app/actions/websocket/index.test.ts index 0a59a2dbc..8ff61d4d4 100644 --- a/app/actions/websocket/index.test.ts +++ b/app/actions/websocket/index.test.ts @@ -13,7 +13,7 @@ import {loadConfigAndCalls} from '@calls/actions/calls'; import {isSupportedServerCalls} from '@calls/utils'; import DatabaseManager from '@database/manager'; import AppsManager from '@managers/apps_manager'; -import {updatePlaybooksVersion} from '@playbooks/actions/remote/version'; +import {handlePlaybookReconnect} from '@playbooks/actions/websocket/reconnect'; import {getActiveServerUrl} from '@queries/app/servers'; import {getLastPostInThread} from '@queries/servers/post'; import {getConfig, getCurrentChannelId, getCurrentTeamId, setLastFullSync} from '@queries/servers/system'; @@ -49,7 +49,7 @@ jest.mock('@utils/helpers', () => ({ isTablet: jest.fn().mockReturnValue(false), })); -jest.mock('@playbooks/actions/remote/version'); +jest.mock('@playbooks/actions/websocket/reconnect'); describe('WebSocket Index Actions', () => { const serverUrl = 'baseHandler.test.com'; @@ -104,7 +104,7 @@ describe('WebSocket Index Actions', () => { expect(setLastFullSync).toHaveBeenCalled(); expect(loadConfigAndCalls).toHaveBeenCalled(); expect(deferredAppEntryActions).toHaveBeenCalled(); - expect(updatePlaybooksVersion).toHaveBeenCalledWith(serverUrl); + expect(handlePlaybookReconnect).toHaveBeenCalledWith(serverUrl); }); it('should handle error when server database not found', async () => { @@ -159,7 +159,7 @@ describe('WebSocket Index Actions', () => { expect(openAllUnreadChannels).toHaveBeenCalled(); expect(dataRetentionCleanup).toHaveBeenCalled(); expect(AppsManager.refreshAppBindings).toHaveBeenCalled(); - expect(updatePlaybooksVersion).toHaveBeenCalledWith(serverUrl); + expect(handlePlaybookReconnect).toHaveBeenCalledWith(serverUrl); }); it('should fetch posts for channel screen', async () => { diff --git a/app/actions/websocket/index.ts b/app/actions/websocket/index.ts index 6e9995697..852d2b037 100644 --- a/app/actions/websocket/index.ts +++ b/app/actions/websocket/index.ts @@ -18,7 +18,7 @@ import {isSupportedServerCalls} from '@calls/utils'; import {Screens} from '@constants'; import DatabaseManager from '@database/manager'; import AppsManager from '@managers/apps_manager'; -import {updatePlaybooksVersion} from '@playbooks/actions/remote/version'; +import {handlePlaybookReconnect} from '@playbooks/actions/websocket/reconnect'; import {getActiveServerUrl} from '@queries/app/servers'; import {getLastPostInThread} from '@queries/servers/post'; import { @@ -92,8 +92,7 @@ async function doReconnect(serverUrl: string, groupLabel?: BaseRequestGroupLabel const license = await getLicense(database); const config = await getConfig(database); - // Set the version of the playbooks plugin to the systems table - updatePlaybooksVersion(serverUrl); + handlePlaybookReconnect(serverUrl); if (isSupportedServerCalls(config?.Version)) { loadConfigAndCalls(serverUrl, currentUserId, groupLabel); diff --git a/app/managers/websocket_manager.test.ts b/app/managers/websocket_manager.test.ts index cf8f36e72..72e4fb7f7 100644 --- a/app/managers/websocket_manager.test.ts +++ b/app/managers/websocket_manager.test.ts @@ -11,7 +11,6 @@ import WebSocketClient from '@client/websocket'; import DatabaseManager from '@database/manager'; import {getCurrentUserId} from '@queries/servers/system'; import {queryAllUsers} from '@queries/servers/user'; -import EphemeralStore from '@store/ephemeral_store'; import TestHelper from '@test/test_helper'; import {logError} from '@utils/log'; @@ -31,7 +30,6 @@ jest.mock('@database/manager'); jest.mock('@queries/servers/system'); jest.mock('@queries/servers/user'); jest.mock('@utils/log'); -jest.mock('@store/ephemeral_store'); describe('WebsocketManager', () => { let manager: typeof WebsocketManager; @@ -125,17 +123,6 @@ describe('WebsocketManager', () => { }); }); - describe('proper callbacks set', () => { - it('should remove playbooks when the reconnect callback is called', () => { - const client = manager.createClient(mockServerUrl, mockToken); - expect(client).toBeDefined(); - - expect(client.setReconnectCallback).toHaveBeenCalled(); - jest.mocked(client.setReconnectCallback).mock.calls[0][0](); - expect(EphemeralStore.clearChannelPlaybooksSynced).toHaveBeenCalled(); - }); - }); - describe('connection handling', () => { beforeEach(async () => { await manager.init(mockCredentials); diff --git a/app/managers/websocket_manager.ts b/app/managers/websocket_manager.ts index fdc52225d..7f8738fde 100644 --- a/app/managers/websocket_manager.ts +++ b/app/managers/websocket_manager.ts @@ -16,7 +16,6 @@ import {General} from '@constants'; import DatabaseManager from '@database/manager'; import {getCurrentUserId} from '@queries/servers/system'; import {queryAllUsers} from '@queries/servers/user'; -import EphemeralStore from '@store/ephemeral_store'; import {toMilliseconds} from '@utils/datetime'; import {isMainActivity} from '@utils/helpers'; import {logError} from '@utils/log'; @@ -180,11 +179,6 @@ class WebsocketManagerSingleton { this.startPeriodicStatusUpdates(serverUrl); this.getConnectedSubject(serverUrl).next('connected'); - // Clear playbooks synced state on reconnect. - // This is done to avoid clearing it on spotty connections - // with reliable websockets. - EphemeralStore.clearChannelPlaybooksSynced(serverUrl); - const error = await handleReconnect(serverUrl); if (error) { this.getClient(serverUrl)?.close(false); diff --git a/app/products/playbooks/actions/remote/runs.test.ts b/app/products/playbooks/actions/remote/runs.test.ts index 81a83cfde..bc443f6cf 100644 --- a/app/products/playbooks/actions/remote/runs.test.ts +++ b/app/products/playbooks/actions/remote/runs.test.ts @@ -7,6 +7,7 @@ import NetworkManager from '@managers/network_manager'; import {updateLastPlaybookRunsFetchAt} from '@playbooks/actions/local/channel'; import {handlePlaybookRuns} from '@playbooks/actions/local/run'; import {getLastPlaybookRunsFetchAt} from '@playbooks/database/queries/run'; +import EphemeralStore from '@store/ephemeral_store'; import TestHelper from '@test/test_helper'; import {fetchPlaybookRunsForChannel, fetchFinishedRunsForChannel} from './runs'; @@ -118,6 +119,32 @@ describe('fetchPlaybookRunsForChannel', () => { expect(result.runs).toEqual([mockPlaybookRun]); expect(handlePlaybookRuns).not.toHaveBeenCalled(); }); + + it('should update the channel in the ephemeral store', async () => { + mockClient.fetchPlaybookRuns.mockResolvedValueOnce({ + items: [mockPlaybookRun], + has_more: false, + }); + + EphemeralStore.clearChannelPlaybooksSynced(serverUrl); + + expect(EphemeralStore.getChannelPlaybooksSynced(serverUrl, channelId)).toBe(false); + await fetchPlaybookRunsForChannel(serverUrl, channelId); + expect(EphemeralStore.getChannelPlaybooksSynced(serverUrl, channelId)).toBe(true); + }); + + it('should not update the channel in the ephemeral store if fetchOnly is true', async () => { + mockClient.fetchPlaybookRuns.mockResolvedValueOnce({ + items: [mockPlaybookRun], + has_more: false, + }); + + EphemeralStore.clearChannelPlaybooksSynced(serverUrl); + + expect(EphemeralStore.getChannelPlaybooksSynced(serverUrl, channelId)).toBe(false); + await fetchPlaybookRunsForChannel(serverUrl, channelId, true); + expect(EphemeralStore.getChannelPlaybooksSynced(serverUrl, channelId)).toBe(false); + }); }); describe('fetchFinishedRunsForChannel', () => { diff --git a/app/products/playbooks/actions/remote/runs.ts b/app/products/playbooks/actions/remote/runs.ts index 92f85633d..83fa77614 100644 --- a/app/products/playbooks/actions/remote/runs.ts +++ b/app/products/playbooks/actions/remote/runs.ts @@ -9,6 +9,7 @@ import {updateLastPlaybookRunsFetchAt} from '@playbooks/actions/local/channel'; import {handlePlaybookRuns} from '@playbooks/actions/local/run'; import {getLastPlaybookRunsFetchAt} from '@playbooks/database/queries/run'; import {getMaxRunUpdateAt} from '@playbooks/utils/run'; +import EphemeralStore from '@store/ephemeral_store'; import {getFullErrorMessage} from '@utils/errors'; import {logDebug} from '@utils/log'; @@ -50,6 +51,7 @@ export const fetchPlaybookRunsForChannel = async (serverUrl: string, channelId: updateLastPlaybookRunsFetchAt(serverUrl, channelId, getMaxRunUpdateAt(allRuns)); if (!fetchOnly) { + EphemeralStore.setChannelPlaybooksSynced(serverUrl, channelId); handlePlaybookRuns(serverUrl, allRuns, false, true); } diff --git a/app/products/playbooks/actions/websocket/reconnect.test.ts b/app/products/playbooks/actions/websocket/reconnect.test.ts new file mode 100644 index 000000000..19fd192f5 --- /dev/null +++ b/app/products/playbooks/actions/websocket/reconnect.test.ts @@ -0,0 +1,103 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {Screens} from '@constants'; +import DatabaseManager from '@database/manager'; +import {fetchPlaybookRunsForChannel} from '@playbooks/actions/remote/runs'; +import {updatePlaybooksVersion} from '@playbooks/actions/remote/version'; +import {fetchIsPlaybooksEnabled} from '@playbooks/database/queries/version'; +import {getCurrentChannelId} from '@queries/servers/system'; +import EphemeralStore from '@store/ephemeral_store'; +import NavigationStore from '@store/navigation_store'; + +import {handlePlaybookReconnect} from './reconnect'; + +const serverUrl = 'test-server.com'; + +jest.mock('@playbooks/actions/remote/runs'); +jest.mock('@playbooks/actions/remote/version'); +jest.mock('@playbooks/database/queries/version'); +jest.mock('@queries/servers/system'); + +describe('handlePlaybookReconnect', () => { + const mockCurrentChannelId = 'channel-123'; + + beforeEach(async () => { + jest.clearAllMocks(); + + await DatabaseManager.init([serverUrl]); + + jest.mocked(updatePlaybooksVersion).mockResolvedValue({data: true}); + jest.mocked(fetchIsPlaybooksEnabled).mockResolvedValue(false); + jest.mocked(getCurrentChannelId).mockResolvedValue(mockCurrentChannelId); + jest.mocked(fetchPlaybookRunsForChannel).mockResolvedValue({runs: []}); + }); + + afterEach(async () => { + await DatabaseManager.deleteServerDatabase(serverUrl); + }); + + it('should return early when database is not found', async () => { + const clearSpy = jest.spyOn(EphemeralStore, 'clearChannelPlaybooksSynced'); + const getScreensSpy = jest.spyOn(NavigationStore, 'getScreensInStack'); + await DatabaseManager.deleteServerDatabase(serverUrl); + + await handlePlaybookReconnect(serverUrl); + + expect(clearSpy).not.toHaveBeenCalled(); + expect(updatePlaybooksVersion).not.toHaveBeenCalled(); + expect(getScreensSpy).not.toHaveBeenCalled(); + }); + + it('should clear channel playbooks synced state', async () => { + const clearSpy = jest.spyOn(EphemeralStore, 'clearChannelPlaybooksSynced'); + + await handlePlaybookReconnect(serverUrl); + + expect(clearSpy).toHaveBeenCalledWith(serverUrl); + expect(clearSpy).toHaveBeenCalledTimes(1); + }); + + it('should update playbooks version', async () => { + await handlePlaybookReconnect(serverUrl); + + expect(updatePlaybooksVersion).toHaveBeenCalledWith(serverUrl); + expect(updatePlaybooksVersion).toHaveBeenCalledTimes(1); + }); + + it('should not fetch playbook runs when not on channel screen', async () => { + const getScreensSpy = jest.spyOn(NavigationStore, 'getScreensInStack').mockReturnValue([Screens.HOME, Screens.THREAD]); + + await handlePlaybookReconnect(serverUrl); + + expect(getScreensSpy).toHaveBeenCalled(); + expect(fetchIsPlaybooksEnabled).not.toHaveBeenCalled(); + expect(getCurrentChannelId).not.toHaveBeenCalled(); + expect(fetchPlaybookRunsForChannel).not.toHaveBeenCalled(); + }); + + it('should not fetch playbook runs when playbooks are disabled', async () => { + const getScreensSpy = jest.spyOn(NavigationStore, 'getScreensInStack').mockReturnValue([Screens.HOME, Screens.CHANNEL, Screens.THREAD]); + jest.mocked(fetchIsPlaybooksEnabled).mockResolvedValue(false); + + await handlePlaybookReconnect(serverUrl); + + expect(getScreensSpy).toHaveBeenCalled(); + expect(fetchIsPlaybooksEnabled).toHaveBeenCalled(); + expect(getCurrentChannelId).not.toHaveBeenCalled(); + expect(fetchPlaybookRunsForChannel).not.toHaveBeenCalled(); + }); + + it('should fetch playbook runs when on channel screen and playbooks are enabled', async () => { + const getScreensSpy = jest.spyOn(NavigationStore, 'getScreensInStack').mockReturnValue([Screens.CHANNEL]); + jest.mocked(fetchIsPlaybooksEnabled).mockResolvedValue(true); + + await handlePlaybookReconnect(serverUrl); + + expect(getScreensSpy).toHaveBeenCalled(); + expect(fetchIsPlaybooksEnabled).toHaveBeenCalled(); + expect(getCurrentChannelId).toHaveBeenCalled(); + expect(fetchPlaybookRunsForChannel).toHaveBeenCalledWith(serverUrl, mockCurrentChannelId); + expect(fetchPlaybookRunsForChannel).toHaveBeenCalledTimes(1); + }); +}); diff --git a/app/products/playbooks/actions/websocket/reconnect.ts b/app/products/playbooks/actions/websocket/reconnect.ts new file mode 100644 index 000000000..61b0d4e23 --- /dev/null +++ b/app/products/playbooks/actions/websocket/reconnect.ts @@ -0,0 +1,40 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. +import {Screens} from '@constants'; +import DatabaseManager from '@database/manager'; +import {fetchPlaybookRunsForChannel} from '@playbooks/actions/remote/runs'; +import {updatePlaybooksVersion} from '@playbooks/actions/remote/version'; +import {fetchIsPlaybooksEnabled} from '@playbooks/database/queries/version'; +import {getCurrentChannelId} from '@queries/servers/system'; +import EphemeralStore from '@store/ephemeral_store'; +import NavigationStore from '@store/navigation_store'; +import {logDebug} from '@utils/log'; + +export async function handlePlaybookReconnect(serverUrl: string) { + const database = DatabaseManager.serverDatabases[serverUrl]?.database; + if (!database) { + return; + } + + // Clear playbooks synced state on reconnect. + // This is done to avoid clearing it on spotty connections + // with reliable websockets. + EphemeralStore.clearChannelPlaybooksSynced(serverUrl); + + // Set the version of the playbooks plugin to the systems table + const updateResult = await updatePlaybooksVersion(serverUrl); + if (updateResult.error) { + logDebug('Error updating playbooks version on reconnect', updateResult.error); + } + + if (NavigationStore.getScreensInStack().includes(Screens.CHANNEL)) { + const isPlaybooksEnabled = await fetchIsPlaybooksEnabled(database); + if (isPlaybooksEnabled) { + const currentChannelId = await getCurrentChannelId(database); + const fetchResult = await fetchPlaybookRunsForChannel(serverUrl, currentChannelId); + if (fetchResult.error) { + logDebug('Error fetching playbook runs on reconnect', fetchResult.error); + } + } + } +} diff --git a/app/products/playbooks/database/queries/version.test.ts b/app/products/playbooks/database/queries/version.test.ts index 5598254c7..2557cde97 100644 --- a/app/products/playbooks/database/queries/version.test.ts +++ b/app/products/playbooks/database/queries/version.test.ts @@ -5,7 +5,7 @@ import {SYSTEM_IDENTIFIERS} from '@constants/database'; import DatabaseManager from '@database/manager'; import {MINIMUM_MAJOR_VERSION, MINIMUM_MINOR_VERSION, MINIMUM_PATCH_VERSION} from '@playbooks/constants/version'; -import {observeIsPlaybooksEnabled} from './version'; +import {fetchIsPlaybooksEnabled, observeIsPlaybooksEnabled} from './version'; import type ServerDataOperator from '@database/operator/server_data_operator'; @@ -151,4 +151,75 @@ describe('Playbook Version Queries', () => { expect(subscriptionNext).toHaveBeenCalledWith(false); }); }); + + describe('fetchIsPlaybooksEnabled', () => { + it('should return false when no playbooks version is set', async () => { + const result = await fetchIsPlaybooksEnabled(operator.database); + expect(result).toBe(false); + }); + + it(`should return true when playbooks version meets minimum requirements (${MINIMUM_VERSION})`, async () => { + await operator.handleSystem({ + systems: [{id: SYSTEM_IDENTIFIERS.PLAYBOOKS_VERSION, value: MINIMUM_VERSION}], + prepareRecordsOnly: false, + }); + + const result = await fetchIsPlaybooksEnabled(operator.database); + expect(result).toBe(true); + }); + + it('should return true when playbooks version has higher major version', async () => { + const higherVersion = `${MINIMUM_MAJOR_VERSION + 1}.0.0`; + await operator.handleSystem({ + systems: [{id: SYSTEM_IDENTIFIERS.PLAYBOOKS_VERSION, value: higherVersion}], + prepareRecordsOnly: false, + }); + + const result = await fetchIsPlaybooksEnabled(operator.database); + expect(result).toBe(true); + }); + + it('should return true when playbooks version has higher minor version', async () => { + const higherVersion = `${MINIMUM_MAJOR_VERSION}.${MINIMUM_MINOR_VERSION + 1}.${MINIMUM_PATCH_VERSION}`; + await operator.handleSystem({ + systems: [{id: SYSTEM_IDENTIFIERS.PLAYBOOKS_VERSION, value: higherVersion}], + prepareRecordsOnly: false, + }); + + const result = await fetchIsPlaybooksEnabled(operator.database); + expect(result).toBe(true); + }); + + it('should return true when playbooks version has higher patch version', async () => { + const higherVersion = `${MINIMUM_MAJOR_VERSION}.${MINIMUM_MINOR_VERSION}.${MINIMUM_PATCH_VERSION + 1}`; + await operator.handleSystem({ + systems: [{id: SYSTEM_IDENTIFIERS.PLAYBOOKS_VERSION, value: higherVersion}], + prepareRecordsOnly: false, + }); + + const result = await fetchIsPlaybooksEnabled(operator.database); + expect(result).toBe(true); + }); + + it('should handle empty version string', async () => { + await operator.handleSystem({ + systems: [{id: SYSTEM_IDENTIFIERS.PLAYBOOKS_VERSION, value: ''}], + prepareRecordsOnly: false, + }); + + const result = await fetchIsPlaybooksEnabled(operator.database); + expect(result).toBe(false); + }); + + it('should return false when playbooks version is below minimum', async () => { + const belowVersion = `${MINIMUM_MAJOR_VERSION - 1}.${MINIMUM_MINOR_VERSION}.${MINIMUM_PATCH_VERSION}`; + await operator.handleSystem({ + systems: [{id: SYSTEM_IDENTIFIERS.PLAYBOOKS_VERSION, value: belowVersion}], + prepareRecordsOnly: false, + }); + + const result = await fetchIsPlaybooksEnabled(operator.database); + expect(result).toBe(false); + }); + }); }); diff --git a/app/products/playbooks/database/queries/version.ts b/app/products/playbooks/database/queries/version.ts index 2702c4034..2a0417bdc 100644 --- a/app/products/playbooks/database/queries/version.ts +++ b/app/products/playbooks/database/queries/version.ts @@ -11,17 +11,32 @@ import {isMinimumServerVersion} from '@utils/helpers'; import type SystemModel from '@typings/database/models/servers/system'; +function queryPlaybooksVersion(database: Database) { + return database.get(MM_TABLES.SERVER.SYSTEM).query( + Q.where('id', SYSTEM_IDENTIFIERS.PLAYBOOKS_VERSION), + ); +} + +function isPlaybooksEnabledFromSystemModel(systems: SystemModel[]) { + const version = systems[0]?.value; + if (!version) { + return false; + } + + return isMinimumServerVersion(version, MINIMUM_MAJOR_VERSION, MINIMUM_MINOR_VERSION, MINIMUM_PATCH_VERSION); +} + +export async function fetchIsPlaybooksEnabled(database: Database) { + const systems = await queryPlaybooksVersion(database).fetch(); + return isPlaybooksEnabledFromSystemModel(systems); +} + export function observeIsPlaybooksEnabled(database: Database) { return database.get(MM_TABLES.SERVER.SYSTEM).query( Q.where('id', SYSTEM_IDENTIFIERS.PLAYBOOKS_VERSION), ).observeWithColumns(['value']).pipe( switchMap((systems) => { - const version = systems[0]?.value; - if (!version) { - return of$(false); - } - - return of$(isMinimumServerVersion(version, MINIMUM_MAJOR_VERSION, MINIMUM_MINOR_VERSION, MINIMUM_PATCH_VERSION)); + return of$(isPlaybooksEnabledFromSystemModel(systems)); }), ); } diff --git a/app/screens/channel/header/header.test.tsx b/app/screens/channel/header/header.test.tsx index 43a338c53..34975c7c1 100644 --- a/app/screens/channel/header/header.test.tsx +++ b/app/screens/channel/header/header.test.tsx @@ -128,31 +128,8 @@ describe('ChannelHeader', () => { expect(goToPlaybookRun).not.toHaveBeenCalled(); }); - it('should set the ephemeral store when we fetch the playbook runs for the channel', async () => { - const ephemeralGetSpy = jest.spyOn(EphemeralStore, 'getChannelPlaybooksSynced'); - const ephemeralSetSpy = jest.spyOn(EphemeralStore, 'setChannelPlaybooksSynced'); - - const props = getBaseProps(); - props.isPlaybooksEnabled = true; - - ephemeralGetSpy.mockReturnValue(false); - - jest.mocked(fetchPlaybookRunsForChannel).mockResolvedValue({ - runs: [], - }); - - renderWithIntl(); - - await waitFor(() => { - expect(ephemeralGetSpy).toHaveBeenCalledWith(serverUrl, 'channel-id'); - expect(fetchPlaybookRunsForChannel).toHaveBeenCalledWith(serverUrl, 'channel-id'); - expect(ephemeralSetSpy).toHaveBeenCalledWith(serverUrl, 'channel-id'); - }); - }); - it('should not fetch runs when playbooks are disabled', async () => { const ephemeralGetSpy = jest.spyOn(EphemeralStore, 'getChannelPlaybooksSynced'); - const ephemeralSetSpy = jest.spyOn(EphemeralStore, 'setChannelPlaybooksSynced'); const props = getBaseProps(); props.isPlaybooksEnabled = false; @@ -162,14 +139,12 @@ describe('ChannelHeader', () => { await waitFor(() => { expect(ephemeralGetSpy).not.toHaveBeenCalled(); - expect(ephemeralSetSpy).not.toHaveBeenCalled(); expect(fetchPlaybookRunsForChannel).not.toHaveBeenCalled(); }); }); it('should not fetch runs when we already have the runs synced', async () => { const ephemeralGetSpy = jest.spyOn(EphemeralStore, 'getChannelPlaybooksSynced'); - const ephemeralSetSpy = jest.spyOn(EphemeralStore, 'setChannelPlaybooksSynced'); const props = getBaseProps(); props.isPlaybooksEnabled = true; @@ -180,28 +155,7 @@ describe('ChannelHeader', () => { await waitFor(() => { expect(ephemeralGetSpy).toHaveBeenCalledWith(serverUrl, 'channel-id'); - expect(ephemeralSetSpy).not.toHaveBeenCalled(); expect(fetchPlaybookRunsForChannel).not.toHaveBeenCalled(); }); }); - - it('should not set the ephemeral store when there is an error fetching the runs', async () => { - const ephemeralGetSpy = jest.spyOn(EphemeralStore, 'getChannelPlaybooksSynced'); - const ephemeralSetSpy = jest.spyOn(EphemeralStore, 'setChannelPlaybooksSynced'); - - const props = getBaseProps(); - props.isPlaybooksEnabled = true; - - ephemeralGetSpy.mockReturnValue(false); - - jest.mocked(fetchPlaybookRunsForChannel).mockResolvedValue({error: new Error('Error fetching runs')}); - - renderWithIntl(); - - await waitFor(() => { - expect(ephemeralGetSpy).toHaveBeenCalledWith(serverUrl, 'channel-id'); - expect(ephemeralSetSpy).not.toHaveBeenCalled(); - expect(fetchPlaybookRunsForChannel).toHaveBeenCalledWith(serverUrl, 'channel-id'); - }); - }); }); diff --git a/app/screens/channel/header/header.tsx b/app/screens/channel/header/header.tsx index 5a4cdc1dc..014d157bc 100644 --- a/app/screens/channel/header/header.tsx +++ b/app/screens/channel/header/header.tsx @@ -303,10 +303,7 @@ const ChannelHeader = ({ useEffect(() => { const asyncEffect = async () => { if (isPlaybooksEnabled && !EphemeralStore.getChannelPlaybooksSynced(serverUrl, channelId)) { - const res = await fetchPlaybookRunsForChannel(serverUrl, channelId); - if (!('error' in res)) { - EphemeralStore.setChannelPlaybooksSynced(serverUrl, channelId); - } + await fetchPlaybookRunsForChannel(serverUrl, channelId); } }; asyncEffect();