Skip to content

Commit

Permalink
Display validation errors (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
andersnylund authored Apr 25, 2023
1 parent bcca956 commit 09a41e7
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 17 deletions.
27 changes: 27 additions & 0 deletions src/ClientApp.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { render, screen } from '@testing-library/react';
import { describe, it } from 'vitest';
import resume from '../resume.json';
import { ClientApp } from './ClientApp';

describe('<ClientApp />', () => {
it('renders errors', () => {
render(
<ClientApp
resume={{
...resume,
basics: {
...resume.basics,
url: '',
},
}}
/>
);
expect(screen.getByText('resume.json is invalid')).toBeInTheDocument();
expect(screen.getByText(/invalid_string/)).toBeInTheDocument();
});

it('renders resume', () => {
render(<ClientApp resume={resume} />);
expect(screen.getByText('Pässi Villanen')).toBeInTheDocument();
});
});
17 changes: 17 additions & 0 deletions src/ClientApp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { FC, StrictMode } from 'react';
import { Resume } from './Resume';
import { Error } from './components/Error';
import { resumeSchema } from './schema';

export const ClientApp: FC<{ resume: unknown }> = ({ resume }) => {
const parsedResume = resumeSchema.safeParse(resume);
return (
<StrictMode>
{parsedResume.success ? (
<Resume resume={parsedResume.data} />
) : (
<Error errors={parsedResume.error} />
)}
</StrictMode>
);
};
2 changes: 0 additions & 2 deletions src/Resume.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { Projects } from './components/Projects';
import { SkillsAndLanguages } from './components/SkillsAndLanguages';
import { Work } from './components/Work';
import { ResumeSchema } from './schema';
import { GlobalStyle } from './styles/GlobalStyle';

interface Props {
resume: ResumeSchema;
Expand All @@ -16,7 +15,6 @@ interface Props {
export const Resume: FC<Props> = ({ resume }) => {
return (
<Layout>
<GlobalStyle />
<Header basics={resume.basics} />
<Work work={resume.work} />
<Projects projects={resume.projects} />
Expand Down
15 changes: 2 additions & 13 deletions src/client.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
import { StrictMode } from 'react';
import ReactDOM from 'react-dom/client';
import resume from '../resume.json';
import { Resume } from './Resume';
import { resumeSchema } from './schema';

const App = () => {
const parsedResume = resumeSchema.parse(resume);
return (
<StrictMode>
<Resume resume={parsedResume} />
</StrictMode>
);
};
import { ClientApp } from './ClientApp';

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<App />
<ClientApp resume={resume} />
);
36 changes: 36 additions & 0 deletions src/components/Error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { ZodError } from 'zod';
import { Layout } from './Layout';
import styled from 'styled-components';
import { FC } from 'react';

export const Error: FC<{ errors: ZodError }> = ({ errors }) => {
return (
<Layout>
<h1>resume.json is invalid</h1>
<List>
{errors.errors.map((error) => (
<ListItem key={error.path.join(', ')}>
<h2>{error.message}</h2>
<div>
{error.code} at{' '}
{error.path.map((error) => `"${error}"`).join(' > ')}
</div>
</ListItem>
))}
</List>
</Layout>
);
};

const List = styled.ul`
list-style: none;
padding: 0;
margin: 0;
`;

const ListItem = styled.li`
margin-top: 48px;
div {
margin-left: 16px;
}
`;
8 changes: 7 additions & 1 deletion src/components/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { FC, PropsWithChildren } from 'react';
import styled from 'styled-components';
import { GlobalStyle } from '../styles/GlobalStyle';

export const Layout: FC<PropsWithChildren> = ({ children }) => {
return <Container>{children}</Container>;
return (
<Container>
<GlobalStyle />
{children}
</Container>
);
};

const Container = styled.div`
Expand Down
3 changes: 2 additions & 1 deletion vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export default defineConfig({
plugins: [react()],
test: {
globals: true,
exclude: [...configDefaults.exclude],
exclude: [...configDefaults.exclude, 'index.js'],
environment: 'jsdom',
setupFiles: './test/setup.ts',
coverage: {
Expand All @@ -16,6 +16,7 @@ export default defineConfig({
'**/*.test.*',
'**/*/coverage',
'**/*/client.tsx',
'index.js',
],
provider: 'c8',
},
Expand Down

0 comments on commit 09a41e7

Please sign in to comment.