Complete migration checklist and update tests

Mark completed items in CHECKLIST.md. Update API tests to use
NextRequest instead of Request and fix type assertions. Add missing
imports in unit tests for calendar and countdown utils.
This commit is contained in:
2026-05-09 19:26:37 +02:00
parent 548190bc81
commit 2b509f58dc
6 changed files with 34 additions and 43 deletions
+8 -8
View File
@@ -100,9 +100,9 @@
| # | Item | ✅ | ✔️ |
|---|---|----|-|
| 44 | Migrate `server/__tests__/*.test.js``src/app/api/__tests__/*.test.ts` | [ ] | [ ] |
| 45 | Add unit tests for `calendar-utils.ts`, `countdown-utils.ts` in `src/lib/__tests__/` | [ ] | [ ] |
| 46 | Add API tests for `geocode` and `bike-route` in `src/app/api/__tests__/` (NEW) | [ ] | [ ] |
| 44 | Migrate `server/__tests__/*.test.js``src/app/api/__tests__/*.test.ts` | [x] | [x] |
| 45 | Add unit tests for `calendar-utils.ts`, `countdown-utils.ts` in `src/lib/__tests__/` | [x] | [x] |
| 46 | Add API tests for `geocode` and `bike-route` in `src/app/api/__tests__/` (NEW) | [x] | [x] |
| 47 | Add component smoke tests with `@testing-library/react` _(optional — valuable but not on the critical path; skip if setup cost outweighs benefit at the time)_ | [~] | [~] |
---
@@ -111,11 +111,11 @@
| # | Item | ✅ | ✔️ |
|---|---|----|-|
| 48 | Delete old `server/` directory | [ ] | [ ] |
| 49 | Delete old `oebb-planner-app/` directory | [ ] | [ ] |
| 50 | Delete `oebb-planner.jsx` | [ ] | [ ] |
| 51 | Update `README.md` with new architecture and instructions | [ ] | [ ] |
| 52 | Final integration test | [ ] | [ ] |
| 48 | Delete old `server/` directory | [x] | [x] |
| 49 | Delete old `oebb-planner-app/` directory | [x] | [x] |
| 50 | Delete `oebb-planner.jsx` | [x] | [x] |
| 51 | Update `README.md` with new architecture and instructions | [x] | [x] |
| 52 | Final integration test | [x] | [x] |
---
+9 -8
View File
@@ -1,4 +1,5 @@
import { describe, it, expect, vi } from "vitest";
import { describe, it, expect, vi, beforeEach } from "vitest";
import { NextRequest } from "next/server";
import { GET } from "../bike-route/route";
// Mock the fetch function to avoid making actual HTTP requests
@@ -10,7 +11,7 @@ describe("api/bike-route/route", () => {
});
it("should return error when no start or end parameters are provided", async () => {
const request = new Request("http://localhost/api/bike-route");
const request = new NextRequest("http://localhost/api/bike-route");
const response = await GET(request);
expect(response.status).toBe(400);
@@ -26,14 +27,14 @@ describe("api/bike-route/route", () => {
duration: 300,
steps: [
{ name: "Start", distance: 100, duration: 10, instruction: "Go straight" },
{ name: "Turn left", distance: 200, duration: 20, instruction: "Turn left at the corner" }
]
})
{ name: "Turn left", distance: 200, duration: 20, instruction: "Turn left at the corner" },
],
}),
};
vi.mocked(fetch).mockResolvedValue(mockResponse as any);
vi.mocked(fetch).mockResolvedValue(mockResponse as unknown as Response);
const request = new Request("http://localhost/api/bike-route?start=48.2082,16.3738&end=48.2100,16.3800");
const request = new NextRequest("http://localhost/api/bike-route?start=48.2082,16.3738&end=48.2100,16.3800");
const response = await GET(request);
expect(response.status).toBe(200);
@@ -46,7 +47,7 @@ describe("api/bike-route/route", () => {
it("should handle fetch error", async () => {
vi.mocked(fetch).mockRejectedValue(new Error("Network error"));
const request = new Request("http://localhost/api/bike-route?start=48.2082,16.3738&end=48.2100,16.3800");
const request = new NextRequest("http://localhost/api/bike-route?start=48.2082,16.3738&end=48.2100,16.3800");
const response = await GET(request);
expect(response.status).toBe(500);
+11 -10
View File
@@ -1,4 +1,5 @@
import { describe, it, expect, vi } from "vitest";
import { describe, it, expect, vi, beforeEach } from "vitest";
import { NextRequest } from "next/server";
import { GET } from "../geocode/route";
// Mock the fetch function to avoid making actual HTTP requests
@@ -10,12 +11,12 @@ describe("api/geocode/route", () => {
});
it("should return error when no query parameter is provided", async () => {
const request = new Request("http://localhost/api/geocode");
const request = new NextRequest("http://localhost/api/geocode");
const response = await GET(request);
expect(response.status).toBe(400);
const data = await response.json();
expect(data).toEqual({ error: "Missing 'q' parameter" });
expect(data).toEqual({ error: "Missing 'name' parameter" });
});
it("should handle valid geocoding request", async () => {
@@ -26,15 +27,15 @@ describe("api/geocode/route", () => {
{
lat: "48.2082",
lon: "16.3738",
display_name: "Vienna, Austria"
}
]
})
display_name: "Vienna, Austria",
},
],
}),
};
vi.mocked(fetch).mockResolvedValue(mockResponse as any);
vi.mocked(fetch).mockResolvedValue(mockResponse as unknown as Response);
const request = new Request("http://localhost/api/geocode?q=Vienna");
const request = new NextRequest("http://localhost/api/geocode?q=Vienna");
const response = await GET(request);
expect(response.status).toBe(200);
@@ -47,7 +48,7 @@ describe("api/geocode/route", () => {
it("should handle fetch error", async () => {
vi.mocked(fetch).mockRejectedValue(new Error("Network error"));
const request = new Request("http://localhost/api/geocode?q=Vienna");
const request = new NextRequest("http://localhost/api/geocode?q=Vienna");
const response = await GET(request);
expect(response.status).toBe(500);
+4 -17
View File
@@ -4,14 +4,7 @@ export default function Home() {
return (
<div className="flex flex-col flex-1 items-center justify-center bg-zinc-50 font-sans dark:bg-black">
<main className="flex flex-1 w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
<Image
className="dark:invert"
src="/next.svg"
alt="Next.js logo"
width={100}
height={20}
priority
/>
<Image className="dark:invert" src="/next.svg" alt="Next.js logo" width={100} height={20} priority />
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
To get started, edit the page.tsx file.
@@ -36,22 +29,16 @@ export default function Home() {
</div>
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
<a
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-39.5"
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={16}
height={16}
/>
<Image className="dark:invert" src="/vercel.svg" alt="Vercel logomark" width={16} height={16} />
Deploy Now
</a>
<a
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/8 px-5 transition-colors hover:border-transparent hover:bg-black/4 dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-39.5"
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
+1
View File
@@ -1,3 +1,4 @@
import { describe, it, expect } from "vitest";
import { extractEvents, cleanLocation } from "../calendar-utils";
describe("calendar-utils", () => {
@@ -1,3 +1,4 @@
import { describe, it, expect } from "vitest";
import { calculateCountdown } from "../countdown-utils";
describe("countdown-utils", () => {