> ## Documentation Index
> Fetch the complete documentation index at: https://exosphere-auto-translate-docs-20260623-1106.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Test Etme

> Birim testleri, uçtan uca testler ve test yardımcıları

failproofai iki test paketi içerir: **birim testleri** (hızlı, mock'lanmış) ve **uçtan uca testler** (gerçek alt işlem çağrıları).

***

## Testleri çalıştırma

```bash theme={null}
# Tüm birim testlerini bir kez çalıştır
bun run test:run

# Birim testlerini izleme modunda çalıştır
bun run test

# E2E testlerini çalıştır (kurulum gerekli - aşağıya bakınız)
bun run test:e2e

# Derlenmeden tip kontrolü yap
bunx tsc --noEmit

# Lint'i çalıştır
bun run lint
```

***

## Birim testleri

Birim testleri `__tests__/` dizininde bulunur ve `jsdom` ile birlikte [Vitest](https://vitest.dev) kullanır.

```text theme={null}
__tests__/
  hooks/
    builtin-policies.test.ts      # Her yerleşik politika için politika mantığı
    hooks-config.test.ts          # Config yükleme ve kapsam birleştirme
    policy-evaluator.test.ts      # Parametre enjeksiyonu ve değerlendirme sırası
    custom-hooks-registry.test.ts # globalThis kayıt defteri ekleme/alma/temizleme
    custom-hooks-loader.test.ts   # ESM yükleyici, geçişli içe aktarımlar, hata işleme
    manager.test.ts               # yükleme/kaldırma/listeleme işlemleri
  components/
    sessions-list.test.tsx        # Oturum listesi bileşeni
    project-list.test.tsx         # Proje listesi bileşeni
    ...
  lib/
    logger.test.ts
    paths.test.ts
    date-filters.test.ts
    telemetry.test.ts
    ...
  actions/
    get-hooks-config.test.ts
    get-hook-activity.test.ts
    ...
  contexts/
    ThemeContext.test.tsx
    AutoRefreshContext.test.tsx
```

### Politika birim testi yazma

```typescript theme={null}
import { describe, it, expect, beforeEach } from "vitest";
import { getBuiltinPolicies } from "../../src/hooks/builtin-policies";
import { allow, deny } from "../../src/hooks/policy-types";

describe("block-sudo", () => {
  const policy = getBuiltinPolicies().find((p) => p.name === "block-sudo")!;

  it("sudo komutlarını reddeder", () => {
    const ctx = {
      eventType: "PreToolUse" as const,
      payload: {},
      toolName: "Bash",
      toolInput: { command: "sudo apt install nodejs" },
      params: { allowPatterns: [] },
    };
    expect(policy.fn(ctx)).toEqual(deny("sudo command blocked by failproofai"));
  });

  it("sudo olmayan komutlara izin verir", () => {
    const ctx = {
      eventType: "PreToolUse" as const,
      payload: {},
      toolName: "Bash",
      toolInput: { command: "ls -la" },
      params: { allowPatterns: [] },
    };
    expect(policy.fn(ctx)).toEqual(allow());
  });

  it("allowPatterns içindeki desenlere izin verir", () => {
    const ctx = {
      eventType: "PreToolUse" as const,
      payload: {},
      toolName: "Bash",
      toolInput: { command: "sudo systemctl status nginx" },
      params: { allowPatterns: ["sudo systemctl status"] },
    };
    expect(policy.fn(ctx)).toEqual(allow());
  });
});
```

***

## Uçtan uca testler

E2E testleri gerçek `failproofai` ikili dosyasını alt işlem olarak çağırır, stdin'e JSON yükü aktarır ve stdout çıktısı ile çıkış kodunu doğrular. Bu, Claude Code tarafından kullanılan tam entegrasyon yolunu test eder.

### Kurulum

E2E testleri, ikili dosyayı doğrudan repo kaynağından çalıştırır. İlk çalıştırmadan önce, özel kanca dosyalarının `'failproofai'`'den içe aktarırken kullandığı CJS paketini oluşturun:

```bash theme={null}
bun build src/index.ts --outdir dist --target node --format cjs
```

Ardından testleri çalıştırın:

```bash theme={null}
bun run test:e2e
```

Genel kanca API'sini değiştirdiğinizde (`src/hooks/custom-hooks-registry.ts`, `src/hooks/policy-helpers.ts` veya `src/hooks/policy-types.ts`) `dist/` dizinini yeniden derleyin.

### E2E test yapısı

```text theme={null}
__tests__/e2e/
  helpers/
    hook-runner.ts      # İkili dosyayı başlat, yükü JSON olarak aktar, çıkış kodu + stdout + stderr'ı yakala
    fixture-env.ts      # Config dosyaları ile test başına izole edilmiş temp dizinler
    payloads.ts         # Her olay türü için Claude'a uygun yükü üreten fabrikalar
  hooks/
    builtin-policies.e2e.test.ts   # Her yerleşik politika gerçek alt işlem ile
    custom-hooks.e2e.test.ts       # Özel kanca yükleme ve değerlendirmesi
    config-scopes.e2e.test.ts      # Proje/yerel/küresel arasında config birleştirme
    policy-params.e2e.test.ts      # Parametreli her politika için parametre enjeksiyonu
```

### E2E yardımcılarını kullanma

**`FixtureEnv`** - test başına izole ortam:

```typescript theme={null}
import { createFixtureEnv } from "../helpers/fixture-env";

const env = createFixtureEnv();
// env.cwd    - temp dizin; .failproofai/policies-config.json almak için payload.cwd olarak geçir
// env.home   - izole ev dizini; gerçek ~/.failproofai sızıntısı olmaz

env.writeConfig({
  enabledPolicies: ["block-sudo"],
  policyParams: {
    "block-sudo": { allowPatterns: ["sudo systemctl status"] },
  },
});
```

`createFixtureEnv()` `afterEach` temizliğini otomatik olarak kaydeder.

**`runHook`** - ikili dosyayı çağır:

```typescript theme={null}
import { runHook } from "../helpers/hook-runner";
import { Payloads } from "../helpers/payloads";

const result = await runHook(
  "PreToolUse",
  Payloads.preToolUse.bash("sudo apt install nodejs", env.cwd),
  { homeDir: env.home }
);

expect(result.exitCode).toBe(0);
expect(result.parsed?.hookSpecificOutput?.permissionDecision).toBe("deny");
```

**`Payloads`** - hazır yükü üreten fabrikalar:

```typescript theme={null}
Payloads.preToolUse.bash(command, cwd)
Payloads.preToolUse.write(filePath, content, cwd)
Payloads.preToolUse.read(filePath, cwd)
Payloads.postToolUse.bash(command, output, cwd)
Payloads.postToolUse.read(filePath, content, cwd)
Payloads.notification(message, cwd)
Payloads.stop(cwd)
```

### E2E test yazma

```typescript theme={null}
import { describe, it, expect } from "vitest";
import { createFixtureEnv } from "../helpers/fixture-env";
import { runHook } from "../helpers/hook-runner";
import { Payloads } from "../helpers/payloads";

describe("block-rm-rf (E2E)", () => {
  it("rm -rf komutunu reddeder", async () => {
    const env = createFixtureEnv();
    env.writeConfig({ enabledPolicies: ["block-rm-rf"] });

    const result = await runHook(
      "PreToolUse",
      Payloads.preToolUse.bash("rm -rf /", env.cwd),
      { homeDir: env.home }
    );

    expect(result.exitCode).toBe(0);
    expect(result.parsed?.hookSpecificOutput?.permissionDecision).toBe("deny");
  });

  it("tekrarsız rm'ye izin verir", async () => {
    const env = createFixtureEnv();
    env.writeConfig({ enabledPolicies: ["block-rm-rf"] });

    const result = await runHook(
      "PreToolUse",
      Payloads.preToolUse.bash("rm /tmp/file.txt", env.cwd),
      { homeDir: env.home }
    );

    expect(result.exitCode).toBe(0);
    expect(result.stdout).toBe("");  // izin ver → boş stdout
  });
});
```

### E2E yanıt şekilleri

| Karar                | Çıkış kodu | stdout                                                                                  |
| -------------------- | ---------- | --------------------------------------------------------------------------------------- |
| `PreToolUse` reddet  | `0`        | `{"hookSpecificOutput":{"permissionDecision":"deny","permissionDecisionReason":"..."}}` |
| `PostToolUse` reddet | `0`        | `{"hookSpecificOutput":{"additionalContext":"Blocked ... because: ..."}}`               |
| Talimat (Stop dışı)  | `0`        | `{"hookSpecificOutput":{"additionalContext":"Instruction from failproofai: ..."}}`      |
| Stop talimatı        | `2`        | boş stdout; sebep stderr'de                                                             |
| İzin ver             | `0`        | boş dize                                                                                |

### Vitest config

E2E testleri `vitest.config.e2e.mts` dosyasını şu ayarlarla kullanır:

* `environment: "node"` - tarayıcı küresellerine gerek yok
* `pool: "forks"` - gerçek işlem izolasyonu (testler alt işlemleri başlatır)
* `testTimeout: 20_000` - test başına 20sn (ikili başlatma + kanca değerlendirmesi)

`forks` havuzu önemlidir: thread tabanlı çalışanlar `globalThis` paylaşır ve bu alt işlemleri başlatan testlerde müdahale edebilir. İşlem tabanlı fork'lar bunu önler.

***

## CI

Birleştirmeden önce tam CI çalıştırması (`bun run lint && bunx tsc --noEmit && bun run test:run && bun run build`) geçmesi gerekir. E2E paketi paralel olarak ayrı bir CI işi olarak çalışır.

Tam ön birleştirme kontrol listesi için [Katkıda Bulunma](../CONTRIBUTING.md) bölümüne bakınız.
