File size: 3,696 Bytes
05c5ed5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import { describe, it, expect } from "vitest";
import { detectConfigChanges } from "./mcp-config-diff";
import type { MCPServerConfig } from "app-types/mcp";

describe("MCP Config Diff", () => {
  describe("detectConfigChanges", () => {
    it("should detect added configurations", () => {
      const prev: Record<string, MCPServerConfig> = {};
      const next: Record<string, MCPServerConfig> = {
        newConfig: {
          url: "https://example.com/sse",
        },
      };

      const changes = detectConfigChanges(prev, next);
      expect(changes.length).toBe(1);
      expect(changes[0]).toEqual({
        type: "add",
        key: "newConfig",
        value: {
          url: "https://example.com/sse",
        },
      });
    });

    it("should detect removed configurations", () => {
      const prev: Record<string, MCPServerConfig> = {
        oldConfig: {
          command: "python3",
        },
      };
      const next: Record<string, MCPServerConfig> = {};

      const changes = detectConfigChanges(prev, next);
      expect(changes.length).toBe(1);
      expect(changes[0]).toEqual({
        type: "remove",
        key: "oldConfig",
        value: {
          command: "python3",
        },
      });
    });

    it("should detect updated configurations", () => {
      const prev: Record<string, MCPServerConfig> = {
        config: {
          url: "https://old-example.com/sse",
        },
      };
      const next: Record<string, MCPServerConfig> = {
        config: {
          url: "https://new-example.com/sse",
        },
      };

      const changes = detectConfigChanges(prev, next);
      expect(changes.length).toBe(1);
      expect(changes[0]).toEqual({
        type: "update",
        key: "config",
        value: {
          url: "https://new-example.com/sse",
        },
      });
    });

    it("should detect multiple changes", () => {
      const prev: Record<string, MCPServerConfig> = {
        config1: {
          url: "https://example.com/sse1",
        },
        config2: {
          command: "python",
        },
      };
      const next: Record<string, MCPServerConfig> = {
        config1: {
          url: "https://example.com/sse1-updated",
        },
        config3: {
          command: "node",
        },
      };

      const changes = detectConfigChanges(prev, next);
      expect(changes.length).toBe(3);

      // Check that we have one of each type of change
      const changeTypes = changes.map((change) => change.type);
      expect(changeTypes).toContain("add");
      expect(changeTypes).toContain("remove");
      expect(changeTypes).toContain("update");

      // Verify the specific changes
      const addChange = changes.find((change) => change.type === "add");
      expect(addChange?.key).toBe("config3");

      const removeChange = changes.find((change) => change.type === "remove");
      expect(removeChange?.key).toBe("config2");

      const updateChange = changes.find((change) => change.type === "update");
      expect(updateChange?.key).toBe("config1");
    });

    it("should not detect changes for identical configurations", () => {
      const config: Record<string, MCPServerConfig> = {
        config: {
          url: "https://example.com/sse",
        },
      };

      const changes = detectConfigChanges(config, { ...config });
      expect(changes.length).toBe(0);
    });

    it("should throw error for invalid configurations", () => {
      const prev: Record<string, unknown> = {};
      const next: Record<string, unknown> = {
        invalidConfig: {
          type: "invalid",
        },
      };

      expect(() => detectConfigChanges(prev, next)).toThrow();
    });
  });
});