#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>
Этот коммит содержится в:
Noha M
2023-10-31 11:35:01 +02:00
коммит произвёл GitHub
родитель b4c9eddca8
Коммит 3812de0dec
11 изменённых файлов: 63 добавлений и 60 удалений

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@@ -202,7 +202,7 @@ describe('components/emoji/components/AddEmoji', () => {
const file = new Blob([image], {type: 'image/png'}); const file = new Blob([image], {type: 'image/png'});
wrapper.setState({image: file as File, imageUrl: image}); 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'); const nameInput = wrapper.find('#name');
nameInput.simulate('change', {target: {name: 'name', value: emojiName}}); nameInput.simulate('change', {target: {name: 'name', value: emojiName}});

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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