diff --git a/package.json b/package.json
index 42291ce..ded9255 100644
--- a/package.json
+++ b/package.json
@@ -13,7 +13,7 @@
"format": "npx standard --fix",
"prepare": "husky",
"deploy": "./util/deploy-gcloud.sh",
- "test": "jest"
+ "test": "jest --verbose"
},
"dependencies": {
"next": "14.1.1",
diff --git a/src/components/CV/CV.jsx b/src/components/CV/CV.jsx
index 61ac9fb..aedaafb 100644
--- a/src/components/CV/CV.jsx
+++ b/src/components/CV/CV.jsx
@@ -2,7 +2,7 @@ import React from 'react'
import style from './CV.module.css'
-function CV ({
+function Cv ({
competencies,
education,
certifications,
@@ -57,7 +57,7 @@ function CV ({
)
}
-export default CV
+export default Cv
function CVWorkExperience ({ position, employer, start, end, children }) {
return (
diff --git a/src/components/CV/CV.module.css b/src/components/CV/Cv.css
similarity index 100%
rename from src/components/CV/CV.module.css
rename to src/components/CV/Cv.css
diff --git a/src/components/CV/Cv.test.jsx b/src/components/CV/Cv.test.jsx
new file mode 100644
index 0000000..a50e5d7
--- /dev/null
+++ b/src/components/CV/Cv.test.jsx
@@ -0,0 +1,63 @@
+/* eslint-env jest */
+import { render } from '@testing-library/react'
+import Cv from './Cv'
+import '@testing-library/jest-dom'
+
+describe('Cv', () => {
+ const props = {
+ competencies: ['Competency 1', 'Competency 2'],
+ education: 'My education history',
+ certifications: ['Certification 1', 'Certification 2'],
+ languages: [{ name: 'English', proficiency: 'Fluent' }],
+ experience: [
+ {
+ employer: 'Employer 1',
+ position: 'Position 1',
+ start: 'Start date 1',
+ end: 'End date 1',
+ desc: 'Description 1'
+ }
+ ]
+ }
+
+ it('renders without crashing', () => {
+ render()
+ })
+
+ it('renders competencies', () => {
+ const { getByText } = render()
+ props.competencies.forEach(competency => {
+ expect(getByText(competency)).toBeInTheDocument()
+ })
+ })
+
+ it('renders education', () => {
+ const { getByText } = render()
+ expect(getByText(props.education)).toBeInTheDocument()
+ })
+
+ it('renders certifications', () => {
+ const { getByText } = render()
+ props.certifications.forEach(certification => {
+ expect(getByText(certification)).toBeInTheDocument()
+ })
+ })
+
+ it('renders languages', () => {
+ const { getByText } = render()
+ props.languages.forEach(language => {
+ expect(getByText(`${language.name} - ${language.proficiency}`)).toBeInTheDocument()
+ })
+ })
+
+ it('renders experience', () => {
+ const { getByText } = render()
+ props.experience.forEach(exp => {
+ expect(getByText(exp.employer)).toBeInTheDocument()
+ expect(getByText(exp.position)).toBeInTheDocument()
+ expect(getByText(exp.start)).toBeInTheDocument()
+ expect(getByText(exp.end)).toBeInTheDocument()
+ expect(getByText(exp.desc)).toBeInTheDocument()
+ })
+ })
+})
diff --git a/src/components/ExternalLink/ExsternalLink.test.jsx b/src/components/ExternalLink/ExsternalLink.test.jsx
new file mode 100644
index 0000000..40c72ac
--- /dev/null
+++ b/src/components/ExternalLink/ExsternalLink.test.jsx
@@ -0,0 +1,28 @@
+/* eslint-env jest */
+import { render, screen } from '@testing-library/react'
+import ExternalLink from './ExternalLink'
+import '@testing-library/jest-dom'
+
+describe('ExternalLink', () => {
+ const props = {
+ href: 'https://example.com',
+ children: 'Test Link'
+ }
+
+ it('renders without crashing', () => {
+ render()
+ })
+
+ it('renders correct href and rel attributes', () => {
+ render()
+ const link = screen.getByText(props.children)
+ expect(link).toHaveAttribute('href', props.href)
+ expect(link).toHaveAttribute('rel', 'nofollow noopener')
+ expect(link).toHaveAttribute('target', '_blank')
+ })
+
+ it('renders children correctly', () => {
+ render()
+ expect(screen.getByText(props.children)).toBeInTheDocument()
+ })
+})
diff --git a/src/components/ExternalLink.jsx b/src/components/ExternalLink/ExternalLink.jsx
similarity index 100%
rename from src/components/ExternalLink.jsx
rename to src/components/ExternalLink/ExternalLink.jsx
diff --git a/src/components/Footer/Footer.test.jsx b/src/components/Footer/Footer.test.jsx
new file mode 100644
index 0000000..822bb13
--- /dev/null
+++ b/src/components/Footer/Footer.test.jsx
@@ -0,0 +1,10 @@
+/* eslint-env jest */
+import { render } from '@testing-library/react'
+import Footer from './Footer'
+import '@testing-library/jest-dom'
+
+describe('Footer', () => {
+ it('renders without crashing', () => {
+ render()
+ })
+})
diff --git a/src/components/Grid/Grid.test.jsx b/src/components/Grid/Grid.test.jsx
new file mode 100644
index 0000000..a769f6d
--- /dev/null
+++ b/src/components/Grid/Grid.test.jsx
@@ -0,0 +1,16 @@
+/* eslint-env jest */
+import { render } from '@testing-library/react'
+import Grid from './Grid'
+import '@testing-library/jest-dom'
+
+describe('Grid', () => {
+ it('renders without crashing', () => {
+ const { container } = render()
+ expect(container.firstChild).toHaveClass('grid')
+ })
+
+ it('renders its children', () => {
+ const { getByText } = render(Child
)
+ expect(getByText('Child')).toBeInTheDocument()
+ })
+})
diff --git a/src/components/Header/Header.test.jsx b/src/components/Header/Header.test.jsx
new file mode 100644
index 0000000..963d82f
--- /dev/null
+++ b/src/components/Header/Header.test.jsx
@@ -0,0 +1,19 @@
+/* eslint-env jest */
+import { render, screen } from '@testing-library/react'
+import Header from './Header'
+import '@testing-library/jest-dom'
+
+describe('Header', () => {
+ it('renders without crashing', () => {
+ render(
+ )
+ })
+
+ it('renders correct navigation links', () => {
+ render()
+ const links = ['Home', 'Writing', 'Recipes', 'Fun', 'CV']
+ links.forEach(link => {
+ expect(screen.getByText(link)).toBeInTheDocument()
+ })
+ })
+})
diff --git a/src/pages/cv/index.js b/src/pages/cv/index.js
index 4a11954..96cb276 100644
--- a/src/pages/cv/index.js
+++ b/src/pages/cv/index.js
@@ -1,4 +1,4 @@
-import CV from '@/components/CV/CV'
+import Cv from '@/components/Cv/Cv'
import DefaultLayout from '@/layouts/DefaultLayout/DefaultLayout'
import React from 'react'
import yaml from 'js-yaml'
@@ -21,7 +21,7 @@ function CVPage ({
{/* eslint-disable-next-line react/jsx-pascal-case */}
-