From c156975231ca72178306ccb14ac622ed71554543 Mon Sep 17 00:00:00 2001 From: Chris <chris@chrissnijder.nl> Date: Fri, 5 Feb 2021 00:55:32 +0100 Subject: [PATCH] Prettify. --- src/App.css | 0 src/App.tsx | 41 ++--- .../locale-switcher/LocaleSwitcher.test.tsx | 16 +- .../locale-switcher/LocaleSwitcher.tsx | 24 +-- .../problem-dropdown/ProblemDropdown.test.tsx | 150 +++++++++--------- .../problem-dropdown/ProblemDropdown.tsx | 50 +++--- src/components/spinner/Spinner.test.tsx | 47 +++--- src/components/spinner/Spinner.tsx | 23 +-- .../ProblemSuggestionList.test.tsx | 40 +++-- .../suggestion-list/ProblemSuggestionList.tsx | 50 +++--- src/index.tsx | 2 +- src/services/i18n.ts | 40 ++--- 12 files changed, 259 insertions(+), 224 deletions(-) delete mode 100644 src/App.css diff --git a/src/App.css b/src/App.css deleted file mode 100644 index e69de29..0000000 diff --git a/src/App.tsx b/src/App.tsx index ea8f884..951754d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,21 +1,20 @@ import i18next from 'i18next'; import React, { useState } from 'react'; -import { useTranslation } from "react-i18next"; -import './App.css'; -import LocaleSwitcher from "./components/locale-switcher/LocaleSwitcher" +import { useTranslation } from 'react-i18next'; +import LocaleSwitcher from './components/locale-switcher/LocaleSwitcher'; import ProblemDropdown from './components/problem-dropdown/ProblemDropdown'; import ProblemSuggestionList from './components/suggestion-list/ProblemSuggestionList'; -import config from "./config.yml"; +import config from './config.yml'; -interface AppProps { } +interface AppProps {} -function App({ }: AppProps) { +function App({}: AppProps) { const { i18n, t } = useTranslation(); - const [problemGroup, _setProblemGroup] = useState<string>(""); - const [problem, setProblem] = useState<string>(""); + const [problemGroup, _setProblemGroup] = useState<string>(''); + const [problem, setProblem] = useState<string>(''); function setProblemGroup(newGroup: string) { - setProblem(""); + setProblem(''); _setProblemGroup(newGroup); } @@ -23,31 +22,35 @@ function App({ }: AppProps) { return ( <> <LocaleSwitcher /> - <header><img src="" /><h1>{t("title")}</h1><p>{t("subtitle")}</p></header> + <header> + <img src="" /> + <h1>{t('title')}</h1> + <p>{t('subtitle')}</p> + </header> <form> <ProblemDropdown - defaultOption={t("selectProblemGroup")} + defaultOption={t('selectProblemGroup')} problems={groups} - problem={problemGroup} setProblem={setProblemGroup} + problem={problemGroup} + setProblem={setProblemGroup} /> - {problemGroup && - (<> + {problemGroup && ( + <> <p>{groups[problemGroup].describe[i18next.language]}</p> <ProblemDropdown - defaultOption={t("selectProblem")} + defaultOption={t('selectProblem')} problems={groups[problemGroup].problems} problem={problem} setProblem={setProblem} /> </> - ) - } - {problem && + )} + {problem && ( <ProblemSuggestionList intro={groups[problemGroup].problems[problem].intro[i18n.language]} suggestions={groups[problemGroup].problems[problem].suggestions} /> - } + )} </form> </> ); diff --git a/src/components/locale-switcher/LocaleSwitcher.test.tsx b/src/components/locale-switcher/LocaleSwitcher.test.tsx index d185f97..b298117 100644 --- a/src/components/locale-switcher/LocaleSwitcher.test.tsx +++ b/src/components/locale-switcher/LocaleSwitcher.test.tsx @@ -4,11 +4,11 @@ import userEvent from '@testing-library/user-event'; import LocaleSwitcher from './LocaleSwitcher'; describe('<LocaleSwitcher>', () => { - it('renders a list of languages', () => { - render(<LocaleSwitcher />); - const elSelect = screen.getByRole("combobox"); - expect(elSelect).toHaveValue("en"); - userEvent.selectOptions(elSelect, ["nl"]) - expect(elSelect).toHaveValue("nl"); - }); -}); \ No newline at end of file + it('renders a list of languages', () => { + render(<LocaleSwitcher />); + const elSelect = screen.getByRole('combobox'); + expect(elSelect).toHaveValue('en'); + userEvent.selectOptions(elSelect, ['nl']); + expect(elSelect).toHaveValue('nl'); + }); +}); diff --git a/src/components/locale-switcher/LocaleSwitcher.tsx b/src/components/locale-switcher/LocaleSwitcher.tsx index b4247b6..3410250 100644 --- a/src/components/locale-switcher/LocaleSwitcher.tsx +++ b/src/components/locale-switcher/LocaleSwitcher.tsx @@ -1,14 +1,16 @@ -import React from "react"; -import { useTranslation } from "react-i18next"; +import React from 'react'; +import { useTranslation } from 'react-i18next'; function LocaleSwitcher() { - const { i18n } = useTranslation(); - return ( - <select value={i18n.language} onChange={e => i18n.changeLanguage(e.target.value)}> - <option value="en">English</option> - <option value="nl">Nederlands</option> - </select> - - ); + const { i18n } = useTranslation(); + return ( + <select + value={i18n.language} + onChange={(e) => i18n.changeLanguage(e.target.value)} + > + <option value="en">English</option> + <option value="nl">Nederlands</option> + </select> + ); } -export default LocaleSwitcher; \ No newline at end of file +export default LocaleSwitcher; diff --git a/src/components/problem-dropdown/ProblemDropdown.test.tsx b/src/components/problem-dropdown/ProblemDropdown.test.tsx index 61fb293..84c673c 100644 --- a/src/components/problem-dropdown/ProblemDropdown.test.tsx +++ b/src/components/problem-dropdown/ProblemDropdown.test.tsx @@ -1,92 +1,94 @@ import React from 'react'; import { render, screen, act, cleanup } from '@testing-library/react'; -import each from "jest-each"; +import each from 'jest-each'; import ProblemDropdown from './ProblemDropdown'; import userEvent from '@testing-library/user-event'; import i18next from '../../services/i18n'; - - -const problems: {[problem: string]: { +const problems: { + [problem: string]: { [description: string]: { - [language: string]: string - } -}} = { - problem1: { - description: { - en: "Description of problem 1", - nl: "Omschrijving van probleem 1" - }, + [language: string]: string; + }; + }; +} = { + problem1: { + description: { + en: 'Description of problem 1', + nl: 'Omschrijving van probleem 1', }, - problem2: { - description: { - en: "Description of problem 2", - nl: "Omschrijving van probleem 2" - }, + }, + problem2: { + description: { + en: 'Description of problem 2', + nl: 'Omschrijving van probleem 2', }, + }, }; -const defaultText = "Select something.."; -const mockSetProblem = jest.fn((problem: string) => { }); +const defaultText = 'Select something..'; +const mockSetProblem = jest.fn((problem: string) => {}); afterEach(cleanup); describe('<ProblemDropdown>', () => { + it('renders a list of problems', () => { + render( + <ProblemDropdown + defaultOption={defaultText} + problems={problems} + problem={''} + setProblem={mockSetProblem} + />, + ); + // Check the default value is selected + const elSelect = screen.getByRole('combobox'); + expect(elSelect).toHaveTextContent(defaultText); + expect(elSelect).toHaveValue(''); - it('renders a list of problems', () => { - render( - <ProblemDropdown - defaultOption={defaultText} - problems={problems} - problem={""} - setProblem={mockSetProblem} - /> - ); - // Check the default value is selected - const elSelect = screen.getByRole("combobox"); - expect(elSelect).toHaveTextContent(defaultText); - expect(elSelect).toHaveValue(""); - - // Select some values and see if everything happens as expected - Object.keys(problems).forEach((problem: string) => { - userEvent.selectOptions(elSelect, [problem]) - // This is set, but its value is controlled by react, so not updated. - expect(elSelect).toHaveTextContent(problems[problem].description.en); - expect(mockSetProblem).toBeCalledWith(problem); - }); + // Select some values and see if everything happens as expected + Object.keys(problems).forEach((problem: string) => { + userEvent.selectOptions(elSelect, [problem]); + // This is set, but its value is controlled by react, so not updated. + expect(elSelect).toHaveTextContent(problems[problem].description.en); + expect(mockSetProblem).toBeCalledWith(problem); }); + }); - each([[""], ["problem1"], ["problem2"]]) - .it('renders a list of problems, selected problem by prop: %s', (problem) => { - render( - <ProblemDropdown - defaultOption={defaultText} - problems={problems} - problem={problem} - setProblem={mockSetProblem} - /> - ); - // Check the prop value is selected - const elSelect = screen.getByRole("combobox"); - if (problem) - expect(elSelect).toHaveTextContent(problems[problem].description.en); - else - expect(elSelect).toHaveTextContent(defaultText); - expect(elSelect).toHaveValue(problem); - }); - it('renders a localised list of problems', async () => { - const problem = Object.keys(problems)[0]; - render( - <ProblemDropdown - defaultOption={defaultText} - problems={problems} - problem={problem} - setProblem={mockSetProblem} - /> - ); - // Check the prop value is selected - const elSelect = screen.getByRole("combobox"); + each([[''], ['problem1'], ['problem2']]).it( + 'renders a list of problems, selected problem by prop: %s', + (problem) => { + render( + <ProblemDropdown + defaultOption={defaultText} + problems={problems} + problem={problem} + setProblem={mockSetProblem} + />, + ); + // Check the prop value is selected + const elSelect = screen.getByRole('combobox'); + if (problem) expect(elSelect).toHaveTextContent(problems[problem].description.en); - await act(async () => { i18next.changeLanguage("nl") }); - expect(elSelect).toHaveTextContent(problems[problem].description.nl); - expect(elSelect).toHaveValue(problem); + else expect(elSelect).toHaveTextContent(defaultText); + expect(elSelect).toHaveValue(problem); + }, + ); + it('renders a localised list of problems', async () => { + const problem = Object.keys(problems)[0]; + render( + <ProblemDropdown + defaultOption={defaultText} + problems={problems} + problem={problem} + setProblem={mockSetProblem} + />, + ); + // Check the prop value is selected + const elSelect = screen.getByRole('combobox'); + expect(elSelect).toHaveTextContent(problems[problem].description.en); + await act(async () => { + i18next.changeLanguage('nl'); }); -}); \ No newline at end of file + expect(elSelect).toHaveTextContent(problems[problem].description.nl); + expect(elSelect).toHaveValue(problem); + }); +}); diff --git a/src/components/problem-dropdown/ProblemDropdown.tsx b/src/components/problem-dropdown/ProblemDropdown.tsx index 0ea077b..6de6800 100644 --- a/src/components/problem-dropdown/ProblemDropdown.tsx +++ b/src/components/problem-dropdown/ProblemDropdown.tsx @@ -1,27 +1,33 @@ -import React from "react"; -import { useTranslation } from "react-i18next"; +import React from 'react'; +import { useTranslation } from 'react-i18next'; interface ProblemDropdownProps { - defaultOption: string, - problems: object, - problem: string, - setProblem: CallableFunction + defaultOption: string; + problems: object; + problem: string; + setProblem: CallableFunction; } -function ProblemDropdown({ defaultOption, problems, problem, setProblem }: ProblemDropdownProps) { - const { i18n } = useTranslation(); - return ( - <div className="field"> - <select value={problem} onChange={e => setProblem(e.target.value)}> - <option key="_default" value="">{defaultOption}</option> - { - Object.entries(problems).map(([problemKey, problem]) => ( - <option key={problemKey} value={problemKey}>{problem.description[i18n.language]}</option> - )) - } - </select> - </div> - - ); +function ProblemDropdown({ + defaultOption, + problems, + problem, + setProblem, +}: ProblemDropdownProps) { + const { i18n } = useTranslation(); + return ( + <div className="field"> + <select value={problem} onChange={(e) => setProblem(e.target.value)}> + <option key="_default" value=""> + {defaultOption} + </option> + {Object.entries(problems).map(([problemKey, problem]) => ( + <option key={problemKey} value={problemKey}> + {problem.description[i18n.language]} + </option> + ))} + </select> + </div> + ); } -export default ProblemDropdown; \ No newline at end of file +export default ProblemDropdown; diff --git a/src/components/spinner/Spinner.test.tsx b/src/components/spinner/Spinner.test.tsx index d613330..8089bbe 100644 --- a/src/components/spinner/Spinner.test.tsx +++ b/src/components/spinner/Spinner.test.tsx @@ -1,28 +1,35 @@ import * as React from 'react'; import { render } from '@testing-library/react'; import Spinner from './Spinner'; -import each from "jest-each"; +import each from 'jest-each'; describe('<Spinner>', () => { + it('renders spinning loading indicator: default', () => { + const { getByRole } = render(<Spinner />); + const spinner = getByRole('progressbar'); + expect(spinner).toBeVisible(); + expect(spinner).not.toHaveClass('big'); + }); - it("renders spinning loading indicator: default", () => { - const { getByRole } = render(<Spinner />); - const spinner = getByRole("progressbar"); - expect(spinner).toBeVisible(); - expect(spinner).not.toHaveClass("big") - }) + const variations = [ + ['small', false], + ['big', true], + ]; + each(variations).it( + `renders spinning loading indicator: %s`, + (big: boolean) => { + const { getByRole } = render(<Spinner loading={true} big={big} />); + const spinner = getByRole('progressbar'); + expect(spinner).toBeVisible(); + }, + ); - const variations = [["small", false], ["big", true]]; - each(variations).it(`renders spinning loading indicator: %s`, (big: boolean) => { - const { getByRole } = render(<Spinner loading={true} big={big} />); - const spinner = getByRole("progressbar"); - expect(spinner).toBeVisible(); - }) - - each(variations).it(`Does not render spinning loading indicator: %s`, (big: boolean) => { - const { queryByRole } = render(<Spinner loading={false} big={big} />); - const spinners = queryByRole("progressbar"); - expect(spinners).toBe(null); - }); + each(variations).it( + `Does not render spinning loading indicator: %s`, + (big: boolean) => { + const { queryByRole } = render(<Spinner loading={false} big={big} />); + const spinners = queryByRole('progressbar'); + expect(spinners).toBe(null); + }, + ); }); - diff --git a/src/components/spinner/Spinner.tsx b/src/components/spinner/Spinner.tsx index 73f6ea7..12698b0 100644 --- a/src/components/spinner/Spinner.tsx +++ b/src/components/spinner/Spinner.tsx @@ -1,20 +1,21 @@ import React from 'react'; export interface SpinnerProps { - big?: boolean, - loading?: boolean + big?: boolean; + loading?: boolean; } function Spinner({ big = false, loading = true }: SpinnerProps) { - if (!loading) - return (<div className="spinner"></div>) - const classes = ["spinner", "loading"]; - if (big) - classes.push("big"); - return ( - <div className={classes.join(" ")} role="progressbar" aria-label="Loading"></div> - ); + if (!loading) return <div className="spinner"></div>; + const classes = ['spinner', 'loading']; + if (big) classes.push('big'); + return ( + <div + className={classes.join(' ')} + role="progressbar" + aria-label="Loading" + ></div> + ); } export default Spinner; - diff --git a/src/components/suggestion-list/ProblemSuggestionList.test.tsx b/src/components/suggestion-list/ProblemSuggestionList.test.tsx index b8f86ca..8458ee2 100644 --- a/src/components/suggestion-list/ProblemSuggestionList.test.tsx +++ b/src/components/suggestion-list/ProblemSuggestionList.test.tsx @@ -1,19 +1,29 @@ import * as React from 'react'; import { render, screen } from '@testing-library/react'; -import ProblemSuggestionList, { ProblemSuggestionListProps } from './ProblemSuggestionList'; +import ProblemSuggestionList, { + ProblemSuggestionListProps, +} from './ProblemSuggestionList'; describe('<ProblemSuggestionList>', () => { - it('renders a list of suggestions to answer questions or solve issues', () => { - const suggestion = { en: {link: "http://example.com", description: "What is your bankaccountnumer?" }}; - const givenSuggestions: ProblemSuggestionListProps = { - intro: "Here are some of the most common examples of administrative issues:", - suggestions: [suggestion] - }; - const { getByText, } = render(<ProblemSuggestionList {...givenSuggestions} />); - const solutionIntro = getByText(/examples of administrative issues:/i); - expect(document.body.contains(solutionIntro)); - const theSolutionLink = screen.getByRole("link"); - expect(theSolutionLink).toHaveTextContent(suggestion.en.description) - expect(theSolutionLink).toHaveAttribute("href", suggestion.en.link) - }); -}); \ No newline at end of file + it('renders a list of suggestions to answer questions or solve issues', () => { + const suggestion = { + en: { + link: 'http://example.com', + description: 'What is your bankaccountnumer?', + }, + }; + const givenSuggestions: ProblemSuggestionListProps = { + intro: + 'Here are some of the most common examples of administrative issues:', + suggestions: [suggestion], + }; + const { getByText } = render( + <ProblemSuggestionList {...givenSuggestions} />, + ); + const solutionIntro = getByText(/examples of administrative issues:/i); + expect(document.body.contains(solutionIntro)); + const theSolutionLink = screen.getByRole('link'); + expect(theSolutionLink).toHaveTextContent(suggestion.en.description); + expect(theSolutionLink).toHaveAttribute('href', suggestion.en.link); + }); +}); diff --git a/src/components/suggestion-list/ProblemSuggestionList.tsx b/src/components/suggestion-list/ProblemSuggestionList.tsx index cc32597..a2cae1a 100644 --- a/src/components/suggestion-list/ProblemSuggestionList.tsx +++ b/src/components/suggestion-list/ProblemSuggestionList.tsx @@ -1,32 +1,36 @@ import React from 'react'; -import { useTranslation } from "react-i18next"; +import { useTranslation } from 'react-i18next'; - -type Suggestion = { - [language: string]: { - link: string, - description: string } +type Suggestion = { + [language: string]: { + link: string; + description: string; + }; }; export interface ProblemSuggestionListProps { - intro: string; - suggestions: Suggestion[]; + intro: string; + suggestions: Suggestion[]; } -function ProblemSuggestionList({ suggestions, intro }: ProblemSuggestionListProps) { - const { i18n } = useTranslation(); - return ( - <> - <p>{intro}</p> - <ul> - { - suggestions.map((suggestion, i) => - <li key={i}><a href={suggestion[i18n.language].link}>{suggestion[i18n.language].description}</a></li> - ) - } - </ul> - </> - ); +function ProblemSuggestionList({ + suggestions, + intro, +}: ProblemSuggestionListProps) { + const { i18n } = useTranslation(); + return ( + <> + <p>{intro}</p> + <ul> + {suggestions.map((suggestion, i) => ( + <li key={i}> + <a href={suggestion[i18n.language].link}> + {suggestion[i18n.language].description} + </a> + </li> + ))} + </ul> + </> + ); } export default ProblemSuggestionList; - diff --git a/src/index.tsx b/src/index.tsx index 25ec269..23f1d8b 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,7 +1,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; -import "./services/i18n"; +import './services/i18n'; ReactDOM.render( <React.StrictMode> diff --git a/src/services/i18n.ts b/src/services/i18n.ts index e7a2943..f9b4bdb 100644 --- a/src/services/i18n.ts +++ b/src/services/i18n.ts @@ -1,33 +1,33 @@ -import i18next, { Resource, ResourceKey } from "i18next"; -import { initReactI18next } from "react-i18next"; +import i18next, { Resource, ResourceKey } from 'i18next'; +import { initReactI18next } from 'react-i18next'; const resources: Resource = { en: { translation: { - title: "Report a problem", - subtitle: "Let's troubleshoot together. What type of issue are you experiencing?", - selectProblemGroup: "Select an issue type..", - selectProblem: "Select issue.." + title: 'Report a problem', + subtitle: + "Let's troubleshoot together. What type of issue are you experiencing?", + selectProblemGroup: 'Select an issue type..', + selectProblem: 'Select issue..', }, }, nl: { translation: { - title: "Meld een probleem", - subtitle: "Laten we samen uitzoeken wat er aan de hand is. Wat voor soort probleem ervaar je?", - selectProblemGroup: "Selecteer een type issue..", - selectProblem: "Selecteer issue.." + title: 'Meld een probleem', + subtitle: + 'Laten we samen uitzoeken wat er aan de hand is. Wat voor soort probleem ervaar je?', + selectProblemGroup: 'Selecteer een type issue..', + selectProblem: 'Selecteer issue..', }, }, }; -i18next - .use(initReactI18next) - .init({ - resources, - lng: "en", - interpolation: { - escapeValue: false, - }, - }); +i18next.use(initReactI18next).init({ + resources, + lng: 'en', + interpolation: { + escapeValue: false, + }, +}); -export default i18next; \ No newline at end of file +export default i18next; -- GitLab