Skip to content
Snippets Groups Projects
Commit c1569752 authored by Chris's avatar Chris
Browse files

Prettify.

parent 8a903467
No related branches found
No related tags found
No related merge requests found
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>
</>
);
......
......@@ -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');
});
});
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;
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);
});
});
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;
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);
},
);
});
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;
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);
});
});
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;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import "./services/i18n";
import './services/i18n';
ReactDOM.render(
<React.StrictMode>
......
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;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment