mattermost-mobile/app/components/post_draft/quick_actions/quick_actions.test.tsx
Felipe Martin 714c3dc769
feat: AI rewrite (#9280)
* feat: ai rewrite

* feat: allow crating content apart from editing it

* feat: feature parity with webapp

* feat: feature parity with webapp

* chore: fixed padding

* map ux to webapp

* refactored ai rewrite logic to separate package

* chore: tests and lint

* Update app/products/ai/rewrite/screens/options/options.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* rewrite post editor animation

* i18n

* ui feedback, centered icon and less top padding

* chore: lint

* Consolidate @ai product into @agents

Move all rewrite functionality from app/products/ai/ into
app/products/agents/ to unify under a single namespace.

- Add rewrite types, store, hooks, components, and screens to agents
- Merge AI client methods into agents client
- Update screen constants (AI_* -> AGENTS_*)
- Update all consumer imports
- Remove AI state from EphemeralStore
- Remove @ai path alias from config
- Delete app/products/ai/ directory

* refactor: load screens from product package

* refactor: move detection logic to the agents pacakge

* refactor: remove "backwards compatibility"

* refactor: move hooks to proper package

* refactor: styles

* refactor: remove unneedd position attribute

* refactor: remove unneeded cancel animation calls

* refactor: "backwards compat"

* refactor: optimize renderContent with useCallback for performance

* refactor: rename variable to avoid confusion

* refactor: update handleRewrite to use async/await for better error handling

* refactor: simplify handleRewrite by always dismissing keyboard

* refactor: use hook, always all keyboard.dismiss

* chore: enhance AgentSelector component with FlatList support

* feat: add rewriteMessage function for AI message rewriting and integrate it into useRewrite hook

* refactor: simplify message length calculation in useHandleSendMessage hook

* refactor: consolidate agent screen constants and integrate with existing screens

* fix: update dependency array in useMemo for isUnrevealedPost to include post expiration metadata

* refactor: remove unused variable to clean up Typing component

* refactor: simplify logic for atDisabled and slashDisabled flags in QuickActions component

* feat: add AIRewriteAction component for AI message rewriting functionality

* revert: thread.ts changes manually

* refactor: integrate useSafeAreaInsets

* refactor: cleanup unused methods

* chore: add comment to clarify casting

* refactor: use_agents

* chore: lint and test

* fix: trim

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-16 16:48:57 +01:00

212 lines
8.4 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Screens} from '@constants';
import {PostPriorityType} from '@constants/post';
import {renderWithIntlAndTheme} from '@test/intl-test-helper';
import QuickActions from './quick_actions';
jest.mock('@components/post_draft/quick_actions/bor_quick_action', () => ({
__esModule: true,
default: jest.fn(),
}));
describe('Quick Actions', () => {
const baseProps: Parameters<typeof QuickActions>[0] = {
isBoREnabled: false,
updatePostBoRStatus: jest.fn(),
testID: 'test-quick-actions',
canUploadFiles: true,
fileCount: 0,
isAgentsEnabled: true,
isPostPriorityEnabled: true,
canShowPostPriority: true,
canShowSlashCommands: true,
maxFileCount: 10,
value: '',
updateValue: jest.fn(),
addFiles: jest.fn(),
postPriority: {
priority: PostPriorityType.STANDARD,
},
updatePostPriority: jest.fn(),
focus: jest.fn(),
location: Screens.CHANNEL,
};
describe('slash commands', () => {
it('should render slash command if canShowSlashCommands is true', () => {
const props = {
...baseProps,
canShowSlashCommands: true,
};
const {queryByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
expect(queryByTestId('test-quick-actions.slash_input_action')).toBeDefined();
});
it('should not render slash command if canShowSlashCommands is false', () => {
const props = {
...baseProps,
canShowSlashCommands: false,
};
const {queryByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
expect(queryByTestId('test-quick-actions.slash_input_action')).toBeNull();
});
it('should render slash command by default when canShowSlashCommands is not provided', () => {
const props = {
...baseProps,
};
delete (props as {canShowSlashCommands?: boolean}).canShowSlashCommands;
const {queryByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
expect(queryByTestId('test-quick-actions.slash_input_action')).toBeDefined();
});
});
describe('post priority', () => {
it('should render post priority action when both isPostPriorityEnabled and canShowPostPriority are true', () => {
const props = {
...baseProps,
isPostPriorityEnabled: true,
canShowPostPriority: true,
};
const {queryByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
expect(queryByTestId('test-quick-actions.post_priority_action')).toBeDefined();
});
it('should not render post priority action when isPostPriorityEnabled is false', () => {
const props = {
...baseProps,
isPostPriorityEnabled: false,
canShowPostPriority: true,
};
const {queryByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
expect(queryByTestId('test-quick-actions.post_priority_action')).toBeNull();
});
it('should not render post priority action when canShowPostPriority is false', () => {
const props = {
...baseProps,
isPostPriorityEnabled: true,
canShowPostPriority: false,
};
const {queryByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
expect(queryByTestId('test-quick-actions.post_priority_action')).toBeNull();
});
it('should not render post priority action when canShowPostPriority is undefined', () => {
const props = {
...baseProps,
isPostPriorityEnabled: true,
};
delete (props as {canShowPostPriority?: boolean}).canShowPostPriority;
const {queryByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
expect(queryByTestId('test-quick-actions.post_priority_action')).toBeNull();
});
});
describe('input action disabled states', () => {
it('should disable at input action when value ends with @', () => {
const props = {
...baseProps,
value: 'test @',
};
const {getByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
const atAction = getByTestId('test-quick-actions.at_input_action.disabled');
expect(atAction).toBeDisabled();
});
it('should enable at input action when value does not end with @', () => {
const props = {
...baseProps,
value: 'test message',
};
const {getByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
const atAction = getByTestId('test-quick-actions.at_input_action');
expect(atAction).not.toBeDisabled();
});
it('should enable at input action when value is empty', () => {
const props = {
...baseProps,
value: '',
};
const {getByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
const atAction = getByTestId('test-quick-actions.at_input_action');
expect(atAction).not.toBeDisabled();
});
it('should disable slash input action when value is not empty', () => {
const props = {
...baseProps,
value: 'test message',
};
const {getByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
const slashAction = getByTestId('test-quick-actions.slash_input_action.disabled');
expect(slashAction).toBeDisabled();
});
it('should enable slash input action when value is empty', () => {
const props = {
...baseProps,
value: '',
};
const {getByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
const slashAction = getByTestId('test-quick-actions.slash_input_action');
expect(slashAction).not.toBeDisabled();
});
});
describe('attachment action props', () => {
it('should pass disabled=true when canUploadFiles is false', () => {
const props = {
...baseProps,
canUploadFiles: false,
};
const {getByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
const attachmentAction = getByTestId('test-quick-actions.attachment_action.disabled');
expect(attachmentAction).toBeDisabled();
});
it('should pass disabled=false when canUploadFiles is true', () => {
const props = {
...baseProps,
canUploadFiles: true,
};
const {getByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
const attachmentAction = getByTestId('test-quick-actions.attachment_action');
expect(attachmentAction).not.toBeDisabled();
});
});
describe('BoR quick action', () => {
it('should render BoR action when isBoREnabled is true', () => {
const props = {
...baseProps,
isBoREnabled: true,
};
const {queryByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
expect(queryByTestId('test-quick-actions.bor_action')).toBeDefined();
});
it('should not render BoR action when isBoREnabled is false', () => {
const props = {
...baseProps,
isBoREnabled: false,
};
const {queryByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
expect(queryByTestId('test-quick-actions.bor_action')).toBeNull();
});
it('should not render BoR action in threads', () => {
const props = {
...baseProps,
isBoREnabled: true,
location: Screens.THREAD,
};
const {queryByTestId} = renderWithIntlAndTheme(<QuickActions {...props}/>);
expect(queryByTestId('test-quick-actions.bor_action')).toBeNull();
});
});
});