From bc070f9749252d3e8ea6d2bbb4648ad707de3421 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Wed, 10 Apr 2024 09:22:46 -0400 Subject: [PATCH 1/3] refactor: field components --- src/components/fields/Checkbox.tsx | 62 ++++++++------- src/components/fields/RadioGroup.tsx | 111 ++++++++++++++------------- 2 files changed, 89 insertions(+), 84 deletions(-) diff --git a/src/components/fields/Checkbox.tsx b/src/components/fields/Checkbox.tsx index 7321e26e9..9bc091e39 100644 --- a/src/components/fields/Checkbox.tsx +++ b/src/components/fields/Checkbox.tsx @@ -1,42 +1,46 @@ +import type { FC, ReactNode } from 'react'; + interface IFieldCheckbox { name: string; label: string; + helpText?: ReactNode | string; checked: boolean; - onChange: (evt: React.ChangeEvent) => void; - placeholder?: string; disabled?: boolean; + onChange: (evt: React.ChangeEvent) => void; } -export const FieldCheckbox = (props: IFieldCheckbox) => { +export const FieldCheckbox: FC = (props: IFieldCheckbox) => { return ( -
-
- -
+
+
+
+ +
-
- - {props.placeholder && ( -
- {props.placeholder} -
- )} +
+ +
+ {props.helpText && ( +
+ {props.helpText} +
+ )}
); }; diff --git a/src/components/fields/RadioGroup.tsx b/src/components/fields/RadioGroup.tsx index ebf5c18ec..1bd897328 100644 --- a/src/components/fields/RadioGroup.tsx +++ b/src/components/fields/RadioGroup.tsx @@ -1,68 +1,69 @@ -import type { ChangeEvent } from 'react'; +import type { ChangeEvent, FC, ReactNode } from 'react'; import type { RadioGroupItem } from '../../types'; -export const FieldRadioGroup = ({ - label, - placeholder, - name, - options, - onChange, - value, -}: { +interface IRadioGroup { name: string; label: string; - placeholder?: string; + helpText?: ReactNode | string; options: RadioGroupItem[]; - onChange: (event: ChangeEvent) => void; value: string; -}) => { - return ( -
-
- + disabled?: boolean; + onChange: (event: ChangeEvent) => void; +} - {placeholder && ( -
- {placeholder} -
- )} -
+export const FieldRadioGroup: FC = (props: IRadioGroup) => { + return ( +
+
+
+ +
-
- {options.map((item) => { - return ( -
- -
+ ); + })} +
+ {props.helpText && ( +
+ {props.helpText} +
+ )}
); }; From 904f9c8a9ecb0cf351bbaa036e26d10e59fdded7 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Wed, 10 Apr 2024 12:54:18 -0400 Subject: [PATCH 2/3] refactor: field components --- src/components/fields/Checkbox.test.tsx | 18 + src/components/fields/Checkbox.tsx | 5 +- src/components/fields/FieldInput.test.tsx | 17 + src/components/fields/FieldInput.tsx | 4 +- src/components/fields/RadioGroup.test.tsx | 10 +- src/components/fields/RadioGroup.tsx | 3 +- .../__snapshots__/Checkbox.test.tsx.snap | 38 ++ .../__snapshots__/RadioGroup.test.tsx.snap | 100 ++-- src/routes/Settings.tsx | 26 +- .../__snapshots__/Settings.test.tsx.snap | 458 ++++++++++-------- 10 files changed, 405 insertions(+), 274 deletions(-) create mode 100644 src/components/fields/Checkbox.test.tsx create mode 100644 src/components/fields/FieldInput.test.tsx create mode 100644 src/components/fields/__snapshots__/Checkbox.test.tsx.snap diff --git a/src/components/fields/Checkbox.test.tsx b/src/components/fields/Checkbox.test.tsx new file mode 100644 index 000000000..95f3496e4 --- /dev/null +++ b/src/components/fields/Checkbox.test.tsx @@ -0,0 +1,18 @@ +import * as TestRenderer from 'react-test-renderer'; + +import { Checkbox, type ICheckbox } from './Checkbox'; + +describe('components/fields/Checkbox.tsx', () => { + const props: ICheckbox = { + name: 'appearance', + label: 'Appearance', + helpText: 'This is some helper text', + checked: true, + onChange: jest.fn(), + }; + + it('should render', () => { + const tree = TestRenderer.create(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/components/fields/Checkbox.tsx b/src/components/fields/Checkbox.tsx index 9bc091e39..20ca31646 100644 --- a/src/components/fields/Checkbox.tsx +++ b/src/components/fields/Checkbox.tsx @@ -1,6 +1,6 @@ import type { FC, ReactNode } from 'react'; -interface IFieldCheckbox { +export interface ICheckbox { name: string; label: string; helpText?: ReactNode | string; @@ -9,7 +9,7 @@ interface IFieldCheckbox { onChange: (evt: React.ChangeEvent) => void; } -export const FieldCheckbox: FC = (props: IFieldCheckbox) => { +export const Checkbox: FC = (props: ICheckbox) => { return (
@@ -36,6 +36,7 @@ export const FieldCheckbox: FC = (props: IFieldCheckbox) => {
+ {props.helpText && (
{props.helpText} diff --git a/src/components/fields/FieldInput.test.tsx b/src/components/fields/FieldInput.test.tsx new file mode 100644 index 000000000..fd4aa92a4 --- /dev/null +++ b/src/components/fields/FieldInput.test.tsx @@ -0,0 +1,17 @@ +import * as TestRendener from 'react-test-renderer'; + +import { FieldInput, type IFieldInput } from './FieldInput'; + +describe('components/fields/FieldInput.tsx', () => { + const props: IFieldInput = { + name: 'appearance', + label: 'Appearance', + placeholder: 'This is some placeholder text', + helpText: 'This is some helper text', + }; + + it('should render ', () => { + const tree = TestRendener.create(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/components/fields/FieldInput.tsx b/src/components/fields/FieldInput.tsx index 930932784..cc1890fe0 100644 --- a/src/components/fields/FieldInput.tsx +++ b/src/components/fields/FieldInput.tsx @@ -1,7 +1,7 @@ import type { FC, ReactNode } from 'react'; import { Field } from 'react-final-form'; -export interface IProps { +export interface IFieldInput { name: string; type?: string; label: string; @@ -10,7 +10,7 @@ export interface IProps { required?: boolean; } -export const FieldInput: FC = ({ +export const FieldInput: FC = ({ label, name, placeholder = '', diff --git a/src/components/fields/RadioGroup.test.tsx b/src/components/fields/RadioGroup.test.tsx index f316c6d9f..25cad0ffd 100644 --- a/src/components/fields/RadioGroup.test.tsx +++ b/src/components/fields/RadioGroup.test.tsx @@ -2,13 +2,13 @@ import { fireEvent, render, screen } from '@testing-library/react'; import * as TestRendener from 'react-test-renderer'; -import { FieldRadioGroup } from './RadioGroup'; +import { FieldRadioGroup, type IRadioGroup } from './RadioGroup'; -describe('components/fields/radiogroup.tsx', () => { - const props = { +describe('components/fields/RadioGroup.tsx', () => { + const props: IRadioGroup = { label: 'Appearance', name: 'appearance', - placeholder: 'This is some helper text', + helpText: 'This is some helper text', options: [ { label: 'Value 1', value: 'one' }, { label: 'Value 2', value: 'two' }, @@ -17,7 +17,7 @@ describe('components/fields/radiogroup.tsx', () => { value: 'two', }; - it('should render ', () => { + it('should render', () => { const tree = TestRendener.create(); expect(tree).toMatchSnapshot(); }); diff --git a/src/components/fields/RadioGroup.tsx b/src/components/fields/RadioGroup.tsx index 1bd897328..ca0d4ac36 100644 --- a/src/components/fields/RadioGroup.tsx +++ b/src/components/fields/RadioGroup.tsx @@ -1,7 +1,7 @@ import type { ChangeEvent, FC, ReactNode } from 'react'; import type { RadioGroupItem } from '../../types'; -interface IRadioGroup { +export interface IRadioGroup { name: string; label: string; helpText?: ReactNode | string; @@ -59,6 +59,7 @@ export const FieldRadioGroup: FC = (props: IRadioGroup) => { })}
+ {props.helpText && (
{props.helpText} diff --git a/src/components/fields/__snapshots__/Checkbox.test.tsx.snap b/src/components/fields/__snapshots__/Checkbox.test.tsx.snap new file mode 100644 index 000000000..0138d82b1 --- /dev/null +++ b/src/components/fields/__snapshots__/Checkbox.test.tsx.snap @@ -0,0 +1,38 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`components/fields/Checkbox.tsx should render 1`] = ` +
+
+
+ +
+
+ +
+
+
+ This is some helper text +
+
+`; diff --git a/src/components/fields/__snapshots__/RadioGroup.test.tsx.snap b/src/components/fields/__snapshots__/RadioGroup.test.tsx.snap index 70e146f0e..dd13f380f 100644 --- a/src/components/fields/__snapshots__/RadioGroup.test.tsx.snap +++ b/src/components/fields/__snapshots__/RadioGroup.test.tsx.snap @@ -1,67 +1,71 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`components/fields/radiogroup.tsx should render 1`] = ` +exports[`components/fields/RadioGroup.tsx should render 1`] = `
- -
- This is some helper text -
-
-
-
- - + + +
+
+ + +
+
+ This is some helper text +
`; diff --git a/src/routes/Settings.tsx b/src/routes/Settings.tsx index 89eb56c25..cd639dbad 100644 --- a/src/routes/Settings.tsx +++ b/src/routes/Settings.tsx @@ -16,7 +16,7 @@ import { } from 'react'; import { useNavigate } from 'react-router-dom'; -import { FieldCheckbox } from '../components/fields/Checkbox'; +import { Checkbox } from '../components/fields/Checkbox'; import { FieldRadioGroup } from '../components/fields/RadioGroup'; import { AppContext } from '../context/App'; import { Theme } from '../types'; @@ -130,8 +130,9 @@ export const SettingsRoute: FC = () => { onChange={(evt) => { updateSetting('theme', evt.target.value); }} + helpText="Changes will take effect after restarting the app" /> - { } disabled={!colorScope} /> - {
- + Notifications - { updateSetting('participating', evt.target.checked) } /> - updateSetting('showBots', evt.target.checked)} /> - {
- + System - updateSetting('showNotificationsCountInTray', evt.target.checked) } + helpText="Changes will take effect after restarting the app" /> - { updateSetting('showNotifications', evt.target.checked) } /> - updateSetting('playSound', evt.target.checked)} /> {!isLinux && ( -
+
+
+
+
- -
-
- -
-
-
-
- -
-
-
+
- Show account hostname - + +
@@ -199,79 +216,91 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = ` class="mb-3" > Notifications
- -
-
- + +
+
+ +
- -
-
- + +
+
+ +
- -
-
- + +
+
+ +
@@ -279,103 +308,124 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = ` class="mb-3" > System
- +
+ +
+
+ +
- + Changes will take effect after restarting the app
- -
-
- + +
+
+ +
- -
-
-
+
- Play sound - + +
- -
-
- + +
+
+ +
From e21b7ce039271f3a593ebdd33c175726a5a78824 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Wed, 10 Apr 2024 23:53:39 -0400 Subject: [PATCH 3/3] refactor: field components --- src/components/fields/RadioGroup.test.tsx | 8 ++++---- src/components/fields/RadioGroup.tsx | 2 +- src/routes/Settings.tsx | 5 ++--- src/routes/__snapshots__/Settings.test.tsx.snap | 5 ----- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/components/fields/RadioGroup.test.tsx b/src/components/fields/RadioGroup.test.tsx index e5b336f42..4a902abe9 100644 --- a/src/components/fields/RadioGroup.test.tsx +++ b/src/components/fields/RadioGroup.test.tsx @@ -2,7 +2,7 @@ import { fireEvent, render, screen } from '@testing-library/react'; import * as TestRenderer from 'react-test-renderer'; -import { FieldRadioGroup, type IRadioGroup } from './RadioGroup'; +import { type IRadioGroup, RadioGroup } from './RadioGroup'; describe('components/fields/RadioGroup.tsx', () => { const props: IRadioGroup = { @@ -18,19 +18,19 @@ describe('components/fields/RadioGroup.tsx', () => { }; it('should render', () => { - const tree = TestRenderer.create(); + const tree = TestRenderer.create(); expect(tree).toMatchSnapshot(); }); it('should render as disabled', () => { const mockProps = { ...props, disabled: true }; - const tree = TestRenderer.create(); + const tree = TestRenderer.create(); expect(tree).toMatchSnapshot(); }); it('should check that NProgress is getting called in getDerivedStateFromProps (loading)', () => { - render(); + render(); fireEvent.click(screen.getByLabelText('Value 1')); expect(props.onChange).toHaveBeenCalledTimes(1); }); diff --git a/src/components/fields/RadioGroup.tsx b/src/components/fields/RadioGroup.tsx index ca0d4ac36..c143b75b5 100644 --- a/src/components/fields/RadioGroup.tsx +++ b/src/components/fields/RadioGroup.tsx @@ -11,7 +11,7 @@ export interface IRadioGroup { onChange: (event: ChangeEvent) => void; } -export const FieldRadioGroup: FC = (props: IRadioGroup) => { +export const RadioGroup: FC = (props: IRadioGroup) => { return (
diff --git a/src/routes/Settings.tsx b/src/routes/Settings.tsx index cd639dbad..7ce87b94a 100644 --- a/src/routes/Settings.tsx +++ b/src/routes/Settings.tsx @@ -17,7 +17,7 @@ import { import { useNavigate } from 'react-router-dom'; import { Checkbox } from '../components/fields/Checkbox'; -import { FieldRadioGroup } from '../components/fields/RadioGroup'; +import { RadioGroup } from '../components/fields/RadioGroup'; import { AppContext } from '../context/App'; import { Theme } from '../types'; import { apiRequestAuth } from '../utils/api-requests'; @@ -118,7 +118,7 @@ export const SettingsRoute: FC = () => { Appearance - { onChange={(evt) => { updateSetting('theme', evt.target.value); }} - helpText="Changes will take effect after restarting the app" />
-
- Changes will take effect after restarting the app -