pi-harness-runtime 1.1.440 → 1.1.441
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/harness/e2e/auto-test-loop.ts +2 -0
- package/harness/e2e/browser-scrapers/base-browser-scraper.ts +2 -0
- package/harness/e2e/browser-scrapers/chrome-profile-manager.ts +2 -0
- package/harness/e2e/browser-scrapers/codex-browser-scraper.ts +2 -0
- package/harness/e2e/tools-detector.ts +2 -0
- package/harness/key-loader.ts +2 -0
- package/harness/langchain/checkpointer.ts +2 -0
- package/harness/langchain/cron-cli.ts +2 -0
- package/harness/langchain/graph.ts +2 -0
- package/harness/notification-center.ts +2 -0
- package/harness/secret-provider.ts +2 -0
- package/index.ts +2 -0
- package/package.json +7 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/agent-policy/dist/extension.d.ts.map +1 -1
- package/packages/agent-policy/dist/extension.js +2 -0
- package/packages/agent-policy/dist/extension.js.map +1 -1
- package/packages/agent-policy/package.json +1 -1
- package/packages/agent-policy/src/extension.ts +2 -0
- package/packages/architecture-generator/package.json +1 -1
- package/packages/auth/dist/minimax-browser-auth.d.ts.map +1 -1
- package/packages/auth/dist/minimax-browser-auth.js +23 -1
- package/packages/auth/dist/minimax-browser-auth.js.map +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/auth/src/minimax-browser-auth.ts +30 -5
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/dist/inbox.d.ts.map +1 -1
- package/packages/autonomous-runtime/dist/inbox.js +2 -0
- package/packages/autonomous-runtime/dist/inbox.js.map +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/autonomous-runtime/src/inbox.ts +2 -0
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/dist/src/clipboard.d.ts.map +1 -1
- package/packages/clipboard/dist/src/clipboard.js +2 -0
- package/packages/clipboard/dist/src/clipboard.js.map +1 -1
- package/packages/clipboard/dist/src/copy-sync.d.ts.map +1 -1
- package/packages/clipboard/dist/src/copy-sync.js +2 -0
- package/packages/clipboard/dist/src/copy-sync.js.map +1 -1
- package/packages/clipboard/dist/src/gist-relay.d.ts.map +1 -1
- package/packages/clipboard/dist/src/gist-relay.js +2 -0
- package/packages/clipboard/dist/src/gist-relay.js.map +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard/src/clipboard.ts +2 -0
- package/packages/clipboard/src/copy-sync.ts +2 -0
- package/packages/clipboard/src/gist-relay.ts +2 -0
- package/packages/clipboard-plugin/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/codex-watcher/package.json +1 -1
- package/packages/config-capture/package.json +1 -1
- package/packages/connection-runtime/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/contracts/dist/delegation-store.js +1 -4
- package/packages/contracts/dist/workspace-env.js +28 -1
- package/packages/contracts/package.json +1 -1
- package/packages/contracts/src/delegation-store.ts +9 -4
- package/packages/contracts/src/workspace-env.ts +29 -4
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/durable-review/package.json +1 -1
- package/packages/e2e-tester/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-sink/package.json +1 -1
- package/packages/event-store/dist/src/store.d.ts.map +1 -1
- package/packages/event-store/dist/src/store.js +2 -0
- package/packages/event-store/dist/src/store.js.map +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/event-store/src/store.ts +3 -0
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/file-copy-helper/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/dist/analyzer.d.ts.map +1 -1
- package/packages/generic-web-plugin/dist/analyzer.js +2 -0
- package/packages/generic-web-plugin/dist/analyzer.js.map +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/generic-web-plugin/src/analyzer.ts +3 -0
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/jev-judge/package.json +1 -1
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/dist/mcp-client.d.ts.map +1 -1
- package/packages/knowledge-retrieval/dist/mcp-client.js +0 -1
- package/packages/knowledge-retrieval/dist/mcp-client.js.map +1 -1
- package/packages/knowledge-retrieval/package.json +1 -4
- package/packages/knowledge-retrieval/src/mcp-client.ts +0 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/logging/package.json +1 -1
- package/packages/mcp-adapter/dist/server.d.ts.map +1 -1
- package/packages/mcp-adapter/dist/server.js +2 -0
- package/packages/mcp-adapter/dist/server.js.map +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/mcp-adapter/src/server.ts +3 -0
- package/packages/memory-engine/package.json +1 -1
- package/packages/milestone-manager/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/okf-indexer/package.json +1 -1
- package/packages/paperclip-integration/dist/index.d.ts.map +1 -1
- package/packages/paperclip-integration/dist/index.js +2 -0
- package/packages/paperclip-integration/dist/index.js.map +1 -1
- package/packages/paperclip-integration/package.json +1 -1
- package/packages/paperclip-integration/src/index.ts +2 -0
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/permission-mode/package.json +1 -1
- package/packages/privilege-broker/dist/audit.d.ts.map +1 -1
- package/packages/privilege-broker/dist/audit.js +2 -0
- package/packages/privilege-broker/dist/audit.js.map +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/privilege-broker/src/audit.ts +2 -0
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-bootstrap/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/dist/compiler.d.ts.map +1 -1
- package/packages/prompt-compiler/dist/compiler.js +2 -0
- package/packages/prompt-compiler/dist/compiler.js.map +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-compiler/src/compiler.ts +2 -0
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/qdrant-skills/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/relay/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-mcp-client/dist/client.d.ts.map +1 -1
- package/packages/skill-mcp-client/dist/client.js +0 -1
- package/packages/skill-mcp-client/dist/client.js.map +1 -1
- package/packages/skill-mcp-client/package.json +1 -4
- package/packages/skill-mcp-client/src/client.ts +0 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/skills/dist/parser.d.ts.map +1 -1
- package/packages/skills/dist/parser.js +2 -0
- package/packages/skills/dist/parser.js.map +1 -1
- package/packages/skills/dist/skill-versioning.d.ts.map +1 -1
- package/packages/skills/dist/skill-versioning.js +2 -0
- package/packages/skills/dist/skill-versioning.js.map +1 -1
- package/packages/skills/package.json +1 -1
- package/packages/skills/src/parser.ts +3 -0
- package/packages/skills/src/skill-versioning.ts +2 -0
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/tooling-preference/package.json +1 -1
- package/packages/trajectory/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/two-phase-review/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/voice-api/package.json +1 -1
- package/packages/webmcp-tester/dist/index.js +0 -2
- package/packages/webmcp-tester/package.json +1 -1
- package/packages/webmcp-tester/src/index.ts +0 -3
- package/packages/wiki/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/dist/trigger.d.ts.map +1 -1
- package/packages/write-review/dist/trigger.js +1 -2
- package/packages/write-review/dist/trigger.js.map +1 -1
- package/packages/write-review/package.json +1 -1
- package/packages/write-review/src/trigger.ts +1 -2
- package/scripts/lib/runtime-imports.ts +189 -3
- package/scripts/telegram-webhook-server.ts +2 -0
- package/scripts/verify-package-contents.ts +148 -1
- package/harness/e2e/tools-detector.test.ts +0 -155
- package/harness/glm-quota-countdown.test.ts +0 -323
- package/harness/langchain/agents.test.ts +0 -39
- package/harness/langchain/checkpointer.test.ts +0 -243
- package/harness/langchain/daemon.test.ts +0 -459
- package/harness/langchain/model-router.test.ts +0 -191
- package/harness/langchain/ping-pong-middleware.test.ts +0 -69
- package/harness/langchain/scoreboard.test.ts +0 -267
- package/harness/langchain/status-line.test.ts +0 -106
- package/harness/langchain/surge.test.ts +0 -467
- package/harness/langchain/widget.test.ts +0 -251
- package/harness/skill-sync.test.ts +0 -57
- package/harness/ssh-detach-interceptor.test.ts +0 -263
- package/harness/ssh-hang-recovery.test.ts +0 -86
- package/packages/a2a-adapter/test/a2a.test.ts +0 -151
- package/packages/agent-policy/test/interlock.test.ts +0 -101
- package/packages/agent-policy/test/policy-retention.test.ts +0 -380
- package/packages/agent-policy/test/policy.test.ts +0 -387
- package/packages/auth/test/auth.test.ts +0 -238
- package/packages/autonomous-refactor/test/refactor.test.ts +0 -202
- package/packages/autonomous-runtime/test/types.test.ts +0 -95
- package/packages/cache-strategy/test/cache.test.ts +0 -137
- package/packages/capability-registry/test/registry.test.ts +0 -204
- package/packages/checkpoint/test/engine.test.ts +0 -265
- package/packages/cli-plugin-sdk/test/cli.test.ts +0 -45
- package/packages/code-generation/test/generator.test.ts +0 -238
- package/packages/code-review/test/engine.test.ts +0 -302
- package/packages/codex-adapter/test/provider.test.ts +0 -142
- package/packages/codex-watcher/test/watch.test.ts +0 -453
- package/packages/context-compiler/test/context-compiler.test.ts +0 -746
- package/packages/context-manager/test/context.test.ts +0 -198
- package/packages/contracts/test/delegation.test.ts +0 -350
- package/packages/contracts/test/workspace-env.test.ts +0 -802
- package/packages/cookie-sanitizer/test/infer.test.ts +0 -110
- package/packages/cookie-sanitizer/test/normalize.test.ts +0 -113
- package/packages/cookie-sanitizer/test/parse.test.ts +0 -204
- package/packages/cookie-sanitizer/test/sync.test.ts +0 -237
- package/packages/cookie-sanitizer/test/watcher.test.ts +0 -27
- package/packages/cost-optimizer/test/cost-optimizer.test.ts +0 -438
- package/packages/dependency-analyzer/test/analyzer.test.ts +0 -49
- package/packages/django-plugin/test/analyzer.test.ts +0 -195
- package/packages/doc-generator/test/docs.test.ts +0 -168
- package/packages/durable-review/test/acceptance.test.ts +0 -357
- package/packages/durable-review/test/smoke.test.ts +0 -107
- package/packages/evaluation-engine/test/engine.test.ts +0 -277
- package/packages/evaluation-runner/test/runner.test.ts +0 -168
- package/packages/event-bus/test/bus.test.ts +0 -100
- package/packages/event-store/test/store.test.ts +0 -115
- package/packages/experience-replay/test/replay.test.ts +0 -267
- package/packages/feedback-collector/test/collector.test.ts +0 -142
- package/packages/framework-detector/test/detector.test.ts +0 -75
- package/packages/framework-plugin-sdk/test/manager.test.ts +0 -320
- package/packages/frappe-plugin/test/analyzer.test.ts +0 -250
- package/packages/generic-web-plugin/test/analyzer.test.ts +0 -134
- package/packages/health-monitor/test/health.test.ts +0 -231
- package/packages/intent-analyzer/test/analyzer.test.ts +0 -72
- package/packages/intent-analyzer/test/ping-pong.test.ts +0 -96
- package/packages/jev-judge/tests/auto-continue-context.test.ts +0 -280
- package/packages/jev-judge/tests/continuation-controller.test.ts +0 -1396
- package/packages/jev-judge/tests/jev-provider-chain.test.ts +0 -536
- package/packages/jev-judge/tests/outcome-application.test.ts +0 -132
- package/packages/jev-judge/tests/question-risk.test.ts +0 -129
- package/packages/jev-judge/tests/typesafe-provider.test.ts +0 -640
- package/packages/jev-judge/tests/validation-ledger.test.ts +0 -181
- package/packages/jev-judge/tests/validation-plan.test.ts +0 -170
- package/packages/jev-judge/tests/validation-tie-breaker.test.ts +0 -88
- package/packages/laravel-plugin/test/analyzer.test.ts +0 -220
- package/packages/learning-engine/test/engine.test.ts +0 -331
- package/packages/logging/test/buffer.test.ts +0 -44
- package/packages/logging/test/classification.test.ts +0 -137
- package/packages/logging/test/config.test.ts +0 -97
- package/packages/logging/test/fanout.test.ts +0 -186
- package/packages/logging/test/identity-transport.test.ts +0 -197
- package/packages/logging/test/incidents.test.ts +0 -404
- package/packages/logging/test/ingest-schema.test.ts +0 -184
- package/packages/logging/test/integration.test.ts +0 -140
- package/packages/logging/test/log-http.test.ts +0 -246
- package/packages/logging/test/redact.test.ts +0 -109
- package/packages/logging/test/sampler.test.ts +0 -57
- package/packages/logging/test/server.test.ts +0 -444
- package/packages/logging/test/shipper.test.ts +0 -152
- package/packages/logging/test/spool.test.ts +0 -96
- package/packages/mcp-adapter/test/server.test.ts +0 -91
- package/packages/memory-engine/test/engine.test.ts +0 -456
- package/packages/model-registry/test/registry.test.ts +0 -342
- package/packages/nextjs-plugin/test/analyzer.test.ts +0 -149
- package/packages/notification/test/approval-payload.test.ts +0 -269
- package/packages/notification/test/detail-format.test.ts +0 -106
- package/packages/notification/test/notification.test.ts +0 -375
- package/packages/notification/test/pending-question-lifecycle.test.ts +0 -195
- package/packages/notification/test/pending-question.test.ts +0 -331
- package/packages/notification/test/tooling-proposal-payload.test.ts +0 -212
- package/packages/observability/test/observability.test.ts +0 -1350
- package/packages/performance-optimizer/test/optimizer.test.ts +0 -267
- package/packages/project-analyzer/test/index.test.ts +0 -1719
- package/packages/prompt-compiler/test/prompt-compiler.test.ts +0 -813
- package/packages/prompt-versioning/test/versioning.test.ts +0 -112
- package/packages/provider-adapter-sdk/test/sdk.test.ts +0 -220
- package/packages/provider-router/test/provider-router.test.ts +0 -405
- package/packages/provider-selector/test/selector.test.ts +0 -192
- package/packages/providers/test/providers.test.ts +0 -225
- package/packages/qdrant-skills/test/collection-info.test.ts +0 -165
- package/packages/qdrant-skills/test/embedder-batch.test.ts +0 -184
- package/packages/qdrant-skills/test/embedder.test.ts +0 -97
- package/packages/quota-manager/test/quota.test.ts +0 -432
- package/packages/rate-limiter/test/limiter.test.ts +0 -128
- package/packages/react-vite-plugin/test/analyzer.test.ts +0 -139
- package/packages/relay/test/client.test.ts +0 -446
- package/packages/relay/test/relay-e2e.test.ts +0 -299
- package/packages/relay/test/relay-endpoint.test.ts +0 -278
- package/packages/release-manager/test/release.test.ts +0 -215
- package/packages/requirement-compiler/test/requirement-compiler.test.ts +0 -743
- package/packages/runtime/test/runtime-api.test.ts +0 -169
- package/packages/runtime/test/runtime.test.ts +0 -297
- package/packages/scheduler/test/scheduler.test.ts +0 -125
- package/packages/session/test/manager.test.ts +0 -233
- package/packages/shared-context/test/shared-context.test.ts +0 -114
- package/packages/skill-registry/test/registry.test.ts +0 -508
- package/packages/skills/test/init-skills.test.ts +0 -114
- package/packages/skills/test/remote-skills.test.ts +0 -360
- package/packages/skills/test/remote-source.test.ts +0 -248
- package/packages/skills/test/sanitize.test.ts +0 -250
- package/packages/skills/test/vector-indexing.test.ts +0 -205
- package/packages/skills/test/vector-schema.test.ts +0 -180
- package/packages/skills/test/vector-threshold.test.ts +0 -108
- package/packages/sprint-planner/test/planner.test.ts +0 -187
- package/packages/task-compiler/test/task-compiler.test.ts +0 -628
- package/packages/test-data-generator/test/generator.test.ts +0 -265
- package/packages/test-generator/test/generator.test.ts +0 -156
- package/packages/token-estimation/test/token-estimation.test.ts +0 -207
- package/packages/token-optimizer/test/optimizer.test.ts +0 -141
- package/packages/tooling-preference/tests/changed-files.test.ts +0 -124
- package/packages/tooling-preference/tests/detect.test.ts +0 -188
- package/packages/tooling-preference/tests/proposal.test.ts +0 -107
- package/packages/tooling-preference/tests/quality-check.test.ts +0 -272
- package/packages/tooling-preference/tests/registry.test.ts +0 -51
- package/packages/tooling-preference/tests/store.test.ts +0 -99
- package/packages/trajectory/test/store.test.ts +0 -250
- package/packages/tui/test/harness-footer.test.ts +0 -559
- package/packages/tui/test/harness-header.test.ts +0 -590
- package/packages/two-phase-review/test/classify.test.ts +0 -102
- package/packages/two-phase-review/test/helpers.ts +0 -72
- package/packages/two-phase-review/test/rules.test.ts +0 -150
- package/packages/two-phase-review/test/runtime.test.ts +0 -362
- package/packages/two-phase-review/test/scope.test.ts +0 -186
- package/packages/two-phase-review/test/signals.test.ts +0 -183
- package/packages/two-phase-review/test/state.test.ts +0 -201
- package/packages/wiki/test/basic.test.ts +0 -242
- package/packages/workspace-scanner/test/scanner.test.ts +0 -43
- package/packages/worktree/test/worktree.test.ts +0 -163
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Framework Plugin SDK - Tests
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { describe, it, expect, beforeEach } from "bun:test";
|
|
6
|
-
import {
|
|
7
|
-
createPluginManager,
|
|
8
|
-
SDK_VERSION,
|
|
9
|
-
PluginError,
|
|
10
|
-
PluginErrorCode,
|
|
11
|
-
} from "../src/index.js";
|
|
12
|
-
|
|
13
|
-
describe("FrameworkPluginSDK", () => {
|
|
14
|
-
describe("SDK_VERSION", () => {
|
|
15
|
-
it("should export SDK_VERSION", () => {
|
|
16
|
-
expect(SDK_VERSION).toBeDefined();
|
|
17
|
-
expect(typeof SDK_VERSION).toBe("string");
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
describe("PluginError", () => {
|
|
22
|
-
it("should create plugin error", () => {
|
|
23
|
-
const error = new PluginError(
|
|
24
|
-
"Test error",
|
|
25
|
-
PluginErrorCode.MANIFEST_INVALID,
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
expect(error).toBeInstanceOf(Error);
|
|
29
|
-
expect(error.message).toBe("Test error");
|
|
30
|
-
expect(error.code).toBe("MANIFEST_INVALID");
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("should include plugin ID", () => {
|
|
34
|
-
const error = new PluginError(
|
|
35
|
-
"Plugin error",
|
|
36
|
-
PluginErrorCode.NOT_FOUND,
|
|
37
|
-
"my-plugin",
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
expect(error.pluginId).toBe("my-plugin");
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
describe("createPluginManager", () => {
|
|
45
|
-
it("should create a plugin manager instance", () => {
|
|
46
|
-
const manager = createPluginManager();
|
|
47
|
-
expect(manager).toBeDefined();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("should create with custom config", () => {
|
|
51
|
-
const manager = createPluginManager({
|
|
52
|
-
pluginDir: "/tmp/plugins",
|
|
53
|
-
autoActivate: true,
|
|
54
|
-
logLevel: "debug",
|
|
55
|
-
});
|
|
56
|
-
expect(manager).toBeDefined();
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
describe("plugin lifecycle", () => {
|
|
61
|
-
const manager = createPluginManager();
|
|
62
|
-
|
|
63
|
-
it("should register a plugin", async () => {
|
|
64
|
-
const manifest = {
|
|
65
|
-
id: "test-plugin",
|
|
66
|
-
name: "Test Plugin",
|
|
67
|
-
version: "1.0.0",
|
|
68
|
-
description: "A test plugin",
|
|
69
|
-
capabilities: ["provider"],
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const plugin = await manager.register(manifest);
|
|
73
|
-
|
|
74
|
-
expect(plugin).toBeDefined();
|
|
75
|
-
expect(plugin.id).toBe("test-plugin");
|
|
76
|
-
expect(plugin.status).toBe("registered");
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it("should throw on duplicate registration", async () => {
|
|
80
|
-
const manifest = {
|
|
81
|
-
id: "duplicate-plugin",
|
|
82
|
-
name: "Duplicate Plugin",
|
|
83
|
-
version: "1.0.0",
|
|
84
|
-
description: "Duplicate test",
|
|
85
|
-
capabilities: ["provider"],
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
await manager.register(manifest);
|
|
89
|
-
|
|
90
|
-
await expect(manager.register(manifest)).rejects.toThrow();
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it("should load a registered plugin", async () => {
|
|
94
|
-
const manifest = {
|
|
95
|
-
id: "loadable-plugin",
|
|
96
|
-
name: "Loadable Plugin",
|
|
97
|
-
version: "1.0.0",
|
|
98
|
-
description: "A loadable plugin",
|
|
99
|
-
capabilities: ["framework"],
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
await manager.register(manifest);
|
|
103
|
-
const plugin = await manager.load({ plugin: "loadable-plugin" });
|
|
104
|
-
|
|
105
|
-
expect(plugin.status).toBe("loaded");
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it("should activate a plugin", async () => {
|
|
109
|
-
const manifest = {
|
|
110
|
-
id: "activatable-plugin",
|
|
111
|
-
name: "Activatable Plugin",
|
|
112
|
-
version: "1.0.0",
|
|
113
|
-
description: "An activatable plugin",
|
|
114
|
-
capabilities: ["tool"],
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
await manager.register(manifest);
|
|
118
|
-
await manager.load({ plugin: "activatable-plugin" });
|
|
119
|
-
await manager.initialize("activatable-plugin");
|
|
120
|
-
await manager.activate("activatable-plugin");
|
|
121
|
-
|
|
122
|
-
const plugin = manager.getPlugin("activatable-plugin");
|
|
123
|
-
expect(plugin?.status).toBe("active");
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it("should deactivate a plugin", async () => {
|
|
127
|
-
await manager.deactivate("activatable-plugin");
|
|
128
|
-
|
|
129
|
-
const plugin = manager.getPlugin("activatable-plugin");
|
|
130
|
-
expect(plugin?.status).toBe("inactive");
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it("should unload a plugin", async () => {
|
|
134
|
-
await manager.unload("activatable-plugin");
|
|
135
|
-
|
|
136
|
-
const plugin = manager.getPlugin("activatable-plugin");
|
|
137
|
-
expect(plugin).toBeUndefined();
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it("should list all plugins", async () => {
|
|
141
|
-
await manager.register({
|
|
142
|
-
id: "list-plugin-1",
|
|
143
|
-
name: "List Plugin 1",
|
|
144
|
-
version: "1.0.0",
|
|
145
|
-
description: "Test",
|
|
146
|
-
capabilities: ["provider"],
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
await manager.register({
|
|
150
|
-
id: "list-plugin-2",
|
|
151
|
-
name: "List Plugin 2",
|
|
152
|
-
version: "1.0.0",
|
|
153
|
-
description: "Test",
|
|
154
|
-
capabilities: ["framework"],
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
const plugins = manager.listPlugins();
|
|
158
|
-
expect(plugins.length).toBeGreaterThanOrEqual(2);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it("should list plugins by status", async () => {
|
|
162
|
-
const byStatus = manager.listByStatus("registered");
|
|
163
|
-
expect(Array.isArray(byStatus)).toBe(true);
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
describe("hooks", () => {
|
|
168
|
-
const manager = createPluginManager();
|
|
169
|
-
|
|
170
|
-
it("should register hook handlers", () => {
|
|
171
|
-
manager.registerHook({
|
|
172
|
-
id: "test-hook",
|
|
173
|
-
name: "onTaskComplete",
|
|
174
|
-
pluginId: "test-plugin",
|
|
175
|
-
priority: 10,
|
|
176
|
-
handler: async (ctx) => ({ handled: true }),
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// Hook registered successfully
|
|
180
|
-
expect(true).toBe(true);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it("should execute hooks", async () => {
|
|
184
|
-
const result = await manager.executeHooks("onTaskComplete", {
|
|
185
|
-
taskId: "123",
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
expect(result.hook).toBe("onTaskComplete");
|
|
189
|
-
expect(Array.isArray(result.results)).toBe(true);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it("should unregister hook handlers", () => {
|
|
193
|
-
const unregistered = manager.unregisterHook("test-hook");
|
|
194
|
-
expect(typeof unregistered).toBe("boolean");
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
describe("capabilities", () => {
|
|
199
|
-
it("should get capabilities by type", async () => {
|
|
200
|
-
const manager = createPluginManager();
|
|
201
|
-
await manager.register({
|
|
202
|
-
id: "capability-plugin-1",
|
|
203
|
-
name: "Capability Plugin 1",
|
|
204
|
-
version: "1.0.0",
|
|
205
|
-
description: "Capability test",
|
|
206
|
-
capabilities: ["provider"],
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
const providers = manager.getCapabilities("provider");
|
|
210
|
-
expect(Array.isArray(providers)).toBe(true);
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
it("should get capability instance", async () => {
|
|
214
|
-
const manager = createPluginManager();
|
|
215
|
-
await manager.register({
|
|
216
|
-
id: "capability-plugin-2",
|
|
217
|
-
name: "Capability Plugin 2",
|
|
218
|
-
version: "1.0.0",
|
|
219
|
-
description: "Capability test",
|
|
220
|
-
capabilities: ["provider"],
|
|
221
|
-
});
|
|
222
|
-
await manager.load({ plugin: "capability-plugin-2" });
|
|
223
|
-
await manager.initialize("capability-plugin-2");
|
|
224
|
-
await manager.activate("capability-plugin-2");
|
|
225
|
-
await manager.registerCapability("capability-plugin-2", "provider", {
|
|
226
|
-
complete: async () => ({ content: "test" }),
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
const capability = manager.getCapability(
|
|
230
|
-
"capability-plugin-2",
|
|
231
|
-
"provider",
|
|
232
|
-
);
|
|
233
|
-
expect(capability).toBeDefined();
|
|
234
|
-
});
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
describe("lifecycle events", () => {
|
|
238
|
-
const manager = createPluginManager();
|
|
239
|
-
|
|
240
|
-
it("should listen to lifecycle events", async () => {
|
|
241
|
-
let eventReceived = false;
|
|
242
|
-
|
|
243
|
-
manager.onLifecycle("afterActivate", () => {
|
|
244
|
-
eventReceived = true;
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
await manager.register({
|
|
248
|
-
id: "event-plugin",
|
|
249
|
-
name: "Event Plugin",
|
|
250
|
-
version: "1.0.0",
|
|
251
|
-
description: "Event test",
|
|
252
|
-
capabilities: ["hook"],
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
await manager.load({ plugin: "event-plugin" });
|
|
256
|
-
await manager.initialize("event-plugin");
|
|
257
|
-
await manager.activate("event-plugin");
|
|
258
|
-
|
|
259
|
-
// Event listener was registered
|
|
260
|
-
expect(true).toBe(true);
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
it("should remove lifecycle listeners", () => {
|
|
264
|
-
const listener = () => {};
|
|
265
|
-
|
|
266
|
-
manager.onLifecycle("beforeLoad", listener);
|
|
267
|
-
manager.offLifecycle("beforeLoad", listener);
|
|
268
|
-
|
|
269
|
-
// Listener removed
|
|
270
|
-
expect(true).toBe(true);
|
|
271
|
-
});
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
describe("manifest validation", () => {
|
|
275
|
-
const manager = createPluginManager();
|
|
276
|
-
|
|
277
|
-
it("should validate manifest has id", async () => {
|
|
278
|
-
try {
|
|
279
|
-
await manager.register({
|
|
280
|
-
name: "Missing ID",
|
|
281
|
-
version: "1.0.0",
|
|
282
|
-
description: "Test",
|
|
283
|
-
capabilities: ["provider"],
|
|
284
|
-
} as any);
|
|
285
|
-
expect(false).toBe(true); // Should not reach here
|
|
286
|
-
} catch (error) {
|
|
287
|
-
expect(error).toBeInstanceOf(PluginError);
|
|
288
|
-
}
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
it("should validate manifest has name", async () => {
|
|
292
|
-
try {
|
|
293
|
-
await manager.register({
|
|
294
|
-
id: "no-name",
|
|
295
|
-
version: "1.0.0",
|
|
296
|
-
description: "Test",
|
|
297
|
-
capabilities: ["provider"],
|
|
298
|
-
} as any);
|
|
299
|
-
expect(false).toBe(true);
|
|
300
|
-
} catch (error) {
|
|
301
|
-
expect(error).toBeInstanceOf(PluginError);
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
it("should validate capabilities", async () => {
|
|
306
|
-
try {
|
|
307
|
-
await manager.register({
|
|
308
|
-
id: "no-caps",
|
|
309
|
-
name: "No Capabilities",
|
|
310
|
-
version: "1.0.0",
|
|
311
|
-
description: "Test",
|
|
312
|
-
capabilities: [],
|
|
313
|
-
});
|
|
314
|
-
expect(false).toBe(true);
|
|
315
|
-
} catch (error) {
|
|
316
|
-
expect(error).toBeInstanceOf(PluginError);
|
|
317
|
-
}
|
|
318
|
-
});
|
|
319
|
-
});
|
|
320
|
-
});
|
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Frappe Plugin Tests (RFC-0061)
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { describe, it, expect, beforeEach, afterEach } from "bun:test";
|
|
6
|
-
import * as fs from "node:fs/promises";
|
|
7
|
-
import * as path from "node:path";
|
|
8
|
-
import * as os from "node:os";
|
|
9
|
-
import { analyzeFrappe } from "../src/analyzer.js";
|
|
10
|
-
|
|
11
|
-
const tempRoots: string[] = [];
|
|
12
|
-
|
|
13
|
-
async function mkdtemp(): Promise<string> {
|
|
14
|
-
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "frappe-plugin-"));
|
|
15
|
-
tempRoots.push(dir);
|
|
16
|
-
return dir;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
afterEach(async () => {
|
|
20
|
-
for (const dir of tempRoots) {
|
|
21
|
-
try {
|
|
22
|
-
await fs.rm(dir, { recursive: true, force: true });
|
|
23
|
-
} catch {
|
|
24
|
-
// ignore
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
tempRoots.length = 0;
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
describe("analyzeFrappe", () => {
|
|
31
|
-
it("returns null for non-frappe workspace", async () => {
|
|
32
|
-
const dir = await mkdtemp();
|
|
33
|
-
await fs.writeFile(path.join(dir, "package.json"), "{}", "utf-8");
|
|
34
|
-
const result = await analyzeFrappe(dir);
|
|
35
|
-
expect(result).toBeNull();
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it("detects frappe workspace via sites directory", async () => {
|
|
39
|
-
const dir = await mkdtemp();
|
|
40
|
-
await fs.mkdir(path.join(dir, "sites"), { recursive: true });
|
|
41
|
-
const result = await analyzeFrappe(dir);
|
|
42
|
-
expect(result).not.toBeNull();
|
|
43
|
-
expect(["frappe", "erpnext"]).toContain(result!.framework.id);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it("detects frappe workspace via apps.txt", async () => {
|
|
47
|
-
const dir = await mkdtemp();
|
|
48
|
-
await fs.writeFile(
|
|
49
|
-
path.join(dir, "apps.txt"),
|
|
50
|
-
"frappe\nerpnext\n",
|
|
51
|
-
"utf-8",
|
|
52
|
-
);
|
|
53
|
-
const result = await analyzeFrappe(dir);
|
|
54
|
-
expect(result).not.toBeNull();
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it("parses apps from apps.txt", async () => {
|
|
58
|
-
const dir = await mkdtemp();
|
|
59
|
-
await fs.mkdir(path.join(dir, "apps"), { recursive: true });
|
|
60
|
-
await fs.writeFile(
|
|
61
|
-
path.join(dir, "apps.txt"),
|
|
62
|
-
"frappe\nerpnext\nmy_custom_app\n",
|
|
63
|
-
"utf-8",
|
|
64
|
-
);
|
|
65
|
-
await fs.mkdir(path.join(dir, "apps", "frappe"), { recursive: true });
|
|
66
|
-
await fs.mkdir(path.join(dir, "apps", "erpnext"), { recursive: true });
|
|
67
|
-
await fs.mkdir(path.join(dir, "apps", "my_custom_app"), {
|
|
68
|
-
recursive: true,
|
|
69
|
-
});
|
|
70
|
-
const result = await analyzeFrappe(dir);
|
|
71
|
-
expect(result).not.toBeNull();
|
|
72
|
-
const appNames = result!.apps.map((a) => a.name);
|
|
73
|
-
expect(appNames).toContain("frappe");
|
|
74
|
-
expect(appNames).toContain("erpnext");
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it("parses hooks.py to extract app_name and __version__", async () => {
|
|
78
|
-
const dir = await mkdtemp();
|
|
79
|
-
await fs.mkdir(path.join(dir, "apps", "myapp", "myapp"), {
|
|
80
|
-
recursive: true,
|
|
81
|
-
});
|
|
82
|
-
await fs.writeFile(path.join(dir, "apps.txt"), "myapp\n", "utf-8");
|
|
83
|
-
await fs.writeFile(
|
|
84
|
-
path.join(dir, "apps", "myapp", "myapp", "hooks.py"),
|
|
85
|
-
`
|
|
86
|
-
app_name = "myapp"
|
|
87
|
-
app_title = "My App"
|
|
88
|
-
app_publisher = "Test"
|
|
89
|
-
__version__ = "1.2.3"
|
|
90
|
-
docevents = {
|
|
91
|
-
"DocType": ["validate", "on_update"],
|
|
92
|
-
}
|
|
93
|
-
`.trim(),
|
|
94
|
-
"utf-8",
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
const result = await analyzeFrappe(dir);
|
|
98
|
-
expect(result).not.toBeNull();
|
|
99
|
-
const myAppHooks = result!.hooks.find((h) => h.appName === "myapp");
|
|
100
|
-
expect(myAppHooks).toBeDefined();
|
|
101
|
-
expect(myAppHooks!.hooks["app_name"]).toContain("myapp");
|
|
102
|
-
expect(myAppHooks!.hooks["docevents"]).toBeDefined();
|
|
103
|
-
|
|
104
|
-
const myApp = result!.apps.find((a) => a.name === "myapp");
|
|
105
|
-
expect(myApp?.version).toBe("1.2.3");
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it("detects ERPNext from package.json dependencies", async () => {
|
|
109
|
-
const dir = await mkdtemp();
|
|
110
|
-
await fs.mkdir(path.join(dir, "apps", "erpnext", "erpnext"), {
|
|
111
|
-
recursive: true,
|
|
112
|
-
});
|
|
113
|
-
await fs.mkdir(path.join(dir, "apps", "frappe", "frappe"), {
|
|
114
|
-
recursive: true,
|
|
115
|
-
});
|
|
116
|
-
await fs.writeFile(
|
|
117
|
-
path.join(dir, "apps.txt"),
|
|
118
|
-
"frappe\nerpnext\n",
|
|
119
|
-
"utf-8",
|
|
120
|
-
);
|
|
121
|
-
await fs.writeFile(
|
|
122
|
-
path.join(dir, "apps", "erpnext", "package.json"),
|
|
123
|
-
JSON.stringify({
|
|
124
|
-
name: "erpnext",
|
|
125
|
-
version: "14.0.0",
|
|
126
|
-
dependencies: { frappe: "^14.0.0", erpnext: "^14.0.0" },
|
|
127
|
-
}),
|
|
128
|
-
"utf-8",
|
|
129
|
-
);
|
|
130
|
-
await fs.writeFile(
|
|
131
|
-
path.join(dir, "apps", "erpnext", "erpnext", "hooks.py"),
|
|
132
|
-
"app_name = 'erpnext'\n",
|
|
133
|
-
"utf-8",
|
|
134
|
-
);
|
|
135
|
-
await fs.writeFile(
|
|
136
|
-
path.join(dir, "apps", "frappe", "frappe", "hooks.py"),
|
|
137
|
-
"app_name = 'frappe'\n",
|
|
138
|
-
"utf-8",
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
const result = await analyzeFrappe(dir);
|
|
142
|
-
expect(result!.isErpNext).toBe(true);
|
|
143
|
-
expect(result!.framework.id).toBe("erpnext");
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it("scans sites directory", async () => {
|
|
147
|
-
const dir = await mkdtemp();
|
|
148
|
-
await fs.mkdir(path.join(dir, "sites", "site1.local"), { recursive: true });
|
|
149
|
-
await fs.mkdir(path.join(dir, "sites", "site2.local"), { recursive: true });
|
|
150
|
-
await fs.writeFile(
|
|
151
|
-
path.join(dir, "sites", "site1.local", "site_config.json"),
|
|
152
|
-
JSON.stringify({ db_port: 3306 }),
|
|
153
|
-
"utf-8",
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
const result = await analyzeFrappe(dir);
|
|
157
|
-
expect(result!.sites.length).toBe(2);
|
|
158
|
-
const site1 = result!.sites.find((s) => s.name === "site1.local");
|
|
159
|
-
expect(site1!.dbPort).toBe(3306);
|
|
160
|
-
expect(site1!.hasSiteConfig).toBe(true);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it("counts DocTypes in app module directory", async () => {
|
|
164
|
-
const dir = await mkdtemp();
|
|
165
|
-
await fs.mkdir(
|
|
166
|
-
path.join(dir, "apps", "myapp", "myapp", "doctype", "customer"),
|
|
167
|
-
{ recursive: true },
|
|
168
|
-
);
|
|
169
|
-
await fs.mkdir(
|
|
170
|
-
path.join(dir, "apps", "myapp", "myapp", "doctype", "order"),
|
|
171
|
-
{ recursive: true },
|
|
172
|
-
);
|
|
173
|
-
await fs.mkdir(
|
|
174
|
-
path.join(dir, "apps", "myapp", "myapp", "doctype", "custom_so"),
|
|
175
|
-
{ recursive: true },
|
|
176
|
-
);
|
|
177
|
-
await fs.writeFile(path.join(dir, "apps.txt"), "myapp\n", "utf-8");
|
|
178
|
-
await fs.writeFile(
|
|
179
|
-
path.join(dir, "apps", "myapp", "myapp", "hooks.py"),
|
|
180
|
-
"app_name = 'myapp'\n",
|
|
181
|
-
"utf-8",
|
|
182
|
-
);
|
|
183
|
-
await fs.writeFile(
|
|
184
|
-
path.join(
|
|
185
|
-
dir,
|
|
186
|
-
"apps",
|
|
187
|
-
"myapp",
|
|
188
|
-
"myapp",
|
|
189
|
-
"doctype",
|
|
190
|
-
"customer",
|
|
191
|
-
"customer.json",
|
|
192
|
-
),
|
|
193
|
-
JSON.stringify({
|
|
194
|
-
doctype: "DocType",
|
|
195
|
-
name: "Customer",
|
|
196
|
-
fields: [{ fieldname: "customer_name" }, { fieldname: "email" }],
|
|
197
|
-
}),
|
|
198
|
-
"utf-8",
|
|
199
|
-
);
|
|
200
|
-
await fs.writeFile(
|
|
201
|
-
path.join(
|
|
202
|
-
dir,
|
|
203
|
-
"apps",
|
|
204
|
-
"myapp",
|
|
205
|
-
"myapp",
|
|
206
|
-
"doctype",
|
|
207
|
-
"order",
|
|
208
|
-
"order.json",
|
|
209
|
-
),
|
|
210
|
-
JSON.stringify({
|
|
211
|
-
doctype: "DocType",
|
|
212
|
-
name: "Sales Order",
|
|
213
|
-
is_submittable: 1,
|
|
214
|
-
fields: Array(5).fill({}),
|
|
215
|
-
}),
|
|
216
|
-
"utf-8",
|
|
217
|
-
);
|
|
218
|
-
|
|
219
|
-
const result = await analyzeFrappe(dir);
|
|
220
|
-
expect(
|
|
221
|
-
result!.apps.find((a) => a.name === "myapp")!.doctypeCount,
|
|
222
|
-
).toBeGreaterThanOrEqual(2);
|
|
223
|
-
const customerDt = result!.doctypes.find((d) => d.name === "customer");
|
|
224
|
-
expect(customerDt).toBeDefined();
|
|
225
|
-
expect(customerDt!.nFields).toBe(2);
|
|
226
|
-
const orderDt = result!.doctypes.find((d) => d.name === "order");
|
|
227
|
-
expect(orderDt!.isSubmittable).toBe(true);
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
it("detects Frappe SPA from package.json", async () => {
|
|
231
|
-
const dir = await mkdtemp();
|
|
232
|
-
await fs.mkdir(path.join(dir, "apps", "frappe", "frappe"), {
|
|
233
|
-
recursive: true,
|
|
234
|
-
});
|
|
235
|
-
await fs.writeFile(path.join(dir, "apps.txt"), "frappe\n", "utf-8");
|
|
236
|
-
await fs.writeFile(
|
|
237
|
-
path.join(dir, "apps", "frappe", "package.json"),
|
|
238
|
-
JSON.stringify({ dependencies: { "@frappe/ui": "^1.0.0" } }),
|
|
239
|
-
"utf-8",
|
|
240
|
-
);
|
|
241
|
-
await fs.writeFile(
|
|
242
|
-
path.join(dir, "apps", "frappe", "frappe", "hooks.py"),
|
|
243
|
-
"app_name = 'frappe'\n",
|
|
244
|
-
"utf-8",
|
|
245
|
-
);
|
|
246
|
-
|
|
247
|
-
const result = await analyzeFrappe(dir);
|
|
248
|
-
expect(result!.hasSPA).toBe(true);
|
|
249
|
-
});
|
|
250
|
-
});
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generic Web Plugin Tests (RFC-0066)
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { describe, it, expect, afterEach } from "bun:test";
|
|
6
|
-
import * as fs from "node:fs/promises";
|
|
7
|
-
import * as path from "node:path";
|
|
8
|
-
import * as os from "node:os";
|
|
9
|
-
import { analyzeWeb, detectWeb } from "../src/analyzer.js";
|
|
10
|
-
|
|
11
|
-
const tempRoots: string[] = [];
|
|
12
|
-
|
|
13
|
-
async function mkdtemp(): Promise<string> {
|
|
14
|
-
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "generic-web-"));
|
|
15
|
-
tempRoots.push(dir);
|
|
16
|
-
return dir;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
afterEach(async () => {
|
|
20
|
-
for (const dir of tempRoots) {
|
|
21
|
-
try {
|
|
22
|
-
await fs.rm(dir, { recursive: true, force: true });
|
|
23
|
-
} catch {
|
|
24
|
-
// ignore
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
tempRoots.length = 0;
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
describe("detectWeb", () => {
|
|
31
|
-
it("returns false for empty directory", async () => {
|
|
32
|
-
const dir = await mkdtemp();
|
|
33
|
-
const result = await detectWeb(dir);
|
|
34
|
-
expect(result).toBe(false);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("returns true when package.json exists", async () => {
|
|
38
|
-
const dir = await mkdtemp();
|
|
39
|
-
await fs.writeFile(path.join(dir, "package.json"), "{}", "utf-8");
|
|
40
|
-
await fs.mkdir(path.join(dir, "node_modules"), { recursive: true });
|
|
41
|
-
const result = await detectWeb(dir);
|
|
42
|
-
expect(result).toBe(true);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it("returns true when src directory exists", async () => {
|
|
46
|
-
const dir = await mkdtemp();
|
|
47
|
-
await fs.mkdir(path.join(dir, "src"), { recursive: true });
|
|
48
|
-
await fs.writeFile(path.join(dir, "package.json"), "{}", "utf-8");
|
|
49
|
-
const result = await detectWeb(dir);
|
|
50
|
-
expect(result).toBe(true);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
describe("analyzeWeb", () => {
|
|
55
|
-
it("returns null for non-web workspace", async () => {
|
|
56
|
-
const dir = await mkdtemp();
|
|
57
|
-
const result = await analyzeWeb(dir);
|
|
58
|
-
expect(result).toBeNull();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it("detects Express.js from package.json", async () => {
|
|
62
|
-
const dir = await mkdtemp();
|
|
63
|
-
await fs.writeFile(
|
|
64
|
-
path.join(dir, "package.json"),
|
|
65
|
-
JSON.stringify({ dependencies: { express: "^4.18.0" } }),
|
|
66
|
-
"utf-8",
|
|
67
|
-
);
|
|
68
|
-
await fs.mkdir(path.join(dir, "src", "routes"), { recursive: true });
|
|
69
|
-
|
|
70
|
-
const result = await analyzeWeb(dir);
|
|
71
|
-
expect(result).not.toBeNull();
|
|
72
|
-
expect(result!.framework).toBe("express");
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it("detects Fastify", async () => {
|
|
76
|
-
const dir = await mkdtemp();
|
|
77
|
-
await fs.writeFile(
|
|
78
|
-
path.join(dir, "package.json"),
|
|
79
|
-
JSON.stringify({ dependencies: { fastify: "^4.0.0" } }),
|
|
80
|
-
"utf-8",
|
|
81
|
-
);
|
|
82
|
-
await fs.mkdir(path.join(dir, "node_modules"), { recursive: true });
|
|
83
|
-
|
|
84
|
-
const result = await analyzeWeb(dir);
|
|
85
|
-
expect(result).not.toBeNull();
|
|
86
|
-
expect(result!.framework).toBe("fastify");
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("detects React/Vite", async () => {
|
|
90
|
-
const dir = await mkdtemp();
|
|
91
|
-
await fs.writeFile(
|
|
92
|
-
path.join(dir, "package.json"),
|
|
93
|
-
JSON.stringify({
|
|
94
|
-
scripts: { dev: "vite" },
|
|
95
|
-
dependencies: { react: "^18.0.0" },
|
|
96
|
-
devDependencies: { vite: "^5.0.0" },
|
|
97
|
-
}),
|
|
98
|
-
"utf-8",
|
|
99
|
-
);
|
|
100
|
-
await fs.mkdir(path.join(dir, "node_modules"), { recursive: true });
|
|
101
|
-
|
|
102
|
-
const result = await analyzeWeb(dir);
|
|
103
|
-
expect(result).not.toBeNull();
|
|
104
|
-
expect(result!.framework).toBe("react-vite");
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it("marks SSR frameworks correctly", async () => {
|
|
108
|
-
const dir = await mkdtemp();
|
|
109
|
-
await fs.writeFile(
|
|
110
|
-
path.join(dir, "package.json"),
|
|
111
|
-
JSON.stringify({ dependencies: { next: "^14.0.0" } }),
|
|
112
|
-
"utf-8",
|
|
113
|
-
);
|
|
114
|
-
await fs.mkdir(path.join(dir, "node_modules"), { recursive: true });
|
|
115
|
-
|
|
116
|
-
const result = await analyzeWeb(dir);
|
|
117
|
-
expect(result).not.toBeNull();
|
|
118
|
-
expect(result!.ssr).toBe(true);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it("marks static site as non-SSR", async () => {
|
|
122
|
-
const dir = await mkdtemp();
|
|
123
|
-
await fs.writeFile(
|
|
124
|
-
path.join(dir, "package.json"),
|
|
125
|
-
JSON.stringify({ dependencies: { astro: "^3.0.0" } }),
|
|
126
|
-
"utf-8",
|
|
127
|
-
);
|
|
128
|
-
await fs.mkdir(path.join(dir, "node_modules"), { recursive: true });
|
|
129
|
-
|
|
130
|
-
const result = await analyzeWeb(dir);
|
|
131
|
-
expect(result).not.toBeNull();
|
|
132
|
-
expect(result!.ssr).toBe(true); // astro detected as astro, not static
|
|
133
|
-
});
|
|
134
|
-
});
|