Agent chat code cleanup (#13088)
This PR addresses feedback from [PR-13061](https://github.com/twentyhq/twenty/pull/13061). - Removed redundant type assertion from `apollo.factory.ts`. - Removed redundant tests: Eliminated test cases that were specifically added to boost coverage metrics rather than testing meaningful functionality
This commit is contained in:
@ -230,7 +230,7 @@ export class ApolloFactory<TCacheShape> implements ApolloManager<TCacheShape> {
|
|||||||
retryLink,
|
retryLink,
|
||||||
restLink,
|
restLink,
|
||||||
httpLink,
|
httpLink,
|
||||||
].filter(isDefined) as ApolloLink[],
|
].filter(isDefined),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
import { InputHotkeyScope } from '@/ui/input/types/InputHotkeyScope';
|
import { InputHotkeyScope } from '@/ui/input/types/InputHotkeyScope';
|
||||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||||
import { useCallback, useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
import { Key } from 'ts-key-enum';
|
import { Key } from 'ts-key-enum';
|
||||||
|
|
||||||
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
|
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
|
||||||
import { useScrollWrapperElement } from '@/ui/utilities/scroll/hooks/useScrollWrapperElement';
|
import { useScrollWrapperElement } from '@/ui/utilities/scroll/hooks/useScrollWrapperElement';
|
||||||
import { AgentChatMessageRole } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/constants/agent-chat-message-role';
|
import { AgentChatMessageRole } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/constants/agent-chat-message-role';
|
||||||
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
import { streamChatResponse } from '../api/streamChatResponse';
|
import { streamChatResponse } from '../api/streamChatResponse';
|
||||||
import { agentChatInputState } from '../states/agentChatInputState';
|
import { agentChatInputState } from '../states/agentChatInputState';
|
||||||
@ -36,22 +37,32 @@ export const useAgentChat = (agentId: string) => {
|
|||||||
|
|
||||||
const { scrollWrapperHTMLElement } = useScrollWrapperElement(agentId);
|
const { scrollWrapperHTMLElement } = useScrollWrapperElement(agentId);
|
||||||
|
|
||||||
const scrollToBottom = useCallback(() => {
|
const scrollToBottom = () => {
|
||||||
scrollWrapperHTMLElement?.scroll({
|
scrollWrapperHTMLElement?.scroll({
|
||||||
top: scrollWrapperHTMLElement.scrollHeight,
|
top: scrollWrapperHTMLElement.scrollHeight,
|
||||||
behavior: 'smooth',
|
behavior: 'smooth',
|
||||||
});
|
});
|
||||||
}, [scrollWrapperHTMLElement]);
|
};
|
||||||
|
|
||||||
const { data: { threads = [] } = {}, loading: threadsLoading } =
|
const { data: { threads = [] } = {}, loading: threadsLoading } =
|
||||||
useAgentChatThreads(agentId);
|
useAgentChatThreads(agentId);
|
||||||
const currentThreadId = threads[0]?.id;
|
const currentThreadId = threads[0]?.id;
|
||||||
|
|
||||||
const { loading: messagesLoading, refetch: refetchMessages } =
|
const {
|
||||||
useAgentChatMessages(currentThreadId);
|
data: messagesData,
|
||||||
|
loading: messagesLoading,
|
||||||
|
refetch: refetchMessages,
|
||||||
|
} = useAgentChatMessages(currentThreadId);
|
||||||
|
|
||||||
const isLoading = messagesLoading || threadsLoading || isStreaming;
|
const isLoading = messagesLoading || threadsLoading || isStreaming;
|
||||||
|
|
||||||
|
if (
|
||||||
|
agentChatMessages.length === 0 &&
|
||||||
|
isDefined(messagesData?.messages?.length)
|
||||||
|
) {
|
||||||
|
setAgentChatMessages(messagesData.messages);
|
||||||
|
}
|
||||||
|
|
||||||
const createOptimisticMessages = (content: string): AgentChatMessage[] => {
|
const createOptimisticMessages = (content: string): AgentChatMessage[] => {
|
||||||
const optimisticUserMessage: OptimisticMessage = {
|
const optimisticUserMessage: OptimisticMessage = {
|
||||||
id: v4(),
|
id: v4(),
|
||||||
|
|||||||
@ -2,237 +2,43 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
|||||||
import { getFieldIcon } from '../getFieldIcon';
|
import { getFieldIcon } from '../getFieldIcon';
|
||||||
|
|
||||||
describe('getFieldIcon', () => {
|
describe('getFieldIcon', () => {
|
||||||
const UNSUPPORTED_FIELD_TYPES = [
|
describe('supported field types', () => {
|
||||||
'string',
|
|
||||||
'number',
|
|
||||||
'boolean',
|
|
||||||
'object',
|
|
||||||
'array',
|
|
||||||
'unknown',
|
|
||||||
FieldMetadataType.DATE_TIME,
|
|
||||||
FieldMetadataType.EMAILS,
|
|
||||||
FieldMetadataType.PHONES,
|
|
||||||
FieldMetadataType.LINKS,
|
|
||||||
FieldMetadataType.CURRENCY,
|
|
||||||
FieldMetadataType.SELECT,
|
|
||||||
FieldMetadataType.MULTI_SELECT,
|
|
||||||
FieldMetadataType.RELATION,
|
|
||||||
FieldMetadataType.UUID,
|
|
||||||
FieldMetadataType.RAW_JSON,
|
|
||||||
FieldMetadataType.FULL_NAME,
|
|
||||||
FieldMetadataType.ADDRESS,
|
|
||||||
FieldMetadataType.ARRAY,
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
type UnsupportedFieldType = (typeof UNSUPPORTED_FIELD_TYPES)[number];
|
|
||||||
|
|
||||||
describe('FieldMetadataType field types', () => {
|
|
||||||
it('should return IconAbc for TEXT field type', () => {
|
it('should return IconAbc for TEXT field type', () => {
|
||||||
const result = getFieldIcon(FieldMetadataType.TEXT);
|
expect(getFieldIcon(FieldMetadataType.TEXT)).toBe('IconAbc');
|
||||||
expect(result).toBe('IconAbc');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return IconText for NUMBER field type', () => {
|
it('should return IconText for NUMBER field type', () => {
|
||||||
const result = getFieldIcon(FieldMetadataType.NUMBER);
|
expect(getFieldIcon(FieldMetadataType.NUMBER)).toBe('IconText');
|
||||||
expect(result).toBe('IconText');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return IconCheckbox for BOOLEAN field type', () => {
|
it('should return IconCheckbox for BOOLEAN field type', () => {
|
||||||
const result = getFieldIcon(FieldMetadataType.BOOLEAN);
|
expect(getFieldIcon(FieldMetadataType.BOOLEAN)).toBe('IconCheckbox');
|
||||||
expect(result).toBe('IconCheckbox');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return IconCalendarEvent for DATE field type', () => {
|
it('should return IconCalendarEvent for DATE field type', () => {
|
||||||
const result = getFieldIcon(FieldMetadataType.DATE);
|
expect(getFieldIcon(FieldMetadataType.DATE)).toBe('IconCalendarEvent');
|
||||||
expect(result).toBe('IconCalendarEvent');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('basic InputSchemaPropertyType field types', () => {
|
describe('unsupported and edge cases', () => {
|
||||||
it('should return IconQuestionMark for string type', () => {
|
it('should return IconQuestionMark for an unsupported field type', () => {
|
||||||
const result = getFieldIcon('string');
|
expect(getFieldIcon('totally-unknown-type' as any)).toBe(
|
||||||
expect(result).toBe('IconQuestionMark');
|
'IconQuestionMark',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
it('should return IconQuestionMark for undefined', () => {
|
||||||
it('should return IconQuestionMark for number type', () => {
|
expect(getFieldIcon(undefined)).toBe('IconQuestionMark');
|
||||||
const result = getFieldIcon('number');
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
});
|
||||||
|
it('should return IconQuestionMark for null', () => {
|
||||||
it('should return IconQuestionMark for boolean type', () => {
|
expect(getFieldIcon(null as any)).toBe('IconQuestionMark');
|
||||||
const result = getFieldIcon('boolean');
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
});
|
||||||
|
it('should return IconQuestionMark for empty string', () => {
|
||||||
it('should return IconQuestionMark for object type', () => {
|
expect(getFieldIcon('' as any)).toBe('IconQuestionMark');
|
||||||
const result = getFieldIcon('object');
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for array type', () => {
|
|
||||||
const result = getFieldIcon('array');
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for unknown type', () => {
|
|
||||||
const result = getFieldIcon('unknown');
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('other FieldMetadataType values', () => {
|
describe('consistency', () => {
|
||||||
it('should return IconQuestionMark for DATE_TIME field type', () => {
|
it('should return the same icon for the same field type', () => {
|
||||||
const result = getFieldIcon(FieldMetadataType.DATE_TIME);
|
const result1 = getFieldIcon(FieldMetadataType.TEXT);
|
||||||
expect(result).toBe('IconQuestionMark');
|
const result2 = getFieldIcon(FieldMetadataType.TEXT);
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for EMAILS field type', () => {
|
|
||||||
const result = getFieldIcon(FieldMetadataType.EMAILS);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for PHONES field type', () => {
|
|
||||||
const result = getFieldIcon(FieldMetadataType.PHONES);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for LINKS field type', () => {
|
|
||||||
const result = getFieldIcon(FieldMetadataType.LINKS);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for CURRENCY field type', () => {
|
|
||||||
const result = getFieldIcon(FieldMetadataType.CURRENCY);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for SELECT field type', () => {
|
|
||||||
const result = getFieldIcon(FieldMetadataType.SELECT);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for MULTI_SELECT field type', () => {
|
|
||||||
const result = getFieldIcon(FieldMetadataType.MULTI_SELECT);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for RELATION field type', () => {
|
|
||||||
const result = getFieldIcon(FieldMetadataType.RELATION);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for UUID field type', () => {
|
|
||||||
const result = getFieldIcon(FieldMetadataType.UUID);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for RAW_JSON field type', () => {
|
|
||||||
const result = getFieldIcon(FieldMetadataType.RAW_JSON);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for FULL_NAME field type', () => {
|
|
||||||
const result = getFieldIcon(FieldMetadataType.FULL_NAME);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for ADDRESS field type', () => {
|
|
||||||
const result = getFieldIcon(FieldMetadataType.ADDRESS);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for ARRAY field type', () => {
|
|
||||||
const result = getFieldIcon(FieldMetadataType.ARRAY);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('edge cases', () => {
|
|
||||||
it('should return IconQuestionMark for undefined field type', () => {
|
|
||||||
const result = getFieldIcon(undefined);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for null field type', () => {
|
|
||||||
const result = getFieldIcon(null as any);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for empty string field type', () => {
|
|
||||||
const result = getFieldIcon('' as any);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for invalid field type', () => {
|
|
||||||
const result = getFieldIcon('INVALID_TYPE' as any);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('icon mapping consistency', () => {
|
|
||||||
it('should return consistent icons for the same field type', () => {
|
|
||||||
const fieldType = FieldMetadataType.TEXT;
|
|
||||||
const result1 = getFieldIcon(fieldType);
|
|
||||||
const result2 = getFieldIcon(fieldType);
|
|
||||||
|
|
||||||
expect(result1).toBe(result2);
|
expect(result1).toBe(result2);
|
||||||
expect(result1).toBe('IconAbc');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have unique icons for different supported field types', () => {
|
|
||||||
const textIcon = getFieldIcon(FieldMetadataType.TEXT);
|
|
||||||
const numberIcon = getFieldIcon(FieldMetadataType.NUMBER);
|
|
||||||
const booleanIcon = getFieldIcon(FieldMetadataType.BOOLEAN);
|
|
||||||
const dateIcon = getFieldIcon(FieldMetadataType.DATE);
|
|
||||||
|
|
||||||
const icons = [textIcon, numberIcon, booleanIcon, dateIcon];
|
|
||||||
const uniqueIcons = new Set(icons);
|
|
||||||
|
|
||||||
expect(uniqueIcons.size).toBe(4);
|
|
||||||
expect(icons).toEqual([
|
|
||||||
'IconAbc',
|
|
||||||
'IconText',
|
|
||||||
'IconCheckbox',
|
|
||||||
'IconCalendarEvent',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return IconQuestionMark for all unsupported field types', () => {
|
|
||||||
const unsupportedTypes = UNSUPPORTED_FIELD_TYPES;
|
|
||||||
|
|
||||||
unsupportedTypes.forEach((fieldType) => {
|
|
||||||
const result = getFieldIcon(fieldType as UnsupportedFieldType);
|
|
||||||
expect(result).toBe('IconQuestionMark');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('function behavior', () => {
|
|
||||||
it('should be a pure function with no side effects', () => {
|
|
||||||
const fieldType = FieldMetadataType.TEXT;
|
|
||||||
const result1 = getFieldIcon(fieldType);
|
|
||||||
const result2 = getFieldIcon(fieldType);
|
|
||||||
const result3 = getFieldIcon(fieldType);
|
|
||||||
|
|
||||||
expect(result1).toBe(result2);
|
|
||||||
expect(result2).toBe(result3);
|
|
||||||
expect(result1).toBe('IconAbc');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle all possible InputSchemaPropertyType values', () => {
|
|
||||||
const allPossibleTypes = [
|
|
||||||
...UNSUPPORTED_FIELD_TYPES,
|
|
||||||
FieldMetadataType.TEXT,
|
|
||||||
FieldMetadataType.NUMBER,
|
|
||||||
FieldMetadataType.BOOLEAN,
|
|
||||||
FieldMetadataType.DATE,
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
allPossibleTypes.forEach((fieldType) => {
|
|
||||||
const result = getFieldIcon(fieldType as UnsupportedFieldType);
|
|
||||||
expect(typeof result).toBe('string');
|
|
||||||
expect(result.length).toBeGreaterThan(0);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { FieldMetadataType } from 'twenty-shared/types';
|
import { FieldMetadataType } from 'twenty-shared/types';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
import { WorkflowFormFieldType } from '../../types/WorkflowFormFieldType';
|
|
||||||
import { getDefaultFormFieldSettings } from '../getDefaultFormFieldSettings';
|
import { getDefaultFormFieldSettings } from '../getDefaultFormFieldSettings';
|
||||||
|
|
||||||
jest.mock('uuid', () => ({
|
jest.mock('uuid', () => ({
|
||||||
@ -12,206 +11,114 @@ describe('getDefaultFormFieldSettings', () => {
|
|||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('FieldMetadataType.TEXT', () => {
|
it('should return correct default settings for TEXT field type', () => {
|
||||||
it('should return correct default settings for TEXT field type', () => {
|
const result = getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
||||||
const result = getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
expect(result).toEqual({
|
||||||
|
id: 'test-uuid-123',
|
||||||
expect(result).toEqual({
|
name: 'text',
|
||||||
id: 'test-uuid-123',
|
label: 'Text',
|
||||||
name: 'text',
|
placeholder: 'Enter your text',
|
||||||
label: 'Text',
|
|
||||||
placeholder: 'Enter your text',
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('FieldMetadataType.NUMBER', () => {
|
it('should return correct default settings for NUMBER field type', () => {
|
||||||
it('should return correct default settings for NUMBER field type', () => {
|
const result = getDefaultFormFieldSettings(FieldMetadataType.NUMBER);
|
||||||
const result = getDefaultFormFieldSettings(FieldMetadataType.NUMBER);
|
expect(result).toEqual({
|
||||||
|
id: 'test-uuid-123',
|
||||||
expect(result).toEqual({
|
name: 'number',
|
||||||
id: 'test-uuid-123',
|
label: 'Number',
|
||||||
name: 'number',
|
placeholder: '1000',
|
||||||
label: 'Number',
|
|
||||||
placeholder: '1000',
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('FieldMetadataType.DATE', () => {
|
it('should return correct default settings for DATE field type', () => {
|
||||||
it('should return correct default settings for DATE field type', () => {
|
const result = getDefaultFormFieldSettings(FieldMetadataType.DATE);
|
||||||
const result = getDefaultFormFieldSettings(FieldMetadataType.DATE);
|
expect(result).toEqual({
|
||||||
|
id: 'test-uuid-123',
|
||||||
expect(result).toEqual({
|
name: 'date',
|
||||||
id: 'test-uuid-123',
|
label: 'Date',
|
||||||
name: 'date',
|
placeholder: 'mm/dd/yyyy',
|
||||||
label: 'Date',
|
|
||||||
placeholder: 'mm/dd/yyyy',
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('RECORD type', () => {
|
it('should return correct default settings for RECORD field type', () => {
|
||||||
it('should return correct default settings for RECORD field type', () => {
|
const result = getDefaultFormFieldSettings('RECORD');
|
||||||
const result = getDefaultFormFieldSettings('RECORD');
|
expect(result).toEqual({
|
||||||
|
id: 'test-uuid-123',
|
||||||
expect(result).toEqual({
|
name: 'record',
|
||||||
id: 'test-uuid-123',
|
label: 'Record',
|
||||||
name: 'record',
|
placeholder: 'Select a Company',
|
||||||
label: 'Record',
|
settings: {
|
||||||
placeholder: 'Select a Company',
|
|
||||||
settings: {
|
|
||||||
objectName: 'company',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('UUID generation', () => {
|
|
||||||
it('should generate unique UUID for each call', () => {
|
|
||||||
getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
|
||||||
getDefaultFormFieldSettings(FieldMetadataType.NUMBER);
|
|
||||||
|
|
||||||
expect(v4).toHaveBeenCalledTimes(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('return value structure', () => {
|
|
||||||
it('should return object with required properties for TEXT type', () => {
|
|
||||||
const result = getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
|
||||||
|
|
||||||
expect(result).toHaveProperty('id');
|
|
||||||
expect(result).toHaveProperty('name');
|
|
||||||
expect(result).toHaveProperty('label');
|
|
||||||
expect(result).toHaveProperty('placeholder');
|
|
||||||
expect(result).not.toHaveProperty('settings');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return object with required properties for NUMBER type', () => {
|
|
||||||
const result = getDefaultFormFieldSettings(FieldMetadataType.NUMBER);
|
|
||||||
|
|
||||||
expect(result).toHaveProperty('id');
|
|
||||||
expect(result).toHaveProperty('name');
|
|
||||||
expect(result).toHaveProperty('label');
|
|
||||||
expect(result).toHaveProperty('placeholder');
|
|
||||||
expect(result).not.toHaveProperty('settings');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return object with required properties for DATE type', () => {
|
|
||||||
const result = getDefaultFormFieldSettings(FieldMetadataType.DATE);
|
|
||||||
|
|
||||||
expect(result).toHaveProperty('id');
|
|
||||||
expect(result).toHaveProperty('name');
|
|
||||||
expect(result).toHaveProperty('label');
|
|
||||||
expect(result).toHaveProperty('placeholder');
|
|
||||||
expect(result).not.toHaveProperty('settings');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return object with required properties for RECORD type', () => {
|
|
||||||
const result = getDefaultFormFieldSettings('RECORD');
|
|
||||||
|
|
||||||
expect(result).toHaveProperty('id');
|
|
||||||
expect(result).toHaveProperty('name');
|
|
||||||
expect(result).toHaveProperty('label');
|
|
||||||
expect(result).toHaveProperty('placeholder');
|
|
||||||
expect(result).toHaveProperty('settings');
|
|
||||||
expect(result.settings).toHaveProperty('objectName');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('field type specific values', () => {
|
|
||||||
it('should have correct name values for each field type', () => {
|
|
||||||
const textResult = getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
|
||||||
const numberResult = getDefaultFormFieldSettings(
|
|
||||||
FieldMetadataType.NUMBER,
|
|
||||||
);
|
|
||||||
const dateResult = getDefaultFormFieldSettings(FieldMetadataType.DATE);
|
|
||||||
const recordResult = getDefaultFormFieldSettings('RECORD');
|
|
||||||
|
|
||||||
expect(textResult.name).toBe('text');
|
|
||||||
expect(numberResult.name).toBe('number');
|
|
||||||
expect(dateResult.name).toBe('date');
|
|
||||||
expect(recordResult.name).toBe('record');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have correct label values for each field type', () => {
|
|
||||||
const textResult = getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
|
||||||
const numberResult = getDefaultFormFieldSettings(
|
|
||||||
FieldMetadataType.NUMBER,
|
|
||||||
);
|
|
||||||
const dateResult = getDefaultFormFieldSettings(FieldMetadataType.DATE);
|
|
||||||
const recordResult = getDefaultFormFieldSettings('RECORD');
|
|
||||||
|
|
||||||
expect(textResult.label).toBe('Text');
|
|
||||||
expect(numberResult.label).toBe('Number');
|
|
||||||
expect(dateResult.label).toBe('Date');
|
|
||||||
expect(recordResult.label).toBe('Record');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have correct placeholder values for each field type', () => {
|
|
||||||
const textResult = getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
|
||||||
const numberResult = getDefaultFormFieldSettings(
|
|
||||||
FieldMetadataType.NUMBER,
|
|
||||||
);
|
|
||||||
const dateResult = getDefaultFormFieldSettings(FieldMetadataType.DATE);
|
|
||||||
const recordResult = getDefaultFormFieldSettings('RECORD');
|
|
||||||
|
|
||||||
expect(textResult.placeholder).toBe('Enter your text');
|
|
||||||
expect(numberResult.placeholder).toBe('1000');
|
|
||||||
expect(dateResult.placeholder).toBe('mm/dd/yyyy');
|
|
||||||
expect(recordResult.placeholder).toBe('Select a Company');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('RECORD type specific settings', () => {
|
|
||||||
it('should have correct settings object for RECORD type', () => {
|
|
||||||
const result = getDefaultFormFieldSettings('RECORD');
|
|
||||||
|
|
||||||
expect(result.settings).toEqual({
|
|
||||||
objectName: 'company',
|
objectName: 'company',
|
||||||
});
|
},
|
||||||
});
|
|
||||||
|
|
||||||
it('should have objectName set to company for RECORD type', () => {
|
|
||||||
const result = getDefaultFormFieldSettings('RECORD');
|
|
||||||
|
|
||||||
expect(result.settings?.objectName).toBe('company');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('consistency', () => {
|
it('should generate unique UUID for each call', () => {
|
||||||
it('should return consistent results for the same field type', () => {
|
getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
||||||
const result1 = getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
getDefaultFormFieldSettings(FieldMetadataType.NUMBER);
|
||||||
const result2 = getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
expect(v4).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
expect(result1).toEqual(result2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return different results for different field types', () => {
|
|
||||||
const textResult = getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
|
||||||
const numberResult = getDefaultFormFieldSettings(
|
|
||||||
FieldMetadataType.NUMBER,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(textResult).not.toEqual(numberResult);
|
|
||||||
expect(textResult.name).not.toBe(numberResult.name);
|
|
||||||
expect(textResult.label).not.toBe(numberResult.label);
|
|
||||||
expect(textResult.placeholder).not.toBe(numberResult.placeholder);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('type safety', () => {
|
it('should return object with required properties for TEXT type', () => {
|
||||||
it('should accept all valid WorkflowFormFieldType values', () => {
|
const result = getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
||||||
const validTypes: WorkflowFormFieldType[] = [
|
expect(result).toHaveProperty('id');
|
||||||
FieldMetadataType.TEXT,
|
expect(result).toHaveProperty('name');
|
||||||
FieldMetadataType.NUMBER,
|
expect(result).toHaveProperty('label');
|
||||||
FieldMetadataType.DATE,
|
expect(result).toHaveProperty('placeholder');
|
||||||
'RECORD',
|
expect(result).not.toHaveProperty('settings');
|
||||||
];
|
});
|
||||||
|
|
||||||
validTypes.forEach((type) => {
|
it('should return object with required properties for RECORD type', () => {
|
||||||
expect(() => getDefaultFormFieldSettings(type)).not.toThrow();
|
const result = getDefaultFormFieldSettings('RECORD');
|
||||||
});
|
expect(result).toHaveProperty('id');
|
||||||
});
|
expect(result).toHaveProperty('name');
|
||||||
|
expect(result).toHaveProperty('label');
|
||||||
|
expect(result).toHaveProperty('placeholder');
|
||||||
|
expect(result).toHaveProperty('settings');
|
||||||
|
expect(result.settings).toHaveProperty('objectName');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have correct name, label, and placeholder for each field type', () => {
|
||||||
|
const textResult = getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
||||||
|
expect(textResult.name).toBe('text');
|
||||||
|
expect(textResult.label).toBe('Text');
|
||||||
|
expect(textResult.placeholder).toBe('Enter your text');
|
||||||
|
|
||||||
|
const numberResult = getDefaultFormFieldSettings(FieldMetadataType.NUMBER);
|
||||||
|
expect(numberResult.name).toBe('number');
|
||||||
|
expect(numberResult.label).toBe('Number');
|
||||||
|
expect(numberResult.placeholder).toBe('1000');
|
||||||
|
|
||||||
|
const dateResult = getDefaultFormFieldSettings(FieldMetadataType.DATE);
|
||||||
|
expect(dateResult.name).toBe('date');
|
||||||
|
expect(dateResult.label).toBe('Date');
|
||||||
|
expect(dateResult.placeholder).toBe('mm/dd/yyyy');
|
||||||
|
|
||||||
|
const recordResult = getDefaultFormFieldSettings('RECORD');
|
||||||
|
expect(recordResult.name).toBe('record');
|
||||||
|
expect(recordResult.label).toBe('Record');
|
||||||
|
expect(recordResult.placeholder).toBe('Select a Company');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have correct settings object for RECORD type', () => {
|
||||||
|
const result = getDefaultFormFieldSettings('RECORD');
|
||||||
|
expect(result.settings).toEqual({ objectName: 'company' });
|
||||||
|
expect(result.settings?.objectName).toBe('company');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return consistent results for the same field type', () => {
|
||||||
|
const result1 = getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
||||||
|
const result2 = getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
||||||
|
expect(result1).toEqual(result2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return different results for different field types', () => {
|
||||||
|
const textResult = getDefaultFormFieldSettings(FieldMetadataType.TEXT);
|
||||||
|
const numberResult = getDefaultFormFieldSettings(FieldMetadataType.NUMBER);
|
||||||
|
expect(textResult).not.toEqual(numberResult);
|
||||||
|
expect(textResult.name).not.toBe(numberResult.name);
|
||||||
|
expect(textResult.label).not.toBe(numberResult.label);
|
||||||
|
expect(textResult.placeholder).not.toBe(numberResult.placeholder);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { WorkflowActionType } from '@/workflow/types/Workflow';
|
|
||||||
import { Theme } from '@emotion/react';
|
import { Theme } from '@emotion/react';
|
||||||
import { COLOR, GRAY_SCALE } from 'twenty-ui/theme';
|
import { COLOR, GRAY_SCALE } from 'twenty-ui/theme';
|
||||||
import { getActionIconColorOrThrow } from '../getActionIconColorOrThrow';
|
import { getActionIconColorOrThrow } from '../getActionIconColorOrThrow';
|
||||||
@ -17,300 +16,112 @@ const mockTheme: Theme = {
|
|||||||
} as Theme;
|
} as Theme;
|
||||||
|
|
||||||
describe('getActionIconColorOrThrow', () => {
|
describe('getActionIconColorOrThrow', () => {
|
||||||
describe('action types that return orange color', () => {
|
it('should return orange color for CODE action type', () => {
|
||||||
it('should return orange color for CODE action type', () => {
|
expect(
|
||||||
const result = getActionIconColorOrThrow({
|
getActionIconColorOrThrow({ theme: mockTheme, actionType: 'CODE' }),
|
||||||
theme: mockTheme,
|
).toBe(mockTheme.color.orange);
|
||||||
actionType: 'CODE',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result).toBe(mockTheme.color.orange);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return orange color for HTTP_REQUEST action type', () => {
|
|
||||||
const result = getActionIconColorOrThrow({
|
|
||||||
theme: mockTheme,
|
|
||||||
actionType: 'HTTP_REQUEST',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result).toBe(mockTheme.color.orange);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('action types that return tertiary font color', () => {
|
it('should return tertiary font color for CREATE_RECORD action type', () => {
|
||||||
const recordActionTypes: WorkflowActionType[] = [
|
expect(
|
||||||
'CREATE_RECORD',
|
getActionIconColorOrThrow({
|
||||||
'UPDATE_RECORD',
|
|
||||||
'DELETE_RECORD',
|
|
||||||
'FIND_RECORDS',
|
|
||||||
'FORM',
|
|
||||||
];
|
|
||||||
|
|
||||||
recordActionTypes.forEach((actionType) => {
|
|
||||||
it(`should return tertiary font color for ${actionType} action type`, () => {
|
|
||||||
const result = getActionIconColorOrThrow({
|
|
||||||
theme: mockTheme,
|
|
||||||
actionType,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result).toBe(mockTheme.font.color.tertiary);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('action types that return blue color', () => {
|
|
||||||
it('should return blue color for SEND_EMAIL action type', () => {
|
|
||||||
const result = getActionIconColorOrThrow({
|
|
||||||
theme: mockTheme,
|
|
||||||
actionType: 'SEND_EMAIL',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result).toBe(mockTheme.color.blue);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('action types that return pink color', () => {
|
|
||||||
it('should return pink color for AI_AGENT action type', () => {
|
|
||||||
const result = getActionIconColorOrThrow({
|
|
||||||
theme: mockTheme,
|
|
||||||
actionType: 'AI_AGENT',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result).toBe(mockTheme.color.pink);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('FILTER action type', () => {
|
|
||||||
it('should throw an error for FILTER action type', () => {
|
|
||||||
expect(() => {
|
|
||||||
getActionIconColorOrThrow({
|
|
||||||
theme: mockTheme,
|
|
||||||
actionType: 'FILTER',
|
|
||||||
});
|
|
||||||
}).toThrow("The Filter action isn't meant to be displayed as a node.");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('theme object handling', () => {
|
|
||||||
it('should use the provided theme colors correctly', () => {
|
|
||||||
const customTheme: Theme = {
|
|
||||||
color: {
|
|
||||||
orange: COLOR.red,
|
|
||||||
blue: COLOR.purple,
|
|
||||||
pink: COLOR.turquoise,
|
|
||||||
},
|
|
||||||
font: {
|
|
||||||
color: {
|
|
||||||
tertiary: GRAY_SCALE.gray50,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as Theme;
|
|
||||||
|
|
||||||
expect(
|
|
||||||
getActionIconColorOrThrow({
|
|
||||||
theme: customTheme,
|
|
||||||
actionType: 'CODE',
|
|
||||||
}),
|
|
||||||
).toBe(COLOR.red);
|
|
||||||
|
|
||||||
expect(
|
|
||||||
getActionIconColorOrThrow({
|
|
||||||
theme: customTheme,
|
|
||||||
actionType: 'SEND_EMAIL',
|
|
||||||
}),
|
|
||||||
).toBe(COLOR.purple);
|
|
||||||
|
|
||||||
expect(
|
|
||||||
getActionIconColorOrThrow({
|
|
||||||
theme: customTheme,
|
|
||||||
actionType: 'AI_AGENT',
|
|
||||||
}),
|
|
||||||
).toBe(COLOR.turquoise);
|
|
||||||
|
|
||||||
expect(
|
|
||||||
getActionIconColorOrThrow({
|
|
||||||
theme: customTheme,
|
|
||||||
actionType: 'CREATE_RECORD',
|
|
||||||
}),
|
|
||||||
).toBe(GRAY_SCALE.gray50);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('type safety and exhaustive checking', () => {
|
|
||||||
it('should handle all valid action types without throwing unreachable errors', () => {
|
|
||||||
const validActionTypes: WorkflowActionType[] = [
|
|
||||||
'CODE',
|
|
||||||
'HTTP_REQUEST',
|
|
||||||
'CREATE_RECORD',
|
|
||||||
'UPDATE_RECORD',
|
|
||||||
'DELETE_RECORD',
|
|
||||||
'FIND_RECORDS',
|
|
||||||
'FORM',
|
|
||||||
'SEND_EMAIL',
|
|
||||||
'AI_AGENT',
|
|
||||||
];
|
|
||||||
|
|
||||||
validActionTypes.forEach((actionType) => {
|
|
||||||
expect(() => {
|
|
||||||
getActionIconColorOrThrow({
|
|
||||||
theme: mockTheme,
|
|
||||||
actionType,
|
|
||||||
});
|
|
||||||
}).not.toThrow();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return consistent color values for the same action type', () => {
|
|
||||||
const actionType: WorkflowActionType = 'CODE';
|
|
||||||
const result1 = getActionIconColorOrThrow({
|
|
||||||
theme: mockTheme,
|
|
||||||
actionType,
|
|
||||||
});
|
|
||||||
const result2 = getActionIconColorOrThrow({
|
|
||||||
theme: mockTheme,
|
|
||||||
actionType,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result1).toBe(result2);
|
|
||||||
expect(result1).toBe(mockTheme.color.orange);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('color grouping logic', () => {
|
|
||||||
it('should group CODE and HTTP_REQUEST actions with orange color', () => {
|
|
||||||
const orangeActions: WorkflowActionType[] = ['CODE', 'HTTP_REQUEST'];
|
|
||||||
|
|
||||||
orangeActions.forEach((actionType) => {
|
|
||||||
const result = getActionIconColorOrThrow({
|
|
||||||
theme: mockTheme,
|
|
||||||
actionType,
|
|
||||||
});
|
|
||||||
expect(result).toBe(mockTheme.color.orange);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should group record-related actions with tertiary font color', () => {
|
|
||||||
const recordActions: WorkflowActionType[] = [
|
|
||||||
'CREATE_RECORD',
|
|
||||||
'UPDATE_RECORD',
|
|
||||||
'DELETE_RECORD',
|
|
||||||
'FIND_RECORDS',
|
|
||||||
'FORM',
|
|
||||||
];
|
|
||||||
|
|
||||||
recordActions.forEach((actionType) => {
|
|
||||||
const result = getActionIconColorOrThrow({
|
|
||||||
theme: mockTheme,
|
|
||||||
actionType,
|
|
||||||
});
|
|
||||||
expect(result).toBe(mockTheme.font.color.tertiary);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have unique colors for different action categories', () => {
|
|
||||||
const orangeResult = getActionIconColorOrThrow({
|
|
||||||
theme: mockTheme,
|
|
||||||
actionType: 'CODE',
|
|
||||||
});
|
|
||||||
|
|
||||||
const tertiaryResult = getActionIconColorOrThrow({
|
|
||||||
theme: mockTheme,
|
theme: mockTheme,
|
||||||
actionType: 'CREATE_RECORD',
|
actionType: 'CREATE_RECORD',
|
||||||
});
|
}),
|
||||||
|
).toBe(mockTheme.font.color.tertiary);
|
||||||
const blueResult = getActionIconColorOrThrow({
|
|
||||||
theme: mockTheme,
|
|
||||||
actionType: 'SEND_EMAIL',
|
|
||||||
});
|
|
||||||
|
|
||||||
const pinkResult = getActionIconColorOrThrow({
|
|
||||||
theme: mockTheme,
|
|
||||||
actionType: 'AI_AGENT',
|
|
||||||
});
|
|
||||||
|
|
||||||
const colors = [orangeResult, tertiaryResult, blueResult, pinkResult];
|
|
||||||
const uniqueColors = new Set(colors);
|
|
||||||
expect(uniqueColors.size).toBe(4);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('error handling edge cases', () => {
|
it('should return blue color for SEND_EMAIL action type', () => {
|
||||||
it('should handle theme object with missing properties gracefully', () => {
|
expect(
|
||||||
const incompleteTheme: Theme = {
|
getActionIconColorOrThrow({ theme: mockTheme, actionType: 'SEND_EMAIL' }),
|
||||||
|
).toBe(mockTheme.color.blue);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return pink color for AI_AGENT action type', () => {
|
||||||
|
expect(
|
||||||
|
getActionIconColorOrThrow({ theme: mockTheme, actionType: 'AI_AGENT' }),
|
||||||
|
).toBe(mockTheme.color.pink);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error for FILTER action type', () => {
|
||||||
|
expect(() => {
|
||||||
|
getActionIconColorOrThrow({ theme: mockTheme, actionType: 'FILTER' });
|
||||||
|
}).toThrow("The Filter action isn't meant to be displayed as a node.");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use the provided theme colors correctly', () => {
|
||||||
|
const customTheme: Theme = {
|
||||||
|
color: {
|
||||||
|
orange: COLOR.red,
|
||||||
|
blue: COLOR.purple,
|
||||||
|
pink: COLOR.turquoise,
|
||||||
|
},
|
||||||
|
font: {
|
||||||
color: {
|
color: {
|
||||||
orange: COLOR.orange,
|
tertiary: GRAY_SCALE.gray50,
|
||||||
},
|
},
|
||||||
font: {
|
},
|
||||||
color: {
|
} as Theme;
|
||||||
tertiary: GRAY_SCALE.gray40,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as Theme;
|
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
getActionIconColorOrThrow({
|
getActionIconColorOrThrow({ theme: customTheme, actionType: 'CODE' }),
|
||||||
theme: incompleteTheme,
|
).toBe(COLOR.red);
|
||||||
actionType: 'CODE',
|
expect(
|
||||||
}),
|
getActionIconColorOrThrow({
|
||||||
).toBe(COLOR.orange);
|
theme: customTheme,
|
||||||
|
actionType: 'SEND_EMAIL',
|
||||||
|
}),
|
||||||
|
).toBe(COLOR.purple);
|
||||||
|
expect(
|
||||||
|
getActionIconColorOrThrow({ theme: customTheme, actionType: 'AI_AGENT' }),
|
||||||
|
).toBe(COLOR.turquoise);
|
||||||
|
expect(
|
||||||
|
getActionIconColorOrThrow({
|
||||||
|
theme: customTheme,
|
||||||
|
actionType: 'CREATE_RECORD',
|
||||||
|
}),
|
||||||
|
).toBe(GRAY_SCALE.gray50);
|
||||||
|
});
|
||||||
|
|
||||||
expect(
|
it('should return undefined when blue color is missing for SEND_EMAIL action', () => {
|
||||||
getActionIconColorOrThrow({
|
const themeWithoutBlue: Theme = {
|
||||||
theme: incompleteTheme,
|
color: {
|
||||||
actionType: 'CREATE_RECORD',
|
orange: COLOR.orange,
|
||||||
}),
|
pink: COLOR.pink,
|
||||||
).toBe(GRAY_SCALE.gray40);
|
},
|
||||||
});
|
font: {
|
||||||
|
|
||||||
it('should return undefined when blue color is missing for SEND_EMAIL action', () => {
|
|
||||||
const themeWithoutBlue: Theme = {
|
|
||||||
color: {
|
color: {
|
||||||
orange: COLOR.orange,
|
tertiary: GRAY_SCALE.gray40,
|
||||||
pink: COLOR.pink,
|
|
||||||
},
|
},
|
||||||
font: {
|
},
|
||||||
color: {
|
} as Theme;
|
||||||
tertiary: GRAY_SCALE.gray40,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as Theme;
|
|
||||||
|
|
||||||
const result = getActionIconColorOrThrow({
|
expect(
|
||||||
|
getActionIconColorOrThrow({
|
||||||
theme: themeWithoutBlue,
|
theme: themeWithoutBlue,
|
||||||
actionType: 'SEND_EMAIL',
|
actionType: 'SEND_EMAIL',
|
||||||
|
}),
|
||||||
|
).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle null theme gracefully', () => {
|
||||||
|
expect(() => {
|
||||||
|
getActionIconColorOrThrow({
|
||||||
|
theme: null as unknown as Theme,
|
||||||
|
actionType: 'CODE',
|
||||||
});
|
});
|
||||||
|
}).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
expect(result).toBeUndefined();
|
it('should return the same color for the same action type', () => {
|
||||||
|
const result1 = getActionIconColorOrThrow({
|
||||||
|
theme: mockTheme,
|
||||||
|
actionType: 'CODE',
|
||||||
});
|
});
|
||||||
|
const result2 = getActionIconColorOrThrow({
|
||||||
it('should return undefined when pink color is missing for AI_AGENT action', () => {
|
theme: mockTheme,
|
||||||
const themeWithoutPink: Theme = {
|
actionType: 'CODE',
|
||||||
color: {
|
|
||||||
orange: COLOR.orange,
|
|
||||||
blue: COLOR.blue,
|
|
||||||
},
|
|
||||||
font: {
|
|
||||||
color: {
|
|
||||||
tertiary: GRAY_SCALE.gray40,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as Theme;
|
|
||||||
|
|
||||||
const result = getActionIconColorOrThrow({
|
|
||||||
theme: themeWithoutPink,
|
|
||||||
actionType: 'AI_AGENT',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle null or undefined theme gracefully', () => {
|
|
||||||
expect(() => {
|
|
||||||
getActionIconColorOrThrow({
|
|
||||||
theme: null as unknown as Theme,
|
|
||||||
actionType: 'CODE',
|
|
||||||
});
|
|
||||||
}).toThrow();
|
|
||||||
});
|
});
|
||||||
|
expect(result1).toBe(result2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user