#24744 Converted ./components/spinner_button.tsx from Class Component to Function Component (#24804)

* Converted [./components/spinner_button.tsx] to functional component

* Converted [./components/spinner_button.tsx] to functional component

* [./components/spinner_button.tsx]: wrapped the component with react.memo + removed default props + use multi-lines in args

* [./components/spinner_button.tsx]:
- fix lint errors in spinner button
- fix error in missing prop on spinnerButton component

* [./components/spinner_button.tsx]:
- convert class component to functional component - fix lint errors in spinner button

* fix:[spinner_button]: fix lint errors

* - fix: [add_emoji.tsx]: add an id selector to the SpinnerButton to fix issue in unit test for this file.
- fix: [add_emoji.test.tsx]: find the saveButton with id selector instead of using element directly (was causing test fai)
- update test snapshots

* fix[add_emoji]: replaced id with data-testid to be used in unit test

---------

Co-authored-by: Noha M <33437197+NohaaAa@users.noreply.github.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
Noha M
2023-10-31 11:35:01 +02:00
committed by GitHub
parent b4c9eddca8
commit 3812de0dec
11 changed files with 63 additions and 60 deletions

View File

@@ -202,7 +202,7 @@ exports[`AppsFormComponent should set match snapshot 1`] = `
id="interactive_dialog.cancel"
/>
</button>
<SpinnerButton
<Memo(SpinnerButton)
autoFocus={false}
className="btn btn-primary save-button"
id="appsModalSubmit"
@@ -215,7 +215,7 @@ exports[`AppsFormComponent should set match snapshot 1`] = `
defaultMessage="Submit"
id="interactive_dialog.submit"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
</div>
</ModalFooter>
</form>

View File

