Langsung ke konten utama

Documentation Index

Fetch the complete documentation index at: https://docs.openclaw.ai/llms.txt

Use this file to discover all available pages before exploring further.

Referensi untuk utilitas pengujian, pola, dan penegakan lint untuk Plugin OpenClaw.
Mencari contoh pengujian? Panduan cara melakukan menyertakan contoh pengujian yang dikerjakan: Pengujian Plugin saluran dan Pengujian Plugin penyedia.

Utilitas pengujian

Subjalur pembantu pengujian ini adalah entrypoint sumber lokal repo untuk pengujian Plugin bawaan OpenClaw sendiri. Ini bukan ekspor paket untuk Plugin pihak ketiga. Impor mock API Plugin: openclaw/plugin-sdk/plugin-test-api Impor kontrak runtime agen: openclaw/plugin-sdk/agent-runtime-test-contracts Impor kontrak saluran: openclaw/plugin-sdk/channel-contract-testing Impor pembantu pengujian saluran: openclaw/plugin-sdk/channel-test-helpers Impor pengujian target saluran: openclaw/plugin-sdk/channel-target-testing Impor kontrak Plugin: openclaw/plugin-sdk/plugin-test-contracts Impor pengujian runtime Plugin: openclaw/plugin-sdk/plugin-test-runtime Impor kontrak penyedia: openclaw/plugin-sdk/provider-test-contracts Impor mock HTTP penyedia: openclaw/plugin-sdk/provider-http-test-mocks Impor pengujian lingkungan/jaringan: openclaw/plugin-sdk/test-env Impor fixture generik: openclaw/plugin-sdk/test-fixtures Impor mock bawaan Node: openclaw/plugin-sdk/test-node-mocks Utamakan subjalur terfokus di bawah ini untuk pengujian Plugin baru. Barrel luas openclaw/plugin-sdk/testing hanya untuk kompatibilitas lama. Guardrail repo menolak impor nyata baru dari plugin-sdk/testing dan plugin-sdk/test-utils; nama-nama tersebut tetap ada hanya sebagai permukaan kompatibilitas usang untuk pengujian catatan kompatibilitas.
import {
  shouldAckReaction,
  removeAckReactionAfterReply,
} from "openclaw/plugin-sdk/channel-feedback";
import { installCommonResolveTargetErrorCases } from "openclaw/plugin-sdk/channel-target-testing";
import { AUTH_PROFILE_RUNTIME_CONTRACT } from "openclaw/plugin-sdk/agent-runtime-test-contracts";
import { createTestPluginApi } from "openclaw/plugin-sdk/plugin-test-api";
import { expectChannelInboundContextContract } from "openclaw/plugin-sdk/channel-contract-testing";
import { createStartAccountContext } from "openclaw/plugin-sdk/channel-test-helpers";
import { describePluginRegistrationContract } from "openclaw/plugin-sdk/plugin-test-contracts";
import { registerSingleProviderPlugin } from "openclaw/plugin-sdk/plugin-test-runtime";
import { describeOpenAIProviderRuntimeContract } from "openclaw/plugin-sdk/provider-test-contracts";
import { getProviderHttpMocks } from "openclaw/plugin-sdk/provider-http-test-mocks";
import { withEnv, withFetchPreconnect, withServer } from "openclaw/plugin-sdk/test-env";
import {
  bundledPluginRoot,
  createCliRuntimeCapture,
  typedCases,
} from "openclaw/plugin-sdk/test-fixtures";
import { mockNodeBuiltinModule } from "openclaw/plugin-sdk/test-node-mocks";

Ekspor yang tersedia

EksporTujuan
createTestPluginApiMembuat tiruan API Plugin minimal untuk uji unit registrasi langsung. Impor dari plugin-sdk/plugin-test-api
AUTH_PROFILE_RUNTIME_CONTRACTFixture kontrak profil auth bersama untuk adapter runtime agen native. Impor dari plugin-sdk/agent-runtime-test-contracts
DELIVERY_NO_REPLY_RUNTIME_CONTRACTFixture kontrak supresi pengiriman bersama untuk adapter runtime agen native. Impor dari plugin-sdk/agent-runtime-test-contracts
OUTCOME_FALLBACK_RUNTIME_CONTRACTFixture kontrak klasifikasi fallback bersama untuk adapter runtime agen native. Impor dari plugin-sdk/agent-runtime-test-contracts
createParameterFreeToolMembuat fixture skema alat dinamis untuk uji kontrak runtime native. Impor dari plugin-sdk/agent-runtime-test-contracts
expectChannelInboundContextContractMemastikan bentuk konteks masuk kanal. Impor dari plugin-sdk/channel-contract-testing
installChannelOutboundPayloadContractSuiteMemasang kasus kontrak payload keluar kanal. Impor dari plugin-sdk/channel-contract-testing
createStartAccountContextMembuat konteks siklus hidup akun kanal. Impor dari plugin-sdk/channel-test-helpers
installChannelActionsContractSuiteMemasang kasus kontrak aksi pesan kanal generik. Impor dari plugin-sdk/channel-test-helpers
installChannelSetupContractSuiteMemasang kasus kontrak penyiapan kanal generik. Impor dari plugin-sdk/channel-test-helpers
installChannelStatusContractSuiteMemasang kasus kontrak status kanal generik. Impor dari plugin-sdk/channel-test-helpers
expectDirectoryIdsMemastikan id direktori kanal dari fungsi daftar direktori. Impor dari plugin-sdk/channel-test-helpers
assertBundledChannelEntriesMemastikan entrypoint kanal terbundel mengekspos kontrak publik yang diharapkan. Impor dari plugin-sdk/channel-test-helpers
formatEnvelopeTimestampMemformat stempel waktu envelope deterministik. Impor dari plugin-sdk/channel-test-helpers
expectPairingReplyTextMemastikan teks balasan pairing kanal dan mengekstrak kodenya. Impor dari plugin-sdk/channel-test-helpers
describePluginRegistrationContractMemasang pemeriksaan kontrak registrasi Plugin. Impor dari plugin-sdk/plugin-test-contracts
registerSingleProviderPluginMendaftarkan satu Plugin penyedia dalam uji asap loader. Impor dari plugin-sdk/plugin-test-runtime
registerProviderPluginMenangkap semua jenis penyedia dari satu Plugin. Impor dari plugin-sdk/plugin-test-runtime
registerProviderPluginsMenangkap registrasi penyedia di beberapa Plugin. Impor dari plugin-sdk/plugin-test-runtime
requireRegisteredProviderMemastikan koleksi penyedia berisi sebuah id. Impor dari plugin-sdk/plugin-test-runtime
createRuntimeEnvMembuat lingkungan runtime CLI/Plugin tiruan. Impor dari plugin-sdk/plugin-test-runtime
createPluginSetupWizardStatusMembuat helper status penyiapan untuk Plugin kanal. Impor dari plugin-sdk/plugin-test-runtime
describeOpenAIProviderRuntimeContractMemasang pemeriksaan kontrak runtime keluarga penyedia. Impor dari plugin-sdk/provider-test-contracts
expectPassthroughReplayPolicyMemastikan kebijakan replay penyedia meneruskan alat dan metadata milik penyedia. Impor dari plugin-sdk/provider-test-contracts
runRealtimeSttLiveTestMenjalankan uji langsung penyedia STT realtime dengan fixture audio bersama. Impor dari plugin-sdk/provider-test-contracts
normalizeTranscriptForMatchMenormalkan keluaran transkrip langsung sebelum asersi fuzzy. Impor dari plugin-sdk/provider-test-contracts
expectExplicitVideoGenerationCapabilitiesMemastikan penyedia video mendeklarasikan kemampuan mode pembuatan eksplisit. Impor dari plugin-sdk/provider-test-contracts
expectExplicitMusicGenerationCapabilitiesMemastikan penyedia musik mendeklarasikan kemampuan pembuatan/pengeditan eksplisit. Impor dari plugin-sdk/provider-test-contracts
mockSuccessfulDashscopeVideoTaskMemasang respons tugas video kompatibel DashScope yang berhasil. Impor dari plugin-sdk/provider-test-contracts
getProviderHttpMocksMengakses tiruan HTTP/auth Vitest penyedia yang ikut-serta. Impor dari plugin-sdk/provider-http-test-mocks
installProviderHttpMockCleanupMereset tiruan HTTP/auth penyedia setelah setiap pengujian. Impor dari plugin-sdk/provider-http-test-mocks
installCommonResolveTargetErrorCasesKasus uji bersama untuk penanganan kesalahan resolusi target. Impor dari plugin-sdk/channel-target-testing
shouldAckReactionMemeriksa apakah kanal harus menambahkan reaksi ack. Impor dari plugin-sdk/channel-feedback
removeAckReactionAfterReplyMenghapus reaksi ack setelah pengiriman balasan. Impor dari plugin-sdk/channel-feedback
createTestRegistryMembuat fixture registry Plugin kanal. Impor dari plugin-sdk/plugin-test-runtime atau plugin-sdk/channel-test-helpers
createEmptyPluginRegistryMembuat fixture registry Plugin kosong. Impor dari plugin-sdk/plugin-test-runtime atau plugin-sdk/channel-test-helpers
setActivePluginRegistryMemasang fixture registry untuk uji runtime Plugin. Impor dari plugin-sdk/plugin-test-runtime atau plugin-sdk/channel-test-helpers
createRequestCaptureJsonFetchMenangkap permintaan fetch JSON dalam uji helper media. Impor dari plugin-sdk/test-env
withServerMenjalankan pengujian terhadap server HTTP lokal sekali pakai. Impor dari plugin-sdk/test-env
createMockIncomingRequestMembuat objek permintaan HTTP masuk minimal. Impor dari plugin-sdk/test-env
withFetchPreconnectMenjalankan uji fetch dengan hook preconnect terpasang. Impor dari plugin-sdk/test-env
withEnv / withEnvAsyncMenambal variabel lingkungan sementara. Impor dari plugin-sdk/test-env
createTempHomeEnv / withTempHome / withTempDirMembuat fixture uji sistem berkas terisolasi. Impor dari plugin-sdk/test-env
createMockServerResponseMembuat tiruan respons server HTTP minimal. Impor dari plugin-sdk/test-env
createCliRuntimeCaptureMenangkap keluaran runtime CLI dalam pengujian. Impor dari plugin-sdk/test-fixtures
importFreshModuleMengimpor modul ESM dengan token kueri baru untuk melewati cache modul. Impor dari plugin-sdk/test-fixtures
bundledPluginRoot / bundledPluginFileMenyelesaikan path fixture sumber atau dist Plugin terbundel. Impor dari plugin-sdk/test-fixtures
mockNodeBuiltinModuleMemasang tiruan Vitest bawaan Node yang sempit. Impor dari plugin-sdk/test-node-mocks
createSandboxTestContextMembuat konteks uji sandbox. Impor dari plugin-sdk/test-fixtures
writeSkillMenulis fixture skill. Impor dari plugin-sdk/test-fixtures
makeAgentAssistantMessageMembuat fixture pesan transkrip agen. Impor dari plugin-sdk/test-fixtures
peekSystemEvents / resetSystemEventsForTestMemeriksa dan mereset fixture peristiwa sistem. Impor dari plugin-sdk/test-fixtures
sanitizeTerminalTextMembersihkan keluaran terminal untuk asersi. Impor dari plugin-sdk/test-fixtures
countLines / hasBalancedFencesMemastikan bentuk keluaran chunking. Impor dari plugin-sdk/test-fixtures
runProviderCatalogMenjalankan hook katalog penyedia dengan dependensi uji
resolveProviderWizardOptionsMenyelesaikan pilihan wizard penyiapan penyedia dalam uji kontrak
resolveProviderModelPickerEntriesMenyelesaikan entri pemilih model penyedia dalam uji kontrak
buildProviderPluginMethodChoiceMembuat id pilihan wizard penyedia untuk asersi
setProviderWizardProvidersResolverForTestMenyuntikkan penyedia wizard penyedia untuk pengujian terisolasi
createProviderUsageFetchMembangun fixture fetch penggunaan penyedia
useFrozenTime / useRealTimeMembekukan dan memulihkan timer untuk pengujian yang sensitif terhadap waktu. Impor dari plugin-sdk/test-env
createTestWizardPrompterMembangun prompter wizard penyiapan tiruan
createRuntimeTaskFlowMembuat status alur tugas runtime yang terisolasi
typedCasesMempertahankan tipe literal untuk pengujian berbasis tabel. Impor dari plugin-sdk/test-fixtures
Suite kontrak plugin bawaan juga menggunakan subpath pengujian SDK untuk helper fixture registri khusus tes, manifes, artefak publik, dan runtime. Suite khusus core yang bergantung pada inventaris OpenClaw bawaan tetap berada di src/plugins/contracts. Tempatkan tes ekstensi baru pada subpath SDK terfokus yang terdokumentasi seperti plugin-sdk/plugin-test-api, plugin-sdk/channel-contract-testing, plugin-sdk/agent-runtime-test-contracts, plugin-sdk/channel-test-helpers, plugin-sdk/plugin-test-contracts, plugin-sdk/plugin-test-runtime, plugin-sdk/provider-test-contracts, plugin-sdk/provider-http-test-mocks, plugin-sdk/test-env, atau plugin-sdk/test-fixtures, alih-alih mengimpor barrel kompatibilitas plugin-sdk/testing yang luas, file repo src/**, atau bridge repo test/helpers/* secara langsung.

Tipe

Subpath pengujian terfokus juga mengekspor ulang tipe yang berguna dalam file tes:
import type {
  ChannelAccountSnapshot,
  ChannelGatewayContext,
} from "openclaw/plugin-sdk/channel-contract";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
import type { MockFn, PluginRuntime, RuntimeEnv } from "openclaw/plugin-sdk/plugin-test-runtime";

Menguji resolusi target

Gunakan installCommonResolveTargetErrorCases untuk menambahkan kasus galat standar untuk resolusi target channel:
import { describe } from "vitest";
import { installCommonResolveTargetErrorCases } from "openclaw/plugin-sdk/channel-target-testing";

describe("my-channel target resolution", () => {
  installCommonResolveTargetErrorCases({
    resolveTarget: ({ to, mode, allowFrom }) => {
      // Your channel's target resolution logic
      return myChannelResolveTarget({ to, mode, allowFrom });
    },
    implicitAllowFrom: ["user1", "user2"],
  });

  // Add channel-specific test cases
  it("should resolve @username targets", () => {
    // ...
  });
});

Pola pengujian

Menguji kontrak pendaftaran

Tes unit yang meneruskan mock api buatan tangan ke register(api) tidak menguji gerbang penerimaan loader OpenClaw. Tambahkan setidaknya satu tes smoke berbasis loader untuk setiap permukaan pendaftaran yang diandalkan plugin Anda, terutama hook dan kapabilitas eksklusif seperti memory. Loader sebenarnya menggagalkan pendaftaran plugin ketika metadata wajib hilang atau plugin memanggil API kapabilitas yang tidak dimilikinya. Misalnya, api.registerHook(...) memerlukan nama hook, dan api.registerMemoryCapability(...) mengharuskan manifes plugin atau entri yang diekspor mendeklarasikan kind: "memory".

Menguji akses konfigurasi runtime

Utamakan mock runtime plugin bersama dari openclaw/plugin-sdk/channel-test-helpers saat menguji plugin channel bawaan. Mock runtime.config.loadConfig() dan runtime.config.writeConfigFile(...) yang sudah usang melempar galat secara default agar tes menangkap penggunaan baru API kompatibilitas. Timpa mock tersebut hanya ketika tes secara eksplisit mencakup perilaku kompatibilitas lama.

Pengujian unit plugin channel

import { describe, it, expect, vi } from "vitest";

describe("my-channel plugin", () => {
  it("should resolve account from config", () => {
    const cfg = {
      channels: {
        "my-channel": {
          token: "test-token",
          allowFrom: ["user1"],
        },
      },
    };

    const account = myPlugin.setup.resolveAccount(cfg, undefined);
    expect(account.token).toBe("test-token");
  });

  it("should inspect account without materializing secrets", () => {
    const cfg = {
      channels: {
        "my-channel": { token: "test-token" },
      },
    };

    const inspection = myPlugin.setup.inspectAccount(cfg, undefined);
    expect(inspection.configured).toBe(true);
    expect(inspection.tokenStatus).toBe("available");
    // No token value exposed
    expect(inspection).not.toHaveProperty("token");
  });
});

Pengujian unit plugin provider

import { describe, it, expect } from "vitest";

describe("my-provider plugin", () => {
  it("should resolve dynamic models", () => {
    const model = myProvider.resolveDynamicModel({
      modelId: "custom-model-v2",
      // ... context
    });

    expect(model.id).toBe("custom-model-v2");
    expect(model.provider).toBe("my-provider");
    expect(model.api).toBe("openai-completions");
  });

  it("should return catalog when API key is available", async () => {
    const result = await myProvider.catalog.run({
      resolveProviderApiKey: () => ({ apiKey: "test-key" }),
      // ... context
    });

    expect(result?.provider?.models).toHaveLength(2);
  });
});

Mem-mock runtime plugin

Untuk kode yang menggunakan createPluginRuntimeStore, mock runtime dalam tes:
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
import type { PluginRuntime } from "openclaw/plugin-sdk/runtime-store";

const store = createPluginRuntimeStore<PluginRuntime>({
  pluginId: "test-plugin",
  errorMessage: "test runtime not set",
});

// In test setup
const mockRuntime = {
  agent: {
    resolveAgentDir: vi.fn().mockReturnValue("/tmp/agent"),
    // ... other mocks
  },
  config: {
    current: vi.fn(() => ({}) as const),
    mutateConfigFile: vi.fn(),
    replaceConfigFile: vi.fn(),
  },
  // ... other namespaces
} as unknown as PluginRuntime;

store.setRuntime(mockRuntime);

// After tests
store.clearRuntime();

Menguji dengan stub per instans

Utamakan stub per instans dibanding mutasi prototipe:
// Preferred: per-instance stub
const client = new MyChannelClient();
client.sendMessage = vi.fn().mockResolvedValue({ id: "msg-1" });

// Avoid: prototype mutation
// MyChannelClient.prototype.sendMessage = vi.fn();

Tes kontrak (plugin dalam repo)

Plugin bawaan memiliki tes kontrak yang memverifikasi kepemilikan pendaftaran:
pnpm test -- src/plugins/contracts/
Tes ini menegaskan:
  • Plugin mana yang mendaftarkan provider mana
  • Plugin mana yang mendaftarkan provider ucapan mana
  • Ketepatan bentuk pendaftaran
  • Kepatuhan kontrak runtime

Menjalankan tes berscope

Untuk plugin tertentu:
pnpm test -- <bundled-plugin-root>/my-channel/
Untuk tes kontrak saja:
pnpm test -- src/plugins/contracts/shape.contract.test.ts
pnpm test -- src/plugins/contracts/auth-choice.contract.test.ts
pnpm test -- src/plugins/contracts/runtime-seams.contract.test.ts

Penegakan lint (plugin dalam repo)

Tiga aturan ditegakkan oleh pnpm check untuk plugin dalam repo:
  1. Tidak ada impor root monolitik — barrel root openclaw/plugin-sdk ditolak
  2. Tidak ada impor src/ langsung — plugin tidak dapat mengimpor ../../src/ secara langsung
  3. Tidak ada impor diri sendiri — plugin tidak dapat mengimpor subpath plugin-sdk/<name> miliknya sendiri
Plugin eksternal tidak tunduk pada aturan lint ini, tetapi mengikuti pola yang sama direkomendasikan.

Konfigurasi tes

OpenClaw menggunakan Vitest dengan ambang coverage V8. Untuk tes plugin:
# Run all tests
pnpm test

# Run specific plugin tests
pnpm test -- <bundled-plugin-root>/my-channel/src/channel.test.ts

# Run with a specific test name filter
pnpm test -- <bundled-plugin-root>/my-channel/ -t "resolves account"

# Run with coverage
pnpm test:coverage
Jika eksekusi lokal menyebabkan tekanan memori:
OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test

Terkait