From 6384d60efc455f848e78c290d6e562befc47d112 Mon Sep 17 00:00:00 2001
From: Danish Ahmed Mirza <77742477+try-catch-stack@users.noreply.github.com>
Date: Fri, 20 May 2022 22:07:57 +0530
Subject: [PATCH] Chore: Migrate containers/Button to Typescript and Hooks
(#4071)
---
app/containers/Button/Button.stories.js | 28 +++++
app/containers/Button/Button.test.tsx | 71 +++++++++++
.../__snapshots__/Button.stories.storyshot | 11 ++
app/containers/Button/index.tsx | 113 +++++++++---------
app/containers/LoginServices.tsx | 1 -
app/containers/TwoFactor/index.tsx | 10 +-
app/containers/UIKit/Actions.tsx | 4 +-
app/containers/UIKit/DatePicker.tsx | 4 +-
app/containers/UIKit/MultiSelect/index.tsx | 2 +-
app/containers/UIKit/index.tsx | 2 -
app/containers/message/Attachments.tsx | 2 +-
app/views/CannedResponseDetail.tsx | 8 +-
.../CannedResponseItem.tsx | 1 -
.../CannedResponseItem.stories.storyshot | 2 +-
app/views/E2EEncryptionSecurityView.tsx | 2 -
app/views/E2EEnterYourPasswordView.tsx | 1 -
app/views/E2ESaveYourPasswordView.tsx | 3 -
app/views/ForgotPasswordView.tsx | 1 -
app/views/InviteUsersEditView/index.tsx | 3 +-
app/views/InviteUsersView/index.tsx | 4 +-
app/views/LivechatEditView.tsx | 2 +-
app/views/LoginView.tsx | 2 -
app/views/NewServerView/index.tsx | 2 -
app/views/ProfileView/index.tsx | 2 -
app/views/RegisterView.tsx | 1 -
app/views/RoomView/JoinCode.tsx | 2 -
app/views/RoomsListView/ServerDropdown.tsx | 1 -
app/views/SendEmailConfirmationView.tsx | 1 -
app/views/SetUsernameView.tsx | 1 -
app/views/WorkspaceView/index.tsx | 3 +-
.../stories/__snapshots__/Message.storyshot | 2 +-
storybook/stories/index.js | 1 +
32 files changed, 178 insertions(+), 115 deletions(-)
create mode 100644 app/containers/Button/Button.stories.js
create mode 100644 app/containers/Button/Button.test.tsx
create mode 100644 app/containers/Button/__snapshots__/Button.stories.storyshot
diff --git a/app/containers/Button/Button.stories.js b/app/containers/Button/Button.stories.js
new file mode 100644
index 00000000..165c8b49
--- /dev/null
+++ b/app/containers/Button/Button.stories.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import { storiesOf } from '@storybook/react-native';
+
+import Button from '.';
+
+const buttonProps = {
+ title: 'Press me!',
+ type: 'primary',
+ onPress: () => {},
+ testID: 'testButton',
+ fontSize: 16,
+ style: {
+ padding: 10,
+ justifyContent: 'center'
+ }
+};
+
+const stories = storiesOf('Button', module);
+
+stories.add('primary button', () => );
+
+stories.add('secondary button', () => );
+
+stories.add('loading button', () => );
+
+stories.add('disabled button', () => );
+
+stories.add('disabled loading button', () => );
diff --git a/app/containers/Button/Button.test.tsx b/app/containers/Button/Button.test.tsx
new file mode 100644
index 00000000..adbe1fb1
--- /dev/null
+++ b/app/containers/Button/Button.test.tsx
@@ -0,0 +1,71 @@
+import React from 'react';
+import { View } from 'react-native';
+import { fireEvent, render } from '@testing-library/react-native';
+
+import Button from '.';
+
+const onPressMock = jest.fn();
+
+const testProps = {
+ title: 'Press me!',
+ type: 'primary',
+ onPress: onPressMock,
+ testID: 'testButton',
+ initialText: 'Initial text',
+ textAfterPress: 'Button pressed!'
+};
+
+const TestButton = ({ loading = false, disabled = false }) => (
+
+
+
+);
+
+describe('ButtonTests', () => {
+ test('rendered', async () => {
+ const { findByTestId } = render();
+ const Button = await findByTestId(testProps.testID);
+ expect(Button).toBeTruthy();
+ });
+
+ test('rendered with correct title', async () => {
+ const { findByText } = render();
+ const ButtonTitle = await findByText(testProps.title);
+ expect(ButtonTitle).toBeTruthy();
+ expect(ButtonTitle.props.children).toEqual(testProps.title);
+ });
+
+ test('find button using accessibilityLabel', async () => {
+ const { findByA11yLabel } = render();
+ const Button = await findByA11yLabel(testProps.title);
+ expect(Button).toBeTruthy();
+ });
+
+ test('title not visible while loading', async () => {
+ const { queryByText } = render();
+ const ButtonTitle = await queryByText(testProps.title);
+ expect(ButtonTitle).toBeNull();
+ });
+
+ test('should not trigger onPress on disabled button', async () => {
+ const { findByTestId } = render();
+ const Button = await findByTestId(testProps.testID);
+ fireEvent.press(Button);
+ expect(onPressMock).not.toHaveBeenCalled();
+ });
+
+ test('should trigger onPress function on button press', async () => {
+ const { findByTestId } = render();
+ const Button = await findByTestId(testProps.testID);
+ fireEvent.press(Button);
+ expect(onPressMock).toHaveBeenCalled();
+ });
+});
diff --git a/app/containers/Button/__snapshots__/Button.stories.storyshot b/app/containers/Button/__snapshots__/Button.stories.storyshot
new file mode 100644
index 00000000..dfeacc87
--- /dev/null
+++ b/app/containers/Button/__snapshots__/Button.stories.storyshot
@@ -0,0 +1,11 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Storyshots Button disabled button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":2,\\"marginBottom\\":12,\\"backgroundColor\\":\\"#1d74f5\\",\\"opacity\\":0.3,\\"padding\\":10}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#ffffff\\",\\"fontSize\\":16},null],\\"accessibilityLabel\\":\\"Press me!\\"},\\"children\\":[\\"Press me!\\"]}]}"`;
+
+exports[`Storyshots Button disabled loading button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":2,\\"marginBottom\\":12,\\"backgroundColor\\":\\"#1d74f5\\",\\"opacity\\":0.3,\\"padding\\":10}},\\"children\\":[{\\"type\\":\\"ActivityIndicator\\",\\"props\\":{\\"animating\\":true,\\"color\\":\\"#ffffff\\",\\"hidesWhenStopped\\":true,\\"size\\":\\"small\\",\\"style\\":[{\\"padding\\":16,\\"flex\\":1},null]},\\"children\\":null}]}"`;
+
+exports[`Storyshots Button loading button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":2,\\"marginBottom\\":12,\\"backgroundColor\\":\\"#1d74f5\\",\\"padding\\":10,\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"ActivityIndicator\\",\\"props\\":{\\"animating\\":true,\\"color\\":\\"#ffffff\\",\\"hidesWhenStopped\\":true,\\"size\\":\\"small\\",\\"style\\":[{\\"padding\\":16,\\"flex\\":1},null]},\\"children\\":null}]}"`;
+
+exports[`Storyshots Button primary button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":2,\\"marginBottom\\":12,\\"backgroundColor\\":\\"#1d74f5\\",\\"padding\\":10,\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#ffffff\\",\\"fontSize\\":16},null],\\"accessibilityLabel\\":\\"Press me!\\"},\\"children\\":[\\"Press me!\\"]}]}"`;
+
+exports[`Storyshots Button secondary button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":2,\\"marginBottom\\":12,\\"backgroundColor\\":\\"#ffffff\\",\\"padding\\":10,\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#2f343d\\",\\"fontSize\\":16},null],\\"accessibilityLabel\\":\\"Press me!\\"},\\"children\\":[\\"Press me!\\"]}]}"`;
diff --git a/app/containers/Button/index.tsx b/app/containers/Button/index.tsx
index e30b4385..de53afd6 100644
--- a/app/containers/Button/index.tsx
+++ b/app/containers/Button/index.tsx
@@ -1,25 +1,20 @@
import React from 'react';
-import { StyleSheet, Text } from 'react-native';
-import Touchable from 'react-native-platform-touchable';
+import { StyleProp, StyleSheet, Text, TextStyle } from 'react-native';
+import Touchable, { PlatformTouchableProps } from 'react-native-platform-touchable';
-import { TSupportedThemes } from '../../theme';
-import { themes } from '../../lib/constants';
+import { useTheme } from '../../theme';
import sharedStyles from '../../views/Styles';
import ActivityIndicator from '../ActivityIndicator';
-interface IButtonProps {
+interface IButtonProps extends PlatformTouchableProps {
title: string;
- type: string;
- onPress(): void;
- disabled: boolean;
- backgroundColor: string;
- loading: boolean;
- theme: TSupportedThemes;
- color: string;
- fontSize: any;
- style: any;
- styleText?: any;
- testID: string;
+ onPress: () => void;
+ type?: string;
+ backgroundColor?: string;
+ loading?: boolean;
+ color?: string;
+ fontSize?: number;
+ styleText?: StyleProp[];
}
const styles = StyleSheet.create({
@@ -31,7 +26,6 @@ const styles = StyleSheet.create({
marginBottom: 12
},
text: {
- fontSize: 16,
...sharedStyles.textMedium,
...sharedStyles.textAlignCenter
},
@@ -40,47 +34,48 @@ const styles = StyleSheet.create({
}
});
-export default class Button extends React.PureComponent, any> {
- static defaultProps = {
- title: 'Press me!',
- type: 'primary',
- onPress: () => alert('It works!'),
- disabled: false,
- loading: false
- };
+const Button = ({
+ type = 'primary',
+ disabled = false,
+ loading = false,
+ fontSize = 16,
+ title,
+ onPress,
+ backgroundColor,
+ color,
+ style,
+ styleText,
+ ...otherProps
+}: IButtonProps): React.ReactElement => {
+ const { colors } = useTheme();
+ const isPrimary = type === 'primary';
- render() {
- const { title, type, onPress, disabled, backgroundColor, color, loading, style, theme, fontSize, styleText, ...otherProps } =
- this.props;
- const isPrimary = type === 'primary';
-
- let textColor = isPrimary ? themes[theme!].buttonText : themes[theme!].bodyText;
- if (color) {
- textColor = color;
- }
-
- return (
-
- {loading ? (
-
- ) : (
-
- {title}
-
- )}
-
- );
+ let textColor = isPrimary ? colors.buttonText : colors.bodyText;
+ if (color) {
+ textColor = color;
}
-}
+
+ return (
+
+ {loading ? (
+
+ ) : (
+
+ {title}
+
+ )}
+
+ );
+};
+
+export default Button;
diff --git a/app/containers/LoginServices.tsx b/app/containers/LoginServices.tsx
index e6feac63..d596b382 100644
--- a/app/containers/LoginServices.tsx
+++ b/app/containers/LoginServices.tsx
@@ -327,7 +327,6 @@ class LoginServices extends React.PureComponent
diff --git a/app/containers/TwoFactor/index.tsx b/app/containers/TwoFactor/index.tsx
index 31f68c2e..8aa6a16d 100644
--- a/app/containers/TwoFactor/index.tsx
+++ b/app/containers/TwoFactor/index.tsx
@@ -139,16 +139,8 @@ const TwoFactor = React.memo(({ isMasterDetail }: { isMasterDetail: boolean }) =
backgroundColor={themes[theme].chatComponentBackground}
style={styles.button}
onPress={onCancel}
- theme={theme}
- />
-
+
diff --git a/app/containers/UIKit/Actions.tsx b/app/containers/UIKit/Actions.tsx
index ad267013..c8bf9ff5 100644
--- a/app/containers/UIKit/Actions.tsx
+++ b/app/containers/UIKit/Actions.tsx
@@ -4,10 +4,8 @@ import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
import Button from '../Button';
import I18n from '../../i18n';
import { IActions } from './interfaces';
-import { useTheme } from '../../theme';
export const Actions = ({ blockId, appId, elements, parser }: IActions) => {
- const { theme } = useTheme();
const [showMoreVisible, setShowMoreVisible] = useState(() => elements && elements.length > 5);
const renderedElements = showMoreVisible ? elements?.slice(0, 5) : elements;
@@ -18,7 +16,7 @@ export const Actions = ({ blockId, appId, elements, parser }: IActions) => {
return (
<>
- {showMoreVisible &&