Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  plugin-hooks.test.ts

  Sprache: JAVA
 

Spracherkennung für: .ts vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

import fs from "node:fs";
import fsp from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
import type { OpenClawConfig } from "../config/config.js";
import {
  clearInternalHooks,
  createInternalHookEvent,
  setInternalHooksEnabled,
  triggerInternalHook,
} from "./internal-hooks.js";
import { loadInternalHooks } from "./loader.js";
import { loadWorkspaceHookEntries } from "./workspace.js";

describe("bundle plugin hooks", () => {
  let fixtureRoot = "";
  let caseId = 0;
  let workspaceDir = "";
  let previousBundledHooksDir: string | undefined;

  beforeAll(async () => {
    fixtureRoot = await fsp.mkdtemp(path.join(os.tmpdir(), "openclaw-plugin-hooks-"));
  });

  beforeEach(async () => {
    clearInternalHooks();
    setInternalHooksEnabled(true);
    workspaceDir = path.join(fixtureRoot, `case-${caseId++}`);
    await fsp.mkdir(workspaceDir, { recursive: true });
    previousBundledHooksDir = process.env.OPENCLAW_BUNDLED_HOOKS_DIR;
    process.env.OPENCLAW_BUNDLED_HOOKS_DIR = "/nonexistent/bundled/hooks";
  });

  afterEach(() => {
    clearInternalHooks();
    setInternalHooksEnabled(true);
    if (previousBundledHooksDir === undefined) {
      delete process.env.OPENCLAW_BUNDLED_HOOKS_DIR;
    } else {
      process.env.OPENCLAW_BUNDLED_HOOKS_DIR = previousBundledHooksDir;
    }
  });

  afterAll(async () => {
    await fsp.rm(fixtureRoot, { recursive: true, force: true });
  });

  async function writeBundleHookFixture(): Promise<string> {
    const bundleRoot = path.join(workspaceDir, ".openclaw", "extensions", "sample-bundle");
    const hookDir = path.join(bundleRoot, "hooks", "bundle-hook");
    await fsp.mkdir(path.join(bundleRoot, ".codex-plugin"), { recursive: true });
    await fsp.mkdir(hookDir, { recursive: true });
    await fsp.writeFile(
      path.join(bundleRoot, ".codex-plugin", "plugin.json"),
      JSON.stringify({
        name: "Sample Bundle",
        hooks: "hooks",
      }),
      "utf-8",
    );
    await fsp.writeFile(
      path.join(hookDir, "HOOK.md"),
      [
        "---",
        "name: bundle-hook",
        'description: "Bundle hook"',
        'metadata: {"openclaw":{"events":["command:new"]}}',
        "---",
        "",
        "# Bundle hook",
        "",
      ].join("\n"),
      "utf-8",
    );
    await fsp.writeFile(
      path.join(hookDir, "handler.js"),
      'export default async function(event) { event.messages.push("bundle-hook-ok"); }\n',
      "utf-8",
    );
    return bundleRoot;
  }

  function createConfig(enabled: boolean): OpenClawConfig {
    return {
      hooks: {
        internal: {
          enabled: true,
        },
      },
      plugins: {
        entries: {
          "sample-bundle": {
            enabled,
          },
        },
      },
    };
  }

  it("exposes enabled bundle hook dirs as plugin-managed hook entries", async () => {
    const bundleRoot = await writeBundleHookFixture();

    const entries = loadWorkspaceHookEntries(workspaceDir, {
      config: createConfig(true),
    });

    expect(entries).toHaveLength(1);
    expect(entries[0]?.hook.name).toBe("bundle-hook");
    expect(entries[0]?.hook.source).toBe("openclaw-plugin");
    expect(entries[0]?.hook.pluginId).toBe("sample-bundle");
    expect(entries[0]?.hook.baseDir).toBe(
      fs.realpathSync.native(path.join(bundleRoot, "hooks", "bundle-hook")),
    );
    expect(entries[0]?.metadata?.events).toEqual(["command:new"]);
  });

  it("loads and executes enabled bundle hooks through the internal hook loader", async () => {
    await writeBundleHookFixture();

    const count = await loadInternalHooks(createConfig(true), workspaceDir);
    expect(count).toBe(1);

    const event = createInternalHookEvent("command", "new", "test-session");
    await triggerInternalHook(event);
    expect(event.messages).toContain("bundle-hook-ok");
  });

  it("skips disabled bundle hooks", async () => {
    await writeBundleHookFixture();

    const entries = loadWorkspaceHookEntries(workspaceDir, {
      config: createConfig(false),
    });
    expect(entries).toHaveLength(0);
  });

  it("does not treat Claude hooks.json bundles as OpenClaw hook packs", async () => {
    const bundleRoot = path.join(workspaceDir, ".openclaw", "extensions", "claude-bundle");
    await fsp.mkdir(path.join(bundleRoot, ".claude-plugin"), { recursive: true });
    await fsp.mkdir(path.join(bundleRoot, "hooks"), { recursive: true });
    await fsp.writeFile(
      path.join(bundleRoot, ".claude-plugin", "plugin.json"),
      JSON.stringify({
        name: "Claude Bundle",
        hooks: [{ type: "command" }],
      }),
      "utf-8",
    );
    await fsp.writeFile(path.join(bundleRoot, "hooks", "hooks.json"), '{"hooks":[]}', "utf-8");

    const entries = loadWorkspaceHookEntries(workspaceDir, {
      config: {
        hooks: { internal: { enabled: true } },
        plugins: { entries: { "claude-bundle": { enabled: true } } },
      },
    });

    expect(entries).toHaveLength(0);
  });
});

¤ Dauer der Verarbeitung: 0.21 Sekunden  (vorverarbeitet am  2026-04-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge