| import { describe, expect, it } from "vitest"; |
| import type { MarketplacePlugin } from "#/api/plugins-service"; |
| import { |
| isPluginSelected, |
| marketplacePluginToSpec, |
| matchesPluginPickerSearch, |
| pluginSpecKey, |
| togglePluginSelection, |
| } from "#/components/features/plugins/plugin-spec-identity"; |
|
|
| const catalogPlugin: MarketplacePlugin = { |
| name: "city-weather", |
| description: "Weather plugin", |
| source: "github:OpenHands/extensions", |
| ref: null, |
| repo_path: "plugins/city-weather", |
| installed: false, |
| }; |
|
|
| describe("plugin-spec-identity", () => { |
| it("maps a catalog entry to attachable coordinates and drops parameters", () => { |
| |
| |
| const spec = marketplacePluginToSpec(catalogPlugin); |
|
|
| |
| expect(spec).toEqual({ |
| source: "github:OpenHands/extensions", |
| ref: null, |
| repo_path: "plugins/city-weather", |
| }); |
| }); |
|
|
| it("treats missing and explicit-null coordinates as the same identity", () => { |
| |
| |
| expect(pluginSpecKey({ source: "github:o/a" })).toBe( |
| pluginSpecKey({ source: "github:o/a", ref: null, repo_path: null }), |
| ); |
| }); |
|
|
| it("adds an unselected plugin to the selection", () => { |
| |
| const selected = togglePluginSelection([], catalogPlugin); |
|
|
| |
| expect(selected).toEqual([ |
| { |
| source: "github:OpenHands/extensions", |
| ref: null, |
| repo_path: "plugins/city-weather", |
| }, |
| ]); |
| }); |
|
|
| it("removes a plugin that is already selected", () => { |
| |
| const existing = marketplacePluginToSpec(catalogPlugin); |
|
|
| |
| const selected = togglePluginSelection([existing], catalogPlugin); |
|
|
| |
| expect(selected).toEqual([]); |
| }); |
|
|
| it("reports whether a plugin's coordinates are in the selection", () => { |
| |
| const selection = [marketplacePluginToSpec(catalogPlugin)]; |
|
|
| |
| expect(isPluginSelected(selection, catalogPlugin)).toBe(true); |
| expect( |
| isPluginSelected(selection, { |
| ...catalogPlugin, |
| repo_path: "plugins/other", |
| }), |
| ).toBe(false); |
| }); |
|
|
| it("filters case-insensitively by visible fields and matches everything when empty", () => { |
| |
| expect(matchesPluginPickerSearch(catalogPlugin, "")).toBe(true); |
| expect(matchesPluginPickerSearch(catalogPlugin, "WEATHER")).toBe(true); |
| expect(matchesPluginPickerSearch(catalogPlugin, "nonexistent")).toBe(false); |
| }); |
| }); |
|
|