From f3effbea644ba95bbc9cdc7f673aef1196016f10 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Oct 2022 14:16:22 +0100 Subject: [PATCH 1/5] Reset custom power selector when blurred on empty --- src/Roles.ts | 2 +- src/components/views/elements/PowerSelector.tsx | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Roles.ts b/src/Roles.ts index ae0d316d301..77c50fe64c3 100644 --- a/src/Roles.ts +++ b/src/Roles.ts @@ -16,7 +16,7 @@ limitations under the License. import { _t } from './languageHandler'; -export function levelRoleMap(usersDefault: number) { +export function levelRoleMap(usersDefault: number): Record { return { undefined: _t('Default'), 0: _t('Restricted'), diff --git a/src/components/views/elements/PowerSelector.tsx b/src/components/views/elements/PowerSelector.tsx index 3a9e87d1581..cbf4df33936 100644 --- a/src/components/views/elements/PowerSelector.tsx +++ b/src/components/views/elements/PowerSelector.tsx @@ -44,7 +44,7 @@ interface IProps { } interface IState { - levelRoleMap: {}; + levelRoleMap: Partial>; // List of power levels to show in the drop-down options: number[]; @@ -125,7 +125,11 @@ export default class PowerSelector extends React.Component { event.preventDefault(); event.stopPropagation(); - this.props.onChange(this.state.customValue, this.props.powerLevelKey); + if (this.state.customValue) { + this.props.onChange(this.state.customValue, this.props.powerLevelKey); + } else { + this.initStateFromProps(this.props); // reset, invalid input + } }; private onCustomKeyDown = (event: React.KeyboardEvent): void => { From 8ec961ae3e2c0ac9359cb518d444d89c26549d76 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Oct 2022 14:27:36 +0100 Subject: [PATCH 2/5] Tweak case --- src/components/views/elements/PowerSelector.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/PowerSelector.tsx b/src/components/views/elements/PowerSelector.tsx index cbf4df33936..e73913cc69b 100644 --- a/src/components/views/elements/PowerSelector.tsx +++ b/src/components/views/elements/PowerSelector.tsx @@ -125,7 +125,7 @@ export default class PowerSelector extends React.Component { event.preventDefault(); event.stopPropagation(); - if (this.state.customValue) { + if (Number.isFinite(this.state.customValue)) { this.props.onChange(this.state.customValue, this.props.powerLevelKey); } else { this.initStateFromProps(this.props); // reset, invalid input From 9aa62cd7f859f303ff68a67208eb7915b52f46fd Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Oct 2022 16:31:11 +0100 Subject: [PATCH 3/5] Add tests --- .../views/elements/PowerSelector.tsx | 3 +- .../views/elements/PowerSelector-test.tsx | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 test/components/views/elements/PowerSelector-test.tsx diff --git a/src/components/views/elements/PowerSelector.tsx b/src/components/views/elements/PowerSelector.tsx index e73913cc69b..8b251b91a51 100644 --- a/src/components/views/elements/PowerSelector.tsx +++ b/src/components/views/elements/PowerSelector.tsx @@ -51,7 +51,6 @@ interface IState { customValue: number; selectValue: number | string; custom?: boolean; - customLevel?: number; } export default class PowerSelector extends React.Component { @@ -101,7 +100,7 @@ export default class PowerSelector extends React.Component { levelRoleMap, options, custom: isCustom, - customLevel: newProps.value, + customValue: newProps.value, selectValue: isCustom ? CUSTOM_VALUE : newProps.value, }); } diff --git a/test/components/views/elements/PowerSelector-test.tsx b/test/components/views/elements/PowerSelector-test.tsx new file mode 100644 index 00000000000..77cde0d5aca --- /dev/null +++ b/test/components/views/elements/PowerSelector-test.tsx @@ -0,0 +1,50 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import { fireEvent, render, screen} from "@testing-library/react"; + +import PowerSelector from "../../../../src/components/views/elements/PowerSelector"; + +describe('', () => { + it("should reset back to custom value when custom input is blurred blank", async () => { + const fn = jest.fn(); + render(); + + const input = screen.getByLabelText("Power level"); + fireEvent.change(input, { target: { value: "" } }); + fireEvent.blur(input); + + await screen.findByDisplayValue(25); + expect(fn).not.toHaveBeenCalled(); + }); + + it("should reset back to preset value when custom input is blurred blank", async () => { + const fn = jest.fn(); + render(); + + const select = screen.getByLabelText("Power level"); + fireEvent.change(select, { target: { value: "SELECT_VALUE_CUSTOM" } }); + + const input = screen.getByLabelText("Power level"); + fireEvent.change(input, { target: { value: "" } }); + fireEvent.blur(input); + + const option = await screen.findByText("Moderator"); + expect(option.selected).toBeTruthy(); + expect(fn).not.toHaveBeenCalled(); + }); +}); From 83978541917950997c8fb80eee097cb2ecf5f9e6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Oct 2022 16:34:26 +0100 Subject: [PATCH 4/5] delint --- test/components/views/elements/PowerSelector-test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/components/views/elements/PowerSelector-test.tsx b/test/components/views/elements/PowerSelector-test.tsx index 77cde0d5aca..63d1726f435 100644 --- a/test/components/views/elements/PowerSelector-test.tsx +++ b/test/components/views/elements/PowerSelector-test.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from 'react'; -import { fireEvent, render, screen} from "@testing-library/react"; +import { fireEvent, render, screen } from "@testing-library/react"; import PowerSelector from "../../../../src/components/views/elements/PowerSelector"; From 7203839fb1423b51337f9e7b8be34074834521dc Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Oct 2022 16:58:24 +0100 Subject: [PATCH 5/5] Add test for existing behaviour --- .../components/views/elements/PowerSelector-test.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/components/views/elements/PowerSelector-test.tsx b/test/components/views/elements/PowerSelector-test.tsx index 63d1726f435..9367d0b089f 100644 --- a/test/components/views/elements/PowerSelector-test.tsx +++ b/test/components/views/elements/PowerSelector-test.tsx @@ -47,4 +47,16 @@ describe('', () => { expect(option.selected).toBeTruthy(); expect(fn).not.toHaveBeenCalled(); }); + + it("should call onChange when custom input is blurred with a number in it", async () => { + const fn = jest.fn(); + render(); + + const input = screen.getByLabelText("Power level"); + fireEvent.change(input, { target: { value: 40 } }); + fireEvent.blur(input); + + await screen.findByDisplayValue(40); + expect(fn).toHaveBeenCalledWith(40, "key"); + }); });