Skip to content

Commit

Permalink
Merge pull request #14 from alexanderscheibler/jest
Browse files Browse the repository at this point in the history
feat: initial unit test with Jest
  • Loading branch information
alexanderscheibler authored Oct 27, 2024
2 parents 7e65a83 + 617a635 commit d4c9790
Show file tree
Hide file tree
Showing 18 changed files with 622 additions and 123 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
uses: actions/setup-node@v4
with:
node-version: "22"
cache: 'yarn'
cache: "yarn"
- name: Setup Pages
uses: actions/configure-pages@v5
with:
Expand Down
18 changes: 18 additions & 0 deletions .github/workflows/jest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Jest
on: push

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
cache: "yarn"
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Run Jest tests
env:
CI: true
run: yarn test
54 changes: 0 additions & 54 deletions app/components/Header.tsx

This file was deleted.

87 changes: 87 additions & 0 deletions app/components/Header/Header.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import {fireEvent, render, screen} from '@testing-library/react'
import Header from '../Header'
import { screens } from '@data/ScreenSizes'
import { setViewportWidth } from "@utils/functions/testHelpers";

describe('Header', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('renders AppCheckWizard brand with a link to the home page', () => {
render(<Header />);
const siteNameElement = screen.getByText(/AppCheckWizard/i);
expect(siteNameElement).toBeInTheDocument();
expect(siteNameElement).toHaveAttribute('href', '/');
});

it('renders Home link', () => {
render(<Header />);
const homeLinkElement = screen.getByRole('link', { name: /Home/i });
expect(homeLinkElement).toBeInTheDocument();
expect(homeLinkElement).toHaveAttribute('href', '#home');
});

it('renders Skills link', () => {
render(<Header />);

const skillsLinkElement = screen.getByRole("link", {name: "Help. What can I do" })
expect(skillsLinkElement).toBeInTheDocument();
expect(skillsLinkElement).toHaveAttribute('href', '#help');
});

it('renders Projects link', () => {
render(<Header />);

const skillsLinkElement = screen.getByRole("link", {name: "Projects. What have I done" })
expect(skillsLinkElement).toBeInTheDocument();
expect(skillsLinkElement).toHaveAttribute('href', '#projects');
});

it('renders Contact link', () => {
render(<Header />);

const skillsLinkElement = screen.getByRole("link", {name: "Contact" })
expect(skillsLinkElement).toBeInTheDocument();
expect(skillsLinkElement).toHaveAttribute('href', '#contact');
});

it('does render mobile menu button on mobile', () => {
setViewportWidth(screens.mobile)
render(<Header />)
const mobileMenuButton = screen.queryByTestId('mobile-menu-div')
expect(mobileMenuButton).toHaveClass('md:hidden')
})

it('does not render mobile menu button on desktop', () => {
setViewportWidth(screens.desktop)
render(<Header />)
const mobileMenuButton = screen.queryByTestId('mobile-menu-div')
expect(mobileMenuButton).toHaveClass('md:hidden')
})

it('renders mobile navigation on mobile', () => {
setViewportWidth(screens.mobile)
render(<Header />)
const mobileMenuButton = screen.queryByTestId('mobile-menu-button')
if (mobileMenuButton) {
fireEvent.click(mobileMenuButton)
}
const desktopNav = screen.getByTestId('mobile-nav')
expect(desktopNav).toBeVisible()
})

it('renders full navigation on tablet', () => {
setViewportWidth(screens.tablet)
render(<Header />)
const desktopNav = screen.getByTestId('desktop-nav')
expect(desktopNav).toBeVisible()
})

it('renders full navigation on desktop', () => {
setViewportWidth(screens.desktop)
render(<Header />)
const desktopNav = screen.getByTestId('desktop-nav')
expect(desktopNav).toBeVisible()
})
});
74 changes: 74 additions & 0 deletions app/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
'use client'

import { useState } from 'react'
import Link from 'next/link'
import { Menu, X } from 'lucide-react'
import { links } from '@data/HeaderLinks';

export default function Header() {
const [isMenuOpen, setIsMenuOpen] = useState(false)

return (
<header className="fixed w-full bg-gray-600 bg-opacity-90 z-50 backdrop-filter backdrop-blur-sm">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex items-center justify-between h-16">
<div className="flex items-center">
<Link href="/" className="text-white font-bold text-xl">
AppCheckWizard
</Link>
</div>

{/* Desktop Links */}
<div className="hidden md:block" data-testid="desktop-nav">
<div className="ml-10 flex items-baseline space-x-4">
{links.map((link) => (
<Link
key={link.href}
href={link.href}
aria-label={link.ariaLabel}
className="text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-lg font-medium"
>
{link.label}
</Link>
))}
</div>
</div>

{/* Mobile Menu Button */}
<div className="md:hidden" data-testid="mobile-menu-div">
<button
onClick={() => setIsMenuOpen(!isMenuOpen)}
className="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-800 focus:ring-white"
data-testid="mobile-menu-button"
>
<span className="sr-only">Open main menu</span>
{isMenuOpen ? (
<X className="block h-6 w-6" aria-hidden="true"/>
) : (
<Menu className="block h-6 w-6" aria-hidden="true"/>
)}
</button>
</div>
</div>
</div>
{/* Mobile Links */}
{isMenuOpen && (
<div className="md:hidden" data-testid="mobile-nav">
<div className="px-2 pt-2 pb-3 space-y-1 flex flex-col sm:px-3">
{links.map((link) => (
<Link
key={link.href}
href={link.href}
aria-label={link.ariaLabel}
onClick={() => setIsMenuOpen(false)}
className="text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-lg font-medium"
>
{link.label}
</Link>
))}
</div>
</div>
)}
</header>
)
}
1 change: 1 addition & 0 deletions app/components/Header/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './Header';
35 changes: 5 additions & 30 deletions app/components/Help.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,22 @@
import { ChevronDown } from "lucide-react";
import Link from "next/link";

export default function Help() {
import { helpCards } from '@data/HelpCards';

const items = [
{
title: "Is my app always on?",
description: "Adding monitoring and alerts so your team can catch critical issues and quickly resolve them before they affect your customers.",
},
{
title: "Is my app working?",
description: "How about we do some functional testing on the most important parts to ensure they are doing what they are supposed to be doing?",
},
{
title: "Will my app keep working if I change things?",
description: "Setting up automated tests allows you to verify that core functionality still works every time an update is made.",
},
{
title: "Can my app scale as my business grows?",
description: "Running performance tests will offer you some answers about how many users your app can safely handle.",
},
{
title: "Is my data safe and secure?",
description: "Analysis and security questionnaires tailored to your business needs, ensuring compliance with standards, including for LGPD in Brazil.",
},
{
title: "What happened with my app?!",
description: "With expertise in investigation and Root Cause Analysis (RCA), together we can identify what happened in an incident, why it happened, and the steps to prevent it in the future.",
}
]
export default function Help() {

return (
<section id="help" className="py-20 bg-gray-900">
<div className="container mx-auto px-6">
<h2 className="text-3xl font-semibold text-center mb-12">How can I help?</h2>

<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{items.map((item, index) => (
{helpCards.map((card, index) => (
<div key={index}
className="bg-gray-800 rounded-lg overflow-hidden shadow-lg hover:shadow-xl transition-shadow duration-300">
<div className="p-6">
<h3 className="text-xl font-semibold mb-2">{item.title}</h3>
<p className="text-gray-300 mb-4">{item.description}</p>
<h3 className="text-xl font-semibold mb-2">{card.title}</h3>
<p className="text-gray-300 mb-4">{card.description}</p>
</div>
</div>
))}
Expand Down
1 change: 1 addition & 0 deletions app/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as Header } from '@components/Header';
12 changes: 12 additions & 0 deletions app/data/HeaderLinks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
interface HeaderLink {
href: string;
label: string;
ariaLabel: string;
}

export const links: HeaderLink[] = [
{ href: '#home', label: 'Home', ariaLabel: 'Home' },
{ href: '#help', label: 'Skills', ariaLabel: 'Help. What can I do' },
{ href: '#projects', label: 'Projects', ariaLabel: 'Projects. What have I done' },
{ href: '#contact', label: 'Contact', ariaLabel: 'Contact' },
];
31 changes: 31 additions & 0 deletions app/data/HelpCards.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
interface HelpCard {
title: string;
description: string;
}

export const helpCards: HelpCard[] = [
{
title: "Is my app always on?",
description: "Adding monitoring and alerts so your team can catch critical issues and quickly resolve them before they affect your customers.",
},
{
title: "Is my app working?",
description: "How about we do some functional testing on the most important parts to ensure they are doing what they are supposed to be doing?",
},
{
title: "Will my app keep working if I change things?",
description: "Setting up automated tests allows you to verify that core functionality still works every time an update is made.",
},
{
title: "Can my app scale as my business grows?",
description: "Running performance tests will offer you some answers about how many users your app can safely handle.",
},
{
title: "Is my data safe and secure?",
description: "Analysis and security questionnaires tailored to your business needs, ensuring compliance with standards, including for LGPD in Brazil.",
},
{
title: "What happened with my app?!",
description: "With expertise in investigation and Root Cause Analysis (RCA), together we can identify what happened in an incident, why it happened, and the steps to prevent it in the future.",
},
];
10 changes: 10 additions & 0 deletions app/data/ScreenSizes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
type ScreenSizes = {
[key: string]: number;
};

export const screens: ScreenSizes = {
mobile: 640,
tablet: 768,
desktop: 1024,
wide: 1280
};
12 changes: 0 additions & 12 deletions jest.config.js

This file was deleted.

Loading

0 comments on commit d4c9790

Please sign in to comment.