Skip to content

Commit

Permalink
Merge branch 'feat/state-mgmt-migration-1' into fix/ignored-state-update
Browse files Browse the repository at this point in the history
  • Loading branch information
git-babel authored Jan 10, 2025
2 parents ebe18bd + 82a93b4 commit cfdd4d7
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 75 deletions.
24 changes: 24 additions & 0 deletions src/utils/__tests__/cloneMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { cloneMessage } from '../cloneMessage';

describe('cloneMessage', () => {
it('Should return a clone message', () => {
const oldMessage = {
isAdminMessage: true,
isUserMessage: true,
isFileMessage: true,
isMultipleFilesMessage: true,
applyParentMessage: true,
applyReactionEvent: true,
applyThreadInfoUpdateEvent: true,
extraProps: {
field1: true,
field2: 'test',
field3: 42,
},
};

const newMessage = cloneMessage(oldMessage);

expect(newMessage).toEqual(oldMessage);
});
});
29 changes: 29 additions & 0 deletions src/utils/__tests__/color.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { changeColorToClassName, Colors } from '../color';
import { truncateString } from '../index';

describe('color', () => {
it('check all color enum exist', () => {
expect(Colors.ONBACKGROUND_1).not.toBe(undefined);
expect(Colors.ONBACKGROUND_2).not.toBe(undefined);
expect(Colors.ONBACKGROUND_3).not.toBe(undefined);
expect(Colors.ONBACKGROUND_4).not.toBe(undefined);
expect(Colors.ONCONTENT_1).not.toBe(undefined);
expect(Colors.PRIMARY).not.toBe(undefined);
expect(Colors.ERROR).not.toBe(undefined);
});

it('change color enum to proper className', () => {
for (const color of Object.values(Colors)) {
expect(changeColorToClassName(color)).toBe(`sendbird-color--${color.toLowerCase().replace('_', '-')}`);
}

const nonColor = 'not-existing-color-enum-value';
expect(changeColorToClassName(nonColor)).toBe('');
});
});

describe('truncateString', () => {
it('truncate string properly by the given parameter', () => {
expect(truncateString('this is full string', 10)).toBe('this...ing');
});
});
48 changes: 48 additions & 0 deletions src/utils/__tests__/useDidMountEffect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { render, waitFor, screen } from '@testing-library/react';
import useDidMountEffect from '../useDidMountEffect';
import React, { useState } from 'react';

describe('useDidMountEffect', () => {
beforeEach(() => {
jest.restoreAllMocks();
});

it('ignore callback if didMount was false', () => {
const mockCallback = jest.fn();

const TestComponent = () => {
const [counter, setCounter] = useState(0);
useDidMountEffect(mockCallback, [counter]);
return (<button onClick={() => setCounter(counter + 1)}>increment</button>);
};

render(<TestComponent />);

expect(mockCallback).not.toHaveBeenCalled();
});

it('call callback if didMount was true', async () => {
const mockCallback = jest.fn();

const TestComponent = () => {
const [counter, setCounter] = useState(0);
useDidMountEffect(mockCallback, [counter]);
return (<button onClick={() => setCounter(counter + 1)}>increment</button>);
};

render(<TestComponent />);
const button = screen.getByText('increment');

await waitFor(() => {
button.click();
});

await waitFor(() => {
button.click();
});

await waitFor(() => {
expect(mockCallback).toHaveBeenCalledTimes(2);
});
});
});
40 changes: 36 additions & 4 deletions src/utils/__tests__/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
isFileMessage,
isUrl,
isUserMessage,
isMultipleFilesMessage, isDefaultChannelName, DEFAULT_GROUP_CHANNEL_NAME, DEFAULT_AI_CHATBOT_CHANNEL_NAME,
isMultipleFilesMessage, isDefaultChannelName, DEFAULT_GROUP_CHANNEL_NAME, DEFAULT_AI_CHATBOT_CHANNEL_NAME, arrayEqual,
} from '../index';
import { AdminMessage, FileMessage, MultipleFilesMessage, UserMessage } from '@sendbird/chat/message';
import { delay, deleteNullish } from '../utils';
Expand Down Expand Up @@ -237,6 +237,8 @@ describe('deleteNullish', () => {
});

describe('delay', () => {
const errorBound = 5;

it('should resolve after the specified time', async () => {
const start = Date.now();
const delayTime = 100;
Expand All @@ -247,7 +249,7 @@ describe('delay', () => {
const elapsed = end - start;

// Check if the elapsed time is at least the delay time
expect(elapsed).toBeGreaterThanOrEqual(delayTime);
expect(elapsed).toBeGreaterThanOrEqual(delayTime - errorBound);
});

it('should resolve immediately for 0 milliseconds', async () => {
Expand All @@ -259,7 +261,7 @@ describe('delay', () => {
const elapsed = end - start;

// Check if the elapsed time is very small
expect(elapsed).toBeLessThan(10);
expect(elapsed).toBeLessThan(errorBound);
});
it('should resolve immediately when no parameter is provided', async () => {
const start = Date.now();
Expand All @@ -269,7 +271,7 @@ describe('delay', () => {
const end = Date.now();
const elapsed = end - start;

expect(elapsed).toBeLessThan(10);
expect(elapsed).toBeLessThan(errorBound);
});
});

Expand Down Expand Up @@ -320,3 +322,33 @@ describe('isDefaultChannelName', () => {
expect(result).toBe(false);
});
});

describe('arrayEqual', () => {
it('return true if two arrays are equal', () => {
const arr1 = ['elem', 2, true];
const arr2 = ['elem', 2, true];

expect(arrayEqual(arr1, arr2)).toBe(true);
});

it('return false if two arrays are not equal', () => {
const arr1 = ['elem', 2, true];
const arr2 = ['elem', 42, false];

expect(arrayEqual(arr1, arr2)).toBe(false);
});

it('return false if two array doesn\'t have same length', () => {
const arr1 = ['elem', 2, true];
const arr2 = ['elem', 42];

expect(arrayEqual(arr1, arr2)).toBe(false);
});

it('return false if the one of parameter is not array', () => {
const arr1 = ['elem', 2, true];
const arr2 = {};

expect(arrayEqual(arr1, arr2)).toBe(false);
});
});
1 change: 0 additions & 1 deletion src/utils/color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ export enum Colors {
ONBACKGROUND_3 = 'ONBACKGROUND_3',
ONBACKGROUND_4 = 'ONBACKGROUND_4',
ONCONTENT_1 = 'ONCONTENT_1',
ONCONTENT_2 = 'ONCONTENT_2',
PRIMARY = 'PRIMARY',
ERROR = 'ERROR',
}
Expand Down
70 changes: 2 additions & 68 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import SendbirdChat, { Emoji, EmojiCategory, EmojiContainer, User } from '@sendbird/chat';
import { GroupChannel, Member, SendbirdGroupChat, GroupChannelListQuery, GroupChannelListOrder } from '@sendbird/chat/groupChannel';
import { Emoji, EmojiCategory, EmojiContainer, User } from '@sendbird/chat';
import { GroupChannel, Member, GroupChannelListQuery, GroupChannelListOrder } from '@sendbird/chat/groupChannel';
import {
AdminMessage,
BaseMessage,
Expand All @@ -10,7 +10,6 @@ import {
UploadedFileInfo,
UserMessage,
} from '@sendbird/chat/message';
import { OpenChannel, SendbirdOpenChat } from '@sendbird/chat/openChannel';
import { SendableMessage } from '@sendbird/chat/lib/__definition';

import { getOutgoingMessageState, OutgoingMessageStates } from './exports/getOutgoingMessageState';
Expand Down Expand Up @@ -217,13 +216,6 @@ const SendingMessageStatus: SendingMessageStatus = {
export type CoreMessageType = AdminMessage | UserMessage | FileMessage | MultipleFilesMessage;
export type SendableMessageType = UserMessage | FileMessage | MultipleFilesMessage;

export const isTextuallyNull = (text: string): boolean => {
if (text === '' || text === null) {
return true;
}
return false;
};

export const isMOVType = (type: string): boolean => type === 'video/quicktime';
/**
* @link: https://sendbird.atlassian.net/browse/SBISSUE-16031?focusedCommentId=270601
Expand Down Expand Up @@ -452,15 +444,6 @@ export const getClassName = (classNames: string | Array<string | Array<string>>)
: classNames
);

export const startsWithAtAndEndsWithBraces = (str: string) => {
const regex = /^\{@.*\}$/;
return regex.test(str);
};

export const removeAtAndBraces = (str: string) => {
return str.replace(/^\{@|}$/g, '');
};

export const isReactedBy = (userId: string, reaction: Reaction): boolean => (
reaction.userIds.some((reactorUserId: string): boolean => reactorUserId === userId)
);
Expand All @@ -480,33 +463,6 @@ export const getEmojiTooltipString = (reaction: Reaction, userId: string, member
.join(', ')}${you}`);
};

// TODO: Use the interface after language tranlsatation of Sendbird.js
interface UIKitStore {
stores: {
sdkStore: {
sdk: SendbirdChat | SendbirdOpenChat | SendbirdGroupChat,
},
userStore: {
user: User,
},
},
config: {
isReactionEnabled: boolean,
htmlTextDirection: HTMLTextDirection,
forceLeftToRightMessageLayout: boolean,
}
}
export const getCurrentUserId = (store: UIKitStore): string => (store?.stores?.userStore?.user?.userId);
export const getUseReaction = (store: UIKitStore, channel: GroupChannel | OpenChannel): boolean => {
if (!store?.config?.isReactionEnabled)
return false;
if (!store?.stores?.sdkStore?.sdk?.appInfo?.useReaction)
return false;
if (channel?.isGroupChannel())
return !((channel as GroupChannel).isBroadcast || (channel as GroupChannel).isSuper);
return store?.config?.isReactionEnabled;
};

export function getSuggestedReplies(message?: BaseMessage): string[] {
if (message?.extendedMessagePayload && Array.isArray(message?.extendedMessagePayload?.suggested_replies)) {
return message.extendedMessagePayload.suggested_replies;
Expand All @@ -515,22 +471,12 @@ export function getSuggestedReplies(message?: BaseMessage): string[] {
}
}

export const isMessageSentByMe = (
userId: string,
message: SendableMessageType,
): boolean => (
!!(userId && message?.sender?.userId && userId === message.sender.userId)
);

const URL_REG = /^((http|https):\/\/)?([a-z\d-]+\.)+[a-z]{2,}(\:[0-9]{1,5})?(\/[-a-zA-Z\d%_.~+&=]*)*(\?[;&a-zA-Z\d%_.~+=-]*)?(#\S*)?$/;
/** @deprecated
* URL detection in a message text will be handled in utils/tokens/tokenize.ts
*/
export const isUrl = (text: string): boolean => URL_REG.test(text);

const MENTION_TAG_REG = /\@\{.*?\}/i;
export const isMentionedText = (text: string): boolean => MENTION_TAG_REG.test(text);

export const truncateString = (fullStr: string, strLen?: number): string => {
if (!strLen) strLen = 40;
if (fullStr === null || fullStr === undefined) return '';
Expand Down Expand Up @@ -897,18 +843,6 @@ export const getChannelsWithUpsertedChannel = (
return sortChannelList(channels, order ?? GroupChannelListOrder.LATEST_LAST_MESSAGE);
};

export const getMatchedUserIds = (word: string, users: Array<User>, _template?: string): boolean => {
const template = _template || '@'; // Use global variable
// const matchedUserIds = [];
// users.map((user) => user?.userId).forEach((userId) => {
// if (word.indexOf(`${template}{${userId}}`) > -1) {
// matchedUserIds.push(userId);
// }
// });
// return matchedUserIds;
return users.map((user) => user?.userId).some((userId) => word.indexOf(`${template}{${userId}}`) > -1);
};

export enum StringObjType {
normal = 'normal',
mention = 'mention',
Expand Down
4 changes: 2 additions & 2 deletions src/utils/useDidMountEffect.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { useEffect, useState } from 'react';

const useDidMountEffect = (func: () => void, deps: Array<unknown>): void => {
const [didMount, setDidmount] = useState(false);
const [didMount, setDidMount] = useState(false);
useEffect(() => {
if (didMount) {
func();
} else {
setDidmount(true);
setDidMount(true);
}
}, deps);
};
Expand Down

0 comments on commit cfdd4d7

Please sign in to comment.