diff --git a/app/products/playbooks/actions/websocket/runs.test.ts b/app/products/playbooks/actions/websocket/runs.test.ts index 2a04e42ab..7978089d0 100644 --- a/app/products/playbooks/actions/websocket/runs.test.ts +++ b/app/products/playbooks/actions/websocket/runs.test.ts @@ -22,6 +22,7 @@ const serverUrl = 'baseHandler.test.com'; const mockPlaybookList = TestHelper.createPlaybookRuns(1, 1, 1); const mockPlaybookRun = mockPlaybookList[0]; +mockPlaybookRun.update_at = 1; // Set the update_at to a value that is before the current time to avoid flakiness const channelId = mockPlaybookRun.channel_id; const playbookRunId = mockPlaybookRun.id; diff --git a/app/products/playbooks/components/channel_actions/playbook_runs_option/index.test.tsx b/app/products/playbooks/components/channel_actions/playbook_runs_option/index.test.tsx index 8a4151888..5a4faecd7 100644 --- a/app/products/playbooks/components/channel_actions/playbook_runs_option/index.test.tsx +++ b/app/products/playbooks/components/channel_actions/playbook_runs_option/index.test.tsx @@ -27,6 +27,7 @@ describe('PlaybookRunsOption', () => { function getBaseProps(): ComponentProps { return { channelId, + location: 'channel_actions', }; } diff --git a/app/products/playbooks/components/channel_actions/playbook_runs_option/playbook_runs_option.test.tsx b/app/products/playbooks/components/channel_actions/playbook_runs_option/playbook_runs_option.test.tsx index 9047d338d..13b154334 100644 --- a/app/products/playbooks/components/channel_actions/playbook_runs_option/playbook_runs_option.test.tsx +++ b/app/products/playbooks/components/channel_actions/playbook_runs_option/playbook_runs_option.test.tsx @@ -1,10 +1,11 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React from 'react'; +import React, {type ComponentProps} from 'react'; import {Platform} from 'react-native'; import OptionItem from '@components/option_item'; +import SlideUpPanelItem from '@components/slide_up_panel_item'; import {goToPlaybookRuns} from '@playbooks/screens/navigation'; import {dismissBottomSheet} from '@screens/navigation'; import {renderWithIntl, waitFor} from '@test/intl-test-helper'; @@ -14,17 +15,24 @@ import PlaybookRunsOption from './playbook_runs_option'; jest.mock('@components/option_item'); jest.mocked(OptionItem).mockImplementation((props) => React.createElement('OptionItem', {testID: 'option-item', ...props})); +jest.mock('@components/slide_up_panel_item'); +jest.mocked(SlideUpPanelItem).mockImplementation((props) => React.createElement('SlideUpPanelItem', {testID: 'slide-up-panel-item', ...props})); + jest.mock('@playbooks/screens/navigation'); describe('PlaybookRunsOption', () => { - const baseProps = { - channelId: 'channel-id', - playbooksActiveRuns: 3, - channelName: 'channel-name', - }; + function getBaseProps(): ComponentProps { + return { + channelId: 'channel-id', + playbooksActiveRuns: 3, + channelName: 'channel-name', + location: 'channel_actions', + }; + } it('renders correctly', () => { - const {getByTestId} = renderWithIntl(); + const props = getBaseProps(); + const {getByTestId, queryByTestId, rerender} = renderWithIntl(); const optionItem = getByTestId('option-item'); expect(optionItem).toBeTruthy(); @@ -33,19 +41,36 @@ describe('PlaybookRunsOption', () => { expect(optionItem.props.icon).toBe('product-playbooks'); expect(optionItem.props.type).toBe('arrow'); expect(optionItem.props.action).toBeDefined(); + + expect(queryByTestId('slide-up-panel-item')).toBeNull(); + + props.location = 'quick_actions'; + rerender(); + + const slideUpPanelItem = getByTestId('slide-up-panel-item'); + expect(slideUpPanelItem).toBeTruthy(); + expect(slideUpPanelItem.props.text).toBe('Playbook runs'); + expect(slideUpPanelItem.props.leftIcon).toBe('product-playbooks'); + expect(slideUpPanelItem.props.rightIcon).toBe('chevron-right'); + expect(slideUpPanelItem.props.onPress).toBeDefined(); + + expect(queryByTestId('option-item')).toBeNull(); }); it('uses correct type based on platform', () => { + const props = getBaseProps(); + // We need to use any because typescript is not inferring the correct type for the dict jest.mocked(Platform.select).mockImplementation((dict) => dict.android ?? (dict as any).default); - const {getByTestId} = renderWithIntl(); + const {getByTestId} = renderWithIntl(); const optionItem = getByTestId('option-item'); expect(optionItem.props.type).toBe('default'); }); it('calls goToPlaybookRuns when pressed', async () => { - const {getByTestId} = renderWithIntl(); + const props = getBaseProps(); + const {getByTestId} = renderWithIntl(); const optionItem = getByTestId('option-item'); optionItem.props.action(); diff --git a/app/products/playbooks/components/channel_actions/playbook_runs_option/playbook_runs_option.tsx b/app/products/playbooks/components/channel_actions/playbook_runs_option/playbook_runs_option.tsx index b12f50ba5..8cad2f922 100644 --- a/app/products/playbooks/components/channel_actions/playbook_runs_option/playbook_runs_option.tsx +++ b/app/products/playbooks/components/channel_actions/playbook_runs_option/playbook_runs_option.tsx @@ -2,10 +2,11 @@ // See LICENSE.txt for license information. import React, {useCallback} from 'react'; -import {useIntl} from 'react-intl'; +import {defineMessages, useIntl} from 'react-intl'; import {Platform} from 'react-native'; import OptionItem from '@components/option_item'; +import SlideUpPanelItem from '@components/slide_up_panel_item'; import {goToPlaybookRuns} from '@playbooks/screens/navigation'; import {dismissBottomSheet} from '@screens/navigation'; @@ -13,12 +14,21 @@ type Props = { channelId: string; playbooksActiveRuns: number; channelName: string; + location: 'channel_actions' | 'quick_actions'; } +const messages = defineMessages({ + playbookRuns: { + id: 'playbooks.playbooks_runs.title', + defaultMessage: 'Playbook runs', + }, +}); + const PlaybookRunsOption = ({ channelId, playbooksActiveRuns, channelName, + location, }: Props) => { const intl = useIntl(); @@ -27,12 +37,23 @@ const PlaybookRunsOption = ({ goToPlaybookRuns(intl, channelId, channelName); }, [intl, channelId, channelName]); + if (location === 'quick_actions') { + return ( + + ); + } + return ( ); diff --git a/app/screens/channel/header/quick_actions/index.test.tsx b/app/screens/channel/header/quick_actions/index.test.tsx index 9b4571499..9d136e8cf 100644 --- a/app/screens/channel/header/quick_actions/index.test.tsx +++ b/app/screens/channel/header/quick_actions/index.test.tsx @@ -52,5 +52,6 @@ describe('ChannelQuickAction', () => { const playbookRunsOption = getByTestId('playbook-runs-option'); expect(playbookRunsOption).toBeTruthy(); expect(playbookRunsOption.props.channelId).toBe('channel-id'); + expect(playbookRunsOption.props.location).toBe('quick_actions'); }); }); diff --git a/app/screens/channel/header/quick_actions/index.tsx b/app/screens/channel/header/quick_actions/index.tsx index 46886f5e1..7e3a05bb8 100644 --- a/app/screens/channel/header/quick_actions/index.tsx +++ b/app/screens/channel/header/quick_actions/index.tsx @@ -65,7 +65,10 @@ const ChannelQuickAction = ({ testID='channel.quick_actions.channel_info.action' /> {hasPlaybookRuns && - + } {callsEnabled && !isDMorGM && // if calls is not enabled, copy link will show in the channel actions { const props = getBaseProps(); const {getByTestId, rerender} = renderWithEverything(, {database}); expect(getByTestId('playbook-runs-option')).toHaveProp('channelId', 'channel-id'); + expect(getByTestId('playbook-runs-option')).toHaveProp('location', 'channel_actions'); props.channelId = 'channel-id-2'; rerender(); diff --git a/app/screens/channel_info/options/index.tsx b/app/screens/channel_info/options/index.tsx index 7199d3583..68f424bc3 100644 --- a/app/screens/channel_info/options/index.tsx +++ b/app/screens/channel_info/options/index.tsx @@ -49,7 +49,10 @@ const Options = ({ - + {type !== General.DM_CHANNEL && }