الاختبار

المكونات والدوال الخادمية دوال عادية، لذا يمكن اختبار الاثنين مباشرة. لا حاجة إلى بيئة DOM ولا إلى مكتبة تصيير.

الإعداد

يشغّل سكربت الاختبار Vitest مع تغطية V8. استثنِ نقاط الدخول وملف الأوجه ومجلد DTO من التغطية، لأنها ربط لا منطق.

// vitest.config.ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    coverage: {
      reporter: [
        "text",
        "html",
        "lcov"
      ],
      include: ['src/**/*.{ts,tsx}'],
      exclude: [
        'src/client/entrypoint.ts',
        'src/server/entrypoint.ts',
        'src/client/facets.cara.ts',
        'src/infra/**/*',
        'src/dto/**/*',
        '**/*.d.ts',
      ],
    },
  },
});

اختبار مكوّن

استدعِ init مرة واحدة من jjsx لتثبيت المترجم، ثم استدعِ transpile بعنصر JSX للحصول على سلسلة HTML. عادةً ما يكفي التأكيد على مقاطع من تلك السلسلة ويبقى الاختبار خاليًا من DOM.

// src/client/__tests__/profile-page.test.tsx
import { expect, test } from "vitest";
import { init, transpile } from "jjsx";
import Profile from "../pages/profile";

init();

test("Render profile page", () => {
    const mockUser = {
        id: "1",
        name: "John Doe",
        email: "john@example.com",
        username: "johndoe",
        phone: "123-456-7890",
        website: "johndoe.com",
    };

    const page = transpile(<Profile {...mockUser} />);

    expect(page).toContain('app-header');
    expect(page).toContain("John Doe");
    expect(page).toContain("john@example.com");
    expect(page).toContain("Vault Member");
});

يقبل المكوّن المُبرَز خصائص خادمه كخصائص عادية، لذا يُصيَّر العنصر نفسه ببيانات وهمية في الاختبار تمامًا كما يُصيَّر على الخادم.

‏`init()`‎ تثبّت مترجم JJSX ويجب أن تعمل قبل أول استدعاء لـ `transpile`. ولأن النتيجة سلسلة HTML عادية، فلا يوجد DOM لإعداده ولا مكتبة تصيير لضبطها.

اختبار دالة خادمية

الدالة الخادمية دالة من طلب إلى قيمة. مرِّر كائنًا عاديًا فيه params واستدعِها. لا يوجد خادم لتشغيله، وهذا هو السبب الرئيسي لكون الدوال الخادمية رخيصة الاختبار.

// src/server/__tests__/trade-api.test.ts
import { describe, expect, test } from "vitest";
import getTradeData from "../culets/trade";

describe("Trade API", () => {
    test("GET /trade/btc", async () => {
        const mockRequest = {
            params: { symbol: "btc" },
            url: "/trade/btc",
            query: {},
            headers: {},
            cookies: {},
            method: "GET",
        };
        const result = await getTradeData(mockRequest);
        expect(result.symbol).toBe("BTC");
        expect(result.price).toBeDefined();
        expect(result.orderBook.bids.length).toBeGreaterThan(0);
    });
});

‏`@fetch-mock/vitest`‎ متاح لدالة خادمية تستدعي واجهة برمجية بعيدة، ما يُبقي الاختبار دون اتصال وحتميًا.

التغطية

لا يمكن ترجمة مكوّن يقرأ ‎`window`‎ أو ‎`document`‎ مباشرة في جسمه في الاختبار، لأن بيئة الاختبار بلا مستند. وهذه إشارة مفيدة لا عقبة: فهي تعني أن الأثر الجانبي ينتمي إلى استدعاء afterMount أو beforeMount، حيث يُبقيه الإطار أصلًا خارج التصيير على الخادم.