From 549d87e800ed0900095004ca4c9f88b6b82bb04c Mon Sep 17 00:00:00 2001 From: Uzi82 Date: Sun, 15 Jun 2025 22:39:25 +0400 Subject: [PATCH 1/8] =?UTF-8?q?tests:=20=D0=91=D0=B0=D0=B7=D0=BE=D0=B2?= =?UTF-8?q?=D1=8B=D0=B5=20e2e=20=D0=B8=20unit=20=D1=82=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D1=8B=20--------------------------------------------------=20-?= =?UTF-8?q?=20=D0=91=D0=B0=D0=BD=D0=BD=D0=B5=D1=80=20=D1=82=D0=B5=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D1=8C=20=D0=BD=D0=B5=202=20=D0=BE=D1=82=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D1=85=20=D0=BA=D0=BE=D0=BC=D0=BF?= =?UTF-8?q?=D0=BE=D0=BD=D0=B5=D0=BD=D1=82=D0=B0,=20=D0=B0=201=20-=20Unit?= =?UTF-8?q?=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=B4=D0=BB=D1=8F=20=D0=BA?= =?UTF-8?q?=D0=B0=D1=80=D1=82=D0=BE=D1=87=D0=B5=D0=BA,=20=D0=B1=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D0=B5=D1=80=D0=BE=D0=B2,=20=D1=81=D0=B0=D0=B9?= =?UTF-8?q?=D0=B4=D0=B1=D0=B0=D1=80=D0=B0=20=D0=B8=20=D0=BA=D0=B0=D1=80?= =?UTF-8?q?=D1=83=D1=81=D0=B5=D0=BB=D0=B8=20-=20E2e=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D1=8B=20=D0=B4=D0=BB=D1=8F=20=D0=BE=D1=81=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BD=D0=BE=D0=B9=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=86=D1=8B=20-=20=D0=90=D1=80=D1=85=D0=B8=D1=82=D0=B5=D0=BA?= =?UTF-8?q?=D1=82=D1=83=D1=80=D0=BD=D1=8B=D0=B5=20=D1=84=D0=B8=D0=BA=D1=81?= =?UTF-8?q?=D1=8B=20-=20=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D0=B0=20husky=20-?= =?UTF-8?q?=20=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D0=B0=20GitHub=20Actions?= =?UTF-8?q?=20--------------------------------------------------?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/check.yaml | 24 +- .github/workflows/jest.yml | 24 + .github/workflows/lint.yml | 24 + .github/workflows/playwright.yml | 7 +- .husky/pre-commit | 3 +- .../(main)/components/found-\321\201ards.tsx" | 3 +- app/(main)/components/header.module.scss | 15 +- app/(main)/components/header.tsx | 1 + app/(main)/home/page.tsx | 6 +- app/libs/types/anime.ts | 2 +- .../anime-card/__tests__/anime-card.test.tsx | 67 ++ app/ui/anime-card/anime-card.tsx | 22 +- app/ui/anime-card/card-skeleton.tsx | 15 +- app/ui/anime-card/favourite-button.tsx | 3 + .../__tests__/banners-showing.test.tsx | 29 + app/ui/banners/banners-showing.tsx | 1 + app/ui/banners/banners.tsx | 7 - app/ui/carousel/__tests__/carousel.test.tsx | 52 ++ app/ui/carousel/carousel.tsx | 2 + app/ui/navigation/__tests__/sidebar.test.tsx | 29 + app/ui/navigation/nav-link.tsx | 1 + app/ui/navigation/sidebar.tsx | 2 +- .../__tests__/person-card.test.tsx | 28 + app/ui/person-card/person-card.tsx | 23 +- db.json | 608 +++++------------- eslint.config.mjs | 8 +- jest.config.ts | 19 + jest.setup.ts | 1 + package.json | 9 +- playwright.config.ts | 16 +- pnpm-lock.yaml | 110 +++- tests/example.spec.ts | 18 - tests/pages/home.spec.ts | 44 ++ 33 files changed, 689 insertions(+), 534 deletions(-) create mode 100644 .github/workflows/jest.yml create mode 100644 .github/workflows/lint.yml create mode 100644 app/ui/anime-card/__tests__/anime-card.test.tsx create mode 100644 app/ui/banners/__tests__/banners-showing.test.tsx delete mode 100644 app/ui/banners/banners.tsx create mode 100644 app/ui/carousel/__tests__/carousel.test.tsx create mode 100644 app/ui/navigation/__tests__/sidebar.test.tsx create mode 100644 app/ui/person-card/__tests__/person-card.test.tsx create mode 100644 jest.config.ts create mode 100644 jest.setup.ts delete mode 100644 tests/example.spec.ts create mode 100644 tests/pages/home.spec.ts diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 9a24689e..c2864883 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -1,5 +1,5 @@ -name: Actions -run-name: ${{ github.actor }} is testing out GitHub Actions 🚀 +name: Build +run-name: ${{ github.actor }} is testing out Next building 🚀 on: push: branches: [main] @@ -20,21 +20,5 @@ jobs: node-version: ${{ matrix.node-version }} - name: Install dependencies run: npm install --force - - name: Lint - run: npm run lint - linting: - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [22.x] - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Starting Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - name: Install dependencies - run: npm install --force - - name: Lint - run: npm run lint \ No newline at end of file + - name: Build + run: npm run build \ No newline at end of file diff --git a/.github/workflows/jest.yml b/.github/workflows/jest.yml new file mode 100644 index 00000000..00176352 --- /dev/null +++ b/.github/workflows/jest.yml @@ -0,0 +1,24 @@ +name: Jest +run-name: ${{ github.actor }} is testing out Jest tests ✈️ +on: + push: + branches: [main] + pull_request: + branches: [main] +jobs: + unit: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [22.x] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Starting Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + - name: Install dependencies + run: npm install --force + - name: Tests + run: npm run unit \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..8011eb17 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,24 @@ +name: Lint +run-name: ${{ github.actor }} is testing out Eslint ⚡ +on: + push: + branches: [main] + pull_request: + branches: [main] +jobs: + building: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [22.x] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Starting Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + - name: Install dependencies + run: npm install --force + - name: Lint + run: npm run lint \ No newline at end of file diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 81162484..3fe60926 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -1,11 +1,12 @@ name: Playwright Tests +run-name: ${{ github.actor }} is testing out Playwrite tests 🎭 on: push: - branches: [ main, master ] + branches: [ main ] pull_request: - branches: [ main, master ] + branches: [ main ] jobs: - test: + e2e: timeout-minutes: 60 runs-on: ubuntu-latest steps: diff --git a/.husky/pre-commit b/.husky/pre-commit index 098a3bea..8660941a 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,5 @@ git add . -pnpm test +pnpm playwrite +pnpm unit pnpm fix pnpm build \ No newline at end of file diff --git "a/app/(main)/components/found-\321\201ards.tsx" "b/app/(main)/components/found-\321\201ards.tsx" index 788e2d3e..a8297458 100644 --- "a/app/(main)/components/found-\321\201ards.tsx" +++ "b/app/(main)/components/found-\321\201ards.tsx" @@ -26,9 +26,10 @@ export default function FoundCards({ query }: { query: string | null }) { return (
Результаты поиска diff --git a/app/(main)/components/header.module.scss b/app/(main)/components/header.module.scss index 9d474f60..c1e3cca2 100644 --- a/app/(main)/components/header.module.scss +++ b/app/(main)/components/header.module.scss @@ -53,9 +53,20 @@ .found-container { @apply w-full flex flex-col gap-2.5 box-border overflow-hidden text-2xl; - transition-duration: 500ms; + transition-duration: 300ms; } .found-anime { @apply flex justify-between gap-5 flex-nowrap; -} \ No newline at end of file +} + +.found-open { + @apply full:h-[446px] mt-2.5; + @media (width >= 1000px) { + height: calc(20vw * 1.388888888 + 10px + 20px + 29px); + } +} + +.found-close { + @apply h-0 mt-0; +} diff --git a/app/(main)/components/header.tsx b/app/(main)/components/header.tsx index 9a0ce157..ebcbd8ec 100644 --- a/app/(main)/components/header.tsx +++ b/app/(main)/components/header.tsx @@ -38,6 +38,7 @@ export default function Header() { )} /> {/* Потом сделаем проверку на авторизацию */} @@ -17,7 +19,7 @@ export default async function Page() { Сейчас в тренде
- +
Новинки diff --git a/app/libs/types/anime.ts b/app/libs/types/anime.ts index 61c239b5..66e15529 100644 --- a/app/libs/types/anime.ts +++ b/app/libs/types/anime.ts @@ -3,7 +3,7 @@ export type AnimeCardData = { genre: string; name: string; released_at: string; - id: number; + id: string; }; export type AnimeData = { diff --git a/app/ui/anime-card/__tests__/anime-card.test.tsx b/app/ui/anime-card/__tests__/anime-card.test.tsx new file mode 100644 index 00000000..ad1b660a --- /dev/null +++ b/app/ui/anime-card/__tests__/anime-card.test.tsx @@ -0,0 +1,67 @@ +import userEvent from "@testing-library/user-event"; +import { render, screen } from "@testing-library/react"; +import AnimeCard from "../anime-card"; +import CardSkeleton from "../card-skeleton"; + +test("Проверка карточки аниме", () => { + render( + , + ); + + const card = screen.getByTestId("AnimeCard: anime-card"); + + // Тест градиента + const darkness = screen.getByTestId("AnimeCard: darkness"); + expect(darkness).toHaveStyle("opacity: 30%;"); + userEvent.hover(card); + expect(darkness).toHaveStyle("opacity: 100%;"); + + // Тест названия + const title = screen.getByTestId("AnimeCard: title"); + expect(title).toBeVisible(); + + // Тест описания + const description = screen.getByTestId("AnimeCard: year&genre"); + expect(description.textContent).toBe("2022Драма"); +}); + +test("Проверка кнопки в карточки аниме", () => { + render( + {}} + />, + ); + + const card = screen.getByTestId("AnimeCard: anime-card"); + + // Проверяю появляется ли кнопка при ховере + const button = screen.getByTestId("AnimeCard: favourite"); + expect(button).toHaveStyle("opacity: 0%;"); + userEvent.hover(card); + expect(button).toHaveStyle("opacity: 100%;"); +}); + +test("Проверка скелетона карточки", () => { + render(); + + const card = screen.getByTestId("AnimeSkeleton: container"); + const bg = screen.getByTestId("AnimeSkeleton: bg"); + const text = screen.getAllByTestId("AnimeSkeleton: text"); + + expect(card).toHaveClass("shimmer", "pulsing"); + expect(bg).toHaveClass("shimmer"); + text.forEach((el) => { + expect(el).toHaveClass("shimmer"); + }); +}); diff --git a/app/ui/anime-card/anime-card.tsx b/app/ui/anime-card/anime-card.tsx index b3384f9e..af26f08d 100644 --- a/app/ui/anime-card/anime-card.tsx +++ b/app/ui/anime-card/anime-card.tsx @@ -21,7 +21,7 @@ export default function AnimeCard({ genre: string; name: string; released_at: string; - id: number; + id: string; classes?: string; style?: CSSProperties; addToFavourite?: () => void; @@ -31,6 +31,7 @@ export default function AnimeCard({ className={clsx(classes, styles.container)} style={style} href={`/anime/${id}`} + data-testid="AnimeCard: anime-card" > anime image -
+
-

{name}

-
+

+ {name} +

+
{new Date(released_at).getFullYear()}
{AnimeGenre[genre as keyof typeof AnimeGenre]}
{addToFavourite && ( - )} diff --git a/app/ui/anime-card/card-skeleton.tsx b/app/ui/anime-card/card-skeleton.tsx index 4d4b7fd4..7ed7da94 100644 --- a/app/ui/anime-card/card-skeleton.tsx +++ b/app/ui/anime-card/card-skeleton.tsx @@ -4,12 +4,19 @@ import styles from "./card-skeleton.module.scss"; export default function CardSkeleton({ style }: { style?: CSSProperties }) { return ( -
+
- +
- - + +
diff --git a/app/ui/anime-card/favourite-button.tsx b/app/ui/anime-card/favourite-button.tsx index d1ccf6bf..a7e05f12 100644 --- a/app/ui/anime-card/favourite-button.tsx +++ b/app/ui/anime-card/favourite-button.tsx @@ -12,16 +12,19 @@ export default function FavouriteButton() { ); diff --git a/app/ui/banners/__tests__/banners-showing.test.tsx b/app/ui/banners/__tests__/banners-showing.test.tsx new file mode 100644 index 00000000..6099929e --- /dev/null +++ b/app/ui/banners/__tests__/banners-showing.test.tsx @@ -0,0 +1,29 @@ +import { render, screen, waitFor } from "@testing-library/react"; +import BannerShowing from "../banners-showing"; + +test("Проверка баннеров", async () => { + render( + , + ); + const banner = screen.getAllByTestId("Banners: banner"); + waitFor(() => { + expect(banner[0]).toHaveStyle( + "transform: translateX(calc(-100% - 20px`}))", + ); + }); +}); diff --git a/app/ui/banners/banners-showing.tsx b/app/ui/banners/banners-showing.tsx index 9db10ad9..a063ef73 100644 --- a/app/ui/banners/banners-showing.tsx +++ b/app/ui/banners/banners-showing.tsx @@ -20,6 +20,7 @@ export default function BannerShowing({ data }: { data: BannerData[] }) {
{data.map((el) => ( ; -} diff --git a/app/ui/carousel/__tests__/carousel.test.tsx b/app/ui/carousel/__tests__/carousel.test.tsx new file mode 100644 index 00000000..d2a29239 --- /dev/null +++ b/app/ui/carousel/__tests__/carousel.test.tsx @@ -0,0 +1,52 @@ +import { render, screen, waitFor } from "@testing-library/react"; +import { AnimeCardData } from "@/app/libs/types/anime"; +import userEvent from "@testing-library/user-event"; +import Carousel from "../carousel"; + +const testData: AnimeCardData[] = [ + { + id: "1", + genre: "DRAMA", + image_url: "/empty_card.png", + name: "Anime test", + released_at: "2022-01-01T00:00:00.000", + }, + { + id: "2", + genre: "DRAMA", + image_url: "/empty_card.png", + name: "Anime test", + released_at: "2022-01-01T00:00:00.000", + }, + { + id: "3", + genre: "DRAMA", + image_url: "/empty_card.png", + name: "Anime test", + released_at: "2022-01-01T00:00:00.000", + }, + { + id: "4", + genre: "DRAMA", + image_url: "/empty_card.png", + name: "Anime test", + released_at: "2022-01-01T00:00:00.000", + }, + { + id: "5", + genre: "DRAMA", + image_url: "/empty_card.png", + name: "Anime test", + released_at: "2022-01-01T00:00:00.000", + }, +]; + +test("Тест карусели", () => { + render(); + const next = screen.getByTestId("Carousel: next"); + const firstCard = screen.getAllByTestId("Carousel: card")[0]; + userEvent.click(next); + waitFor(() => { + expect(firstCard).toHaveStyle("transform: translateX(calc(-300% - 60px));"); + }); +}); diff --git a/app/ui/carousel/carousel.tsx b/app/ui/carousel/carousel.tsx index fa929421..46dc46d7 100644 --- a/app/ui/carousel/carousel.tsx +++ b/app/ui/carousel/carousel.tsx @@ -59,6 +59,7 @@ export default function Carousel({ {animeData.map((el, i) => (
diff --git a/app/ui/navigation/__tests__/sidebar.test.tsx b/app/ui/navigation/__tests__/sidebar.test.tsx new file mode 100644 index 00000000..d8e63f12 --- /dev/null +++ b/app/ui/navigation/__tests__/sidebar.test.tsx @@ -0,0 +1,29 @@ +import { render, screen, waitFor } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import SideBar from "../sidebar"; + +const mock = jest.fn(); + +jest.mock("next/navigation", () => ({ + usePathname() { + return mock(); + }, +})); + +test("Проверка навигации", () => { + mock.mockImplementation(() => "/home"); + render(); + const navLinks = screen.getAllByTestId("Sidebar: navlink"); + const currLink = screen.getByTestId("Sidebar: navlink-curr"); + waitFor(() => { + navLinks.forEach((el) => { + expect(el).toHaveStyle("filter: grayscale();"); + }); + expect(currLink).not.toHaveStyle("filter: grayscale(100%);"); + }); + + navLinks.forEach((el) => { + userEvent.hover(el); + waitFor(() => expect(el).not.toHaveStyle("filter: grayscale(100%);")); + }); +}); diff --git a/app/ui/navigation/nav-link.tsx b/app/ui/navigation/nav-link.tsx index d8730e9a..a07b4015 100644 --- a/app/ui/navigation/nav-link.tsx +++ b/app/ui/navigation/nav-link.tsx @@ -20,6 +20,7 @@ export default function NavLink({ +