@@ -121,8 +121,9 @@ exports[`components/emoji/components/AddEmoji should match snapshot 1`] = `
id="add_emoji.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
data-testid="save-button"
onClick={[Function]}
spinning={false}
spinningText="Saving..."
@@ -132,7 +133,7 @@ exports[`components/emoji/components/AddEmoji should match snapshot 1`] = `
defaultMessage="Save"
id="add_emoji.save"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
</div>
</form>
</div>
@@ -296,8 +297,9 @@ exports[`components/emoji/components/AddEmoji should select a file and match sna
id="add_emoji.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
data-testid="save-button"
onClick={[Function]}
spinning={false}
spinningText="Saving..."
@@ -307,7 +309,7 @@ exports[`components/emoji/components/AddEmoji should select a file and match sna
defaultMessage="Save"
id="add_emoji.save"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
</div>
</form>
</div>
@@ -435,8 +437,9 @@ exports[`components/emoji/components/AddEmoji should update emoji name and match
id="add_emoji.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
data-testid="save-button"
onClick={[Function]}
spinning={false}
spinningText="Saving..."
@@ -446,7 +449,7 @@ exports[`components/emoji/components/AddEmoji should update emoji name and match
defaultMessage="Save"
id="add_emoji.save"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
</div>
</form>
</div>

View File

@@ -202,7 +202,7 @@ describe('components/emoji/components/AddEmoji', () => {
const file = new Blob([image], {type: 'image/png'});
wrapper.setState({image: file as File, imageUrl: image});
const saveButton = wrapper.find('SpinnerButton').first();
const saveButton = wrapper.find({'data-testid': 'save-button'}).first();
const nameInput = wrapper.find('#name');
nameInput.simulate('change', {target: {name: 'name', value: emojiName}});

View File

@@ -385,6 +385,7 @@ export default class AddEmoji extends React.PureComponent<AddEmojiProps, AddEmoj
/>
</Link>
<SpinnerButton
data-testid='save-button'
className='btn btn-primary'
type='submit'
spinning={this.state.saving}

View File

@@ -419,7 +419,7 @@ exports[`components/integrations/AbstractCommand should match snapshot 1`] = `
id="add_command.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
id="saveCommand"
onClick={[Function]}
@@ -431,7 +431,7 @@ exports[`components/integrations/AbstractCommand should match snapshot 1`] = `
defaultMessage="Footer"
id="Footer"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
<div>
renderExtra
</div>
@@ -859,7 +859,7 @@ exports[`components/integrations/AbstractCommand should match snapshot when head
id="add_command.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
id="saveCommand"
onClick={[Function]}
@@ -870,7 +870,7 @@ exports[`components/integrations/AbstractCommand should match snapshot when head
<span>
Footer as string
</span>
</SpinnerButton>
</Memo(SpinnerButton)>
<div>
renderExtra
</div>
@@ -1302,7 +1302,7 @@ exports[`components/integrations/AbstractCommand should match snapshot, displays
id="add_command.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
id="saveCommand"
onClick={[Function]}
@@ -1314,7 +1314,7 @@ exports[`components/integrations/AbstractCommand should match snapshot, displays
defaultMessage="Footer"
id="Footer"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
<div>
renderExtra
</div>

View File

@@ -242,7 +242,7 @@ exports[`components/integrations/AbstractIncomingWebhook should call action func
id="add_incoming_webhook.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
id="saveWebhook"
onClick={[Function]}
@@ -254,7 +254,7 @@ exports[`components/integrations/AbstractIncomingWebhook should call action func
defaultMessage="Footer"
id="footer_id"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
</div>
</form>
</div>
@@ -503,7 +503,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot 1
id="add_incoming_webhook.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
id="saveWebhook"
onClick={[Function]}
@@ -515,7 +515,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot 1
defaultMessage="Footer"
id="footer_id"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
</div>
</form>
</div>
@@ -767,7 +767,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
id="add_incoming_webhook.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
id="saveWebhook"
onClick={[Function]}
@@ -779,7 +779,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
defaultMessage="Footer"
id="footer_id"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
</div>
</form>
</div>
@@ -995,7 +995,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
id="add_incoming_webhook.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
id="saveWebhook"
onClick={[Function]}
@@ -1007,7 +1007,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
defaultMessage="Footer"
id="footer_id"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
</div>
</form>
</div>
@@ -1223,7 +1223,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
id="add_incoming_webhook.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
id="saveWebhook"
onClick={[Function]}
@@ -1235,7 +1235,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
defaultMessage="Footer"
id="footer_id"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
</div>
</form>
</div>
@@ -1484,7 +1484,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
id="add_incoming_webhook.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
id="saveWebhook"
onClick={[Function]}
@@ -1496,7 +1496,7 @@ exports[`components/integrations/AbstractIncomingWebhook should match snapshot,
defaultMessage="Footer"
id="footer_id"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
</div>
</form>
</div>

View File

@@ -283,7 +283,7 @@ https://test.com/callback2"
id="installed_oauth_apps.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
id="saveOauthApp"
onClick={[Function]}
@@ -295,7 +295,7 @@ https://test.com/callback2"
defaultMessage="Footer"
id="Footer"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
<div>
renderExtra
</div>
@@ -590,7 +590,7 @@ exports[`components/integrations/AbstractOAuthApp should match snapshot, display
id="installed_oauth_apps.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
id="saveOauthApp"
onClick={[Function]}
@@ -602,7 +602,7 @@ exports[`components/integrations/AbstractOAuthApp should match snapshot, display
defaultMessage="Footer"
id="Footer"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
<div>
renderExtra
</div>

View File

@@ -328,7 +328,7 @@ callbackUrl2.com
id="add_outgoing_webhook.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
id="saveWebhook"
onClick={[Function]}
@@ -340,7 +340,7 @@ callbackUrl2.com
defaultMessage="Footer"
id="footer_id"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
</div>
</form>
</div>

View File

@@ -337,7 +337,7 @@ exports[`components/integrations/bots/AddBot blank 1`] = `
id="bots.manage.add.cancel"
/>
</Link>
<SpinnerButton
<Memo(SpinnerButton)
className="btn btn-primary"
id="saveBot"
onClick={[Function]}
@@ -354,7 +354,7 @@ exports[`components/integrations/bots/AddBot blank 1`] = `
defaultMessage="Create Bot Account"
id="bots.manage.add.create"
/>
</SpinnerButton>
</Memo(SpinnerButton)>
</div>
</form>
</div>

View File

@@ -61,6 +61,7 @@ describe('components/SpinnerButton', () => {
id='my-button-id'
className='btn btn-success'
spinningText='Test'
spinning={false}
/>,
);

View File

@@ -1,37 +1,35 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {PureComponent} from 'react';
import type {ButtonHTMLAttributes, ReactNode} from 'react';
import React from 'react';
import type {ReactNode} from 'react';
import LoadingWrapper from 'components/widgets/loading/loading_wrapper';
type Props = {
type Props = React.ButtonHTMLAttributes<HTMLButtonElement> & {
children?: ReactNode;
spinning: boolean;
spinningText: ReactNode;
}
export default class SpinnerButton extends PureComponent<Props & ButtonHTMLAttributes<HTMLButtonElement>> {
public static defaultProps: Partial<Props> = {
spinning: false,
};
public render(): JSX.Element {
const {spinning, spinningText, children, ...props} = this.props;
return (
<button
disabled={spinning}
{...props}
const SpinnerButton = ({
spinning = false,
spinningText,
children,
...props
}: Props) => {
return (
<button
disabled={spinning}
{...props}
>
<LoadingWrapper
loading={spinning}
text={spinningText}
>
<LoadingWrapper
loading={spinning}
text={spinningText}
>
{children}
</LoadingWrapper>
</button>
);
}
}
{children}
</LoadingWrapper>
</button>
);
};
export default React.memo(SpinnerButton);