Skip to content

Commit

Permalink
Introduce unit tests (#3)
Browse files Browse the repository at this point in the history
* Introduce unit tests with vitest

* Remove unused code/packages

* Run unit-tests in CI

* Fix issue with rehypePlugin

* Add missing tests

* Fix vitest snapshots

Prior to this commit the generated vitest snapshots were empty.
I discovered in order to avoid that I need to access first to the screen.
  • Loading branch information
abel-castro authored Aug 12, 2024
1 parent 3a1de8c commit 21b2b4d
Show file tree
Hide file tree
Showing 22 changed files with 2,982 additions and 634 deletions.
File renamed without changes.
31 changes: 31 additions & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Unit Tests

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [20]

steps:
- uses: actions/checkout@v3

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm install -g pnpm && pnpm install
- run: pnpm test:coverage

- name: Upload coverage reports to Codecov
uses: codecov/[email protected]
with:
token: ${{ secrets.CODECOV_TOKEN }}
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[![codecov](https://codecov.io/github/abel-castro/abelcastro.dev-next/branch/main/graph/badge.svg?token=YOUR_TOKEN)](github/abel-castro/abelcastro.dev-next)

# blog.abelcastro.dev

The first version of my blog was developed with Django (see more here https://github.com/abel-castro/abelcastro.dev).
Expand Down Expand Up @@ -58,6 +60,22 @@ Open [http://localhost:3000](http://localhost:3000) with your browser to see the

## Tests

### Unit tests
This project provides unit tests with vitest.

Run:

```sh
pnpm test
```

With coverage:

```sh
pnpm test:coverage
```

### End to end tests
This project provides e2e test with playwright.

Headless run:
Expand All @@ -71,3 +89,4 @@ Run with UI:
```sh
pnpm exec playwright test --ui
```

2 changes: 1 addition & 1 deletion app/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export async function generateMetadata(
};
}

export default async function Page({ params }: { params: { slug: string } }) {
export default async function SinglePostPage({ params }: { params: { slug: string } }) {
const slug = params.slug;
const post = await fetchSinglePost(slug);

Expand Down
1 change: 1 addition & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import "server-only";
import { Analytics } from "@vercel/analytics/react";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
Expand Down
13 changes: 13 additions & 0 deletions app/lib/fetchPosts.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { POST_PAGE_SIZE } from "../constants";
import { Post, PostsAPIResponse } from "./definitions";

interface FetchAllPostsOptions {
Expand Down Expand Up @@ -43,3 +44,15 @@ export async function fetchSinglePost(slug: string): Promise<Post | null> {
}
return res.json();
}

export async function getPostsAndTotalPages(
query: string,
currentPage: number
) {
const postsResponse = await fetchAllPosts({ query, page: currentPage });
const totalPages = Math.ceil(postsResponse.count / POST_PAGE_SIZE);
return {
posts: postsResponse.results,
totalPages,
};
}
27 changes: 12 additions & 15 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
import "server-only";
import BlogFooter from "./components/blog-footer";
import BlogHeader from "./components/blog-header";
import PostList from "./components/posts/post-list";
import { Suspense } from "react";
import { PostListSkeleton } from "./components/posts/skeletons";
import { fetchAllPosts } from "./lib/fetchPosts";
import { getPostsAndTotalPages } from "./lib/fetchPosts";
import Pagination from "./components/posts/post-pagination";
import { POST_PAGE_SIZE } from "./constants";

async function getPostsAndTotalPages(query: string, currentPage: number) {
const postsResponse = await fetchAllPosts({ query, page: currentPage });
const totalPages = Math.ceil(postsResponse.count / POST_PAGE_SIZE);
return {
posts: postsResponse.results,
totalPages,
};
}
export type HomeSearchParams = {
query?: string;
page?: string;
};

export default async function Home({
searchParams,
}: {
searchParams?: {
query?: string;
page?: string;
};
searchParams?: HomeSearchParams;
}) {
const query = searchParams?.query || "";
const currentPage = Number(searchParams?.page) || 1;
Expand All @@ -32,7 +25,11 @@ export default async function Home({
<>
<BlogHeader />
<main className="flex-grow p-4">
<div id="post-container" className="max-w-4xl mx-auto">
<div
id="post-container"
data-testid="post-container"
className="max-w-4xl mx-auto"
>
<Suspense key={query + currentPage} fallback={<PostListSkeleton />}>
<PostList posts={posts} />
</Suspense>
Expand Down
2 changes: 1 addition & 1 deletion app/privacy-policy/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import Link from "next/link";

export default async function Page() {
export default function PrivacyPolicyPage() {
return (
<>
<main>
Expand Down
20 changes: 3 additions & 17 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,18 +1,4 @@
// next.config.mjs
import withMDX from "@next/mdx";
import rehypeSlug from "rehype-slug";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
import rehypeHighlight from "rehype-highlight";
/** @type {import('next').NextConfig} */
const nextConfig = {};

const mdxOptions = {
extension: /\.mdx?$/,
options: {
rehypePlugins: [rehypeSlug, rehypeAutolinkHeadings, rehypeHighlight],
},
};

const nextConfig = {
pageExtensions: ["js", "jsx", "ts", "tsx", "md", "mdx"],
};

export default withMDX(mdxOptions)(nextConfig);
export default nextConfig;
34 changes: 21 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"test": "vitest",
"test:coverage": "vitest --coverage --reporter=verbose",
"test:e2e": "exec playwright test"
},
"dependencies": {
"@heroicons/react": "^2.1.5",
Expand All @@ -23,33 +26,38 @@
"dotenv": "^16.4.5",
"highlight.js": "^11.10.0",
"install": "^0.13.0",
"next": "14.2.3",
"next": "^15.0.0-rc.0",
"next-mdx-remote": "^5.0.0",
"prismjs": "^1.29.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react": "canary",
"react-dom": "canary",
"rehype-autolink-headings": "^7.1.0",
"rehype-highlight": "^7.0.0",
"rehype-slug": "^6.0.0",
"rehype-stringify": "^10.0.0",
"remark": "^15.0.1",
"remark-html": "^16.0.1",
"remark-parse": "^11.0.0",
"remark-prism": "^1.3.6",
"remark-rehype": "^11.1.0",
"use-debounce": "^10.0.2"
},
"devDependencies": {
"@playwright/test": "^1.45.3",
"@types/mapbox__rehype-prism": "^0.8.3",
"@testing-library/react": "^16.0.0",
"@types/node": "^20.14.13",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/refractor": "^3.4.1",
"@vitejs/plugin-react": "^4.3.1",
"@vitejs/plugin-react-swc": "^3.7.0",
"@vitest/coverage-v8": "^2.0.5",
"eslint": "^8.57.0",
"eslint-config-next": "14.2.3",
"eslint-config-next": "14.2.5",
"jsdom": "^24.1.1",
"postcss": "^8.4.40",
"server-only": "^0.0.1",
"tailwindcss": "^3.4.7",
"typescript": "^5.5.4"
"typescript": "^5.5.4",
"vite-tsconfig-paths": "^4.3.2",
"vitest": "^2.0.5"
},
"overrides": {
"react": "canary",
"react-dom": "canary"
}
}
2 changes: 1 addition & 1 deletion playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { defineConfig, devices } from "@playwright/test";
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./e2e-tests",
testDir: "./tests/e2e-tests",
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
Expand Down
Loading

0 comments on commit 21b2b4d

Please sign in to comment.