From 97ca67194a6833913256f8a4d99ee22de551bf8e Mon Sep 17 00:00:00 2001 From: dima Date: Fri, 24 Oct 2025 15:53:02 +0200 Subject: [PATCH 1/2] added unit and integration tests --- .babelrc | 7 + components/__tests__/BackToTopButton.test.tsx | 41 ++++ components/__tests__/Contributors.test.tsx | 37 ++++ components/__tests__/Footer.test.tsx | 35 ++++ components/__tests__/Header.test.tsx | 186 ++++++++++++++++++ components/__tests__/LazyImage.test.tsx | 39 ++++ components/__tests__/LoadingPage.test.tsx | 48 +++++ components/__tests__/TawkToChat.test.tsx | 42 ++++ components/__tests__/ThemeSelector.test.tsx | 31 +++ components/layout/Header.tsx | 35 ++-- jest.config.js | 12 ++ package.json | 21 +- setupTests.ts | 1 + tsconfig.json | 4 +- types/jest-dom.d.ts | 1 + 15 files changed, 521 insertions(+), 19 deletions(-) create mode 100644 .babelrc create mode 100644 components/__tests__/BackToTopButton.test.tsx create mode 100644 components/__tests__/Contributors.test.tsx create mode 100644 components/__tests__/Footer.test.tsx create mode 100644 components/__tests__/Header.test.tsx create mode 100644 components/__tests__/LazyImage.test.tsx create mode 100644 components/__tests__/LoadingPage.test.tsx create mode 100644 components/__tests__/TawkToChat.test.tsx create mode 100644 components/__tests__/ThemeSelector.test.tsx create mode 100644 jest.config.js create mode 100644 setupTests.ts create mode 100644 types/jest-dom.d.ts diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..c2b9ef10 --- /dev/null +++ b/.babelrc @@ -0,0 +1,7 @@ +{ + "presets": [ + ["@babel/preset-env", { "targets": { "node": "current" } }], + ["@babel/preset-react", { "runtime": "automatic" }], + "@babel/preset-typescript" + ] +} diff --git a/components/__tests__/BackToTopButton.test.tsx b/components/__tests__/BackToTopButton.test.tsx new file mode 100644 index 00000000..a6892837 --- /dev/null +++ b/components/__tests__/BackToTopButton.test.tsx @@ -0,0 +1,41 @@ +import { render, screen, fireEvent } from '@testing-library/react' +import '@testing-library/jest-dom' +import { beforeAll, beforeEach, describe, expect, jest, test } from '@jest/globals' +import BackToTopButton from '../buttons/BackToTopButton' +import '@testing-library/jest-dom' + +describe('BackToTopButton Test', () => { + beforeAll(() => { + window.scrollTo = jest.fn() + + Object.defineProperty(window, 'scrollY', { value: 0, writable: true }) + }) + + test('Not displayed when scrollY < 300', () => { + render() + fireEvent.scroll(window) + expect(screen.queryByRole('button')).toBeNull() + }) + + test('Displayed when scrollY > 300', () => { + render() + Object.defineProperty(window, 'scrollY', { value: 400, writable: true }) + fireEvent.scroll(window) + expect(screen.getByRole('button')) + }) + + test('When clicked, it calls scrollTo with the correct parameters', () => { + render() + Object.defineProperty(window, 'scrollY', { value: 400, writable: true }) + fireEvent.scroll(window) + + const button = screen.getByRole('button') + fireEvent.click(button) + + expect(window.scrollTo).toHaveBeenCalledWith({ + top: 0, + behavior: 'smooth' + }) + }) +}) + diff --git a/components/__tests__/Contributors.test.tsx b/components/__tests__/Contributors.test.tsx new file mode 100644 index 00000000..60d95013 --- /dev/null +++ b/components/__tests__/Contributors.test.tsx @@ -0,0 +1,37 @@ +import { render, screen, fireEvent } from '@testing-library/react' +import '@testing-library/jest-dom' +import { describe, expect, test } from '@jest/globals' +import { Contributors } from '../index/Contributors' + +describe('Contributors', () => { + const mockContributors = [ + { id: '1', url: 'https://github.com/alice', avatar: '/alice.png', name: 'Alice' }, + { id: '2', url: 'https://github.com/bob', avatar: '/bob.png', name: 'Bob' } + ] + + test('renders all contributor images', () => { + render() + + const aliceImage = screen.getByAltText('Alice') + const bobImage = screen.getByAltText('Bob') + + expect(aliceImage).not.toBeNull() + expect(bobImage).not.toBeNull() + + const aliceLink = screen.getByRole('link', { name: /alice/i }) + const bobLink = screen.getByRole('link', { name: /bob/i }) + + expect(aliceLink.getAttribute('href')).toBe('https://github.com/alice') + expect(bobLink.getAttribute('href')).toBe('https://github.com/bob') + }) + + test('renders fallback when image fails to load', () => { + render() + + const aliceImage = screen.getByAltText('Alice') + fireEvent.error(aliceImage) + + const fallback = screen.getByText('A') + expect(fallback).not.toBeNull() + }) +}) diff --git a/components/__tests__/Footer.test.tsx b/components/__tests__/Footer.test.tsx new file mode 100644 index 00000000..0b23f68f --- /dev/null +++ b/components/__tests__/Footer.test.tsx @@ -0,0 +1,35 @@ +import { render, screen, waitFor } from '@testing-library/react' +import React from 'react' +import Footer from '../layout/Footer' + +jest.mock('../buttons/Coffee', () => () =>
) +jest.mock('../buttons/Sponsor', () => () =>
) + +describe('Footer', () => { + beforeEach(() => { + global.fetch = jest.fn(() => + Promise.resolve({ + json: () => Promise.resolve({ stargazers_count: 123 }) + } as Response) + ) as jest.Mock + }) + + afterEach(() => { + jest.resetAllMocks() + }) + + test('renders footer links and components', async () => { + render(