Fresh — это современный подход к рендерингу веб-приложений, при котором основной упор делается на минимизацию состояния на сервере и сокращение времени загрузки страниц за счёт генерации контента «свежим» на каждый запрос. В отличие от классических SPA и SSR-подходов, Fresh стремится избегать тяжёлого клиентского JavaScript и работает по принципу zero-runtime JavaScript, используя возможности современного браузера и сервера.
В контексте JavaScript Fresh строится вокруг следующих принципов:
Middleware в Fresh выполняет роль промежуточного слоя между запросом клиента и обработкой страницы. Он позволяет:
Middleware в Fresh реализуется как функция, принимающая объект запроса и возвращающая объект ответа или передающая управление следующему обработчику.
Пример типичной структуры middleware:
export async function middleware(req, next) {
// Проверка токена аутентификации
const token = req.headers.get("Authorization");
if (!token) {
return new Response("Unauthorized", { status: 401 });
}
// Передача управления следующему обработчику
return next();
}
Ключевые моменты:
next() передаёт управление следующему
middleware или конечному обработчику.Response,
чтобы браузер получил валидный ответ.Тестирование middleware в Fresh имеет критическое значение для обеспечения безопасности и корректного поведения приложения. Основные аспекты тестирования:
Юнит-тесты проверяют отдельные функции middleware без необходимости поднятия сервера. Для этого используют такие инструменты, как Deno Test или Jest (с эмуляцией Request и Response объектов).
Пример юнит-теста middleware:
import { middleware } from "./authMiddleware.js";
Deno.test("Возвращает 401 если токена нет", async () => {
const req = new Request("http://localhost", { headers: {} });
const response = await middleware(req, () => new Response("Next"));
const text = await response.text();
if (response.status !== 401 || text !== "Unauthorized") {
throw new Error("Тест провален");
}
});
Особенности:
Request и Response могут быть
смоделированы.Интеграционные тесты проверяют middleware вместе с маршрутизацией и
другими компонентами приложения. Обычно используют фреймворки,
поддерживающие HTTP-запросы к серверу, например, Deno’s
superoak или Node.js supertest.
Пример интеграционного теста:
import { app } from "./app.js";
import { superoak } from "https://deno.land/x/superoak/mod.ts";
Deno.test("Защищённый маршрут возвращает 401 без токена", async () => {
const request = await superoak(app);
await request.get("/protected")
.expect(401)
.expect("Unauthorized");
});
Проверка сценариев:
Для более точного тестирования используют моки
(mock) и стабсы (stub)
объектов запроса и ответов, чтобы изолировать middleware от внешних
зависимостей. Это позволяет:
Пример мок-Request:
const mockRequest = {
headers: new Map([["Authorization", "Bearer valid-token"]]),
url: "http://localhost/protected",
method: "GET"
};
next() аккуратно, чтобы не
блокировать дальнейшую обработку.Тестирование middleware в Fresh сочетает в себе строгую проверку отдельных функций и интеграцию с маршрутизатором. Использование юнит-тестов, интеграционных тестов и мок-объектов позволяет создавать надёжные и безопасные приложения, минимизируя риск ошибок на уровне промежуточной логики.
Эффективное тестирование middleware обеспечивает предсказуемое поведение приложения, защищает маршруты, ускоряет разработку и поддерживает архитектуру Fresh с её принципами минимального состояния и zero-runtime JavaScript.