|
2 | 2 | (:require |
3 | 3 | [babashka.fs :as fs] |
4 | 4 | [cheshire.core :as json] |
5 | | - [clojure.test :refer [deftest is testing]] |
| 5 | + [clojure.test :refer [deftest is testing use-fixtures]] |
6 | 6 | [eca.config :as config] |
| 7 | + [eca.features.commands :as commands] |
7 | 8 | [eca.features.plugins :as plugins] |
| 9 | + [eca.features.rules :as rules] |
| 10 | + [eca.interpolation :as interpolation] |
8 | 11 | [matcher-combinators.matchers :as m] |
9 | 12 | [matcher-combinators.test :refer [match?]])) |
10 | 13 |
|
| 14 | +(use-fixtures :each |
| 15 | + (fn [t] |
| 16 | + (interpolation/reset-plugin-dirs!) |
| 17 | + (try |
| 18 | + (t) |
| 19 | + (finally |
| 20 | + (interpolation/reset-plugin-dirs!))))) |
| 21 | + |
11 | 22 | (deftest sanitize-source-url-test |
12 | 23 | (testing "HTTPS URL" |
13 | 24 | (is (= "github.com-my-org-my-plugins" |
|
219 | 230 | (finally |
220 | 231 | (fs/delete-tree tmp-dir))))) |
221 | 232 |
|
| 233 | +(deftest plugin-root-interpolation-test |
| 234 | + (let [tmp-dir (fs/create-temp-dir)] |
| 235 | + (try |
| 236 | + (let [source-dir (fs/file tmp-dir "repo") |
| 237 | + plugin-dir (fs/file source-dir "plugins" "test" "demo") |
| 238 | + secret "line \"quoted\"\nbackslash \\ ok"] |
| 239 | + (fs/create-dirs (fs/file source-dir ".eca-plugin")) |
| 240 | + (fs/create-dirs (fs/file plugin-dir "hooks")) |
| 241 | + (fs/create-dirs (fs/file plugin-dir "commands")) |
| 242 | + (fs/create-dirs (fs/file plugin-dir "rules")) |
| 243 | + (spit (fs/file source-dir ".eca-plugin" "marketplace.json") |
| 244 | + (json/generate-string |
| 245 | + {:plugins [{:name "demo" |
| 246 | + :description "Demo" |
| 247 | + :source "./plugins/test/demo"}]})) |
| 248 | + (spit (fs/file plugin-dir "secret.txt") secret) |
| 249 | + (spit (fs/file plugin-dir ".mcp.json") |
| 250 | + (json/generate-string |
| 251 | + {:mcpServers {"local" {:command "${plugin:root}/bin/server"}}})) |
| 252 | + (spit (fs/file plugin-dir "eca.json") |
| 253 | + (json/generate-string |
| 254 | + {:pluginRoot "${plugin:root}" |
| 255 | + :quotedSecret "${file:secret.txt}"})) |
| 256 | + (spit (fs/file plugin-dir "hooks" "hooks.json") |
| 257 | + (json/generate-string |
| 258 | + {:PostToolUse [{:hooks [{:type "command" |
| 259 | + :command "node ${plugin:root}/hooks/check.js"}]}]})) |
| 260 | + (spit (fs/file plugin-dir "commands" "where.md") |
| 261 | + "Plugin command: ${plugin:root}") |
| 262 | + (spit (fs/file plugin-dir "rules" "where.md") |
| 263 | + "Plugin rule: ${plugin:root}") |
| 264 | + (let [plugin-root (str (fs/canonicalize plugin-dir)) |
| 265 | + result (plugins/resolve-all! |
| 266 | + {"local" {:source (str source-dir)} |
| 267 | + "install" ["demo"]})] |
| 268 | + (is (= (str plugin-root "/bin/server") |
| 269 | + (get-in result [:config-fragment :mcpServers :local :command]))) |
| 270 | + (is (= plugin-root |
| 271 | + (get-in result [:config-fragment :pluginRoot]))) |
| 272 | + (is (= secret |
| 273 | + (get-in result [:config-fragment :quotedSecret]))) |
| 274 | + (is (= (str "node " plugin-root "/hooks/check.js") |
| 275 | + (get-in result [:config-fragment :hooks :PostToolUse 0 :hooks 0 :command]))) |
| 276 | + (let [loaded-commands (vec (#'commands/custom-commands |
| 277 | + {:pureConfig true |
| 278 | + :commands (:commands result)} |
| 279 | + []))] |
| 280 | + (is (= [(str "Plugin command: " plugin-root)] |
| 281 | + (mapv :content loaded-commands)))) |
| 282 | + (let [loaded-rules (vec (#'rules/config-rules {:rules (:rules result)} []))] |
| 283 | + (is (= [(str "Plugin rule: " plugin-root)] |
| 284 | + (mapv :content loaded-rules)))))) |
| 285 | + (finally |
| 286 | + (fs/delete-tree tmp-dir))))) |
| 287 | + |
222 | 288 | (deftest merge-components-test |
223 | 289 | (testing "merges multiple plugin components" |
224 | 290 | (let [c1 {:config-fragment {:mcpServers {:server-a {:url "http://a"}} |
|
0 commit comments