package reconcile import ( "encoding/json" "testing" ) func TestJsonSet(t *testing.T) { munin := json.RawMessage(`{"type":"http","url":"https://m"}`) tests := []struct { name, before string path []string value json.RawMessage expected string }{ {"neue Datei", "", []string{"mcpServers", "munin"}, munin, "{\n \"mcpServers\": {\n \"munin\": {\n \"type\": \"http\",\n \"url\": \"https://m\"\n }\n }\n}\n"}, {"Einrückung der Datei", "{\n \"a\": 1\n}\n", []string{"mcpServers", "munin"}, munin, "{\n \"a\": 1,\n \"mcpServers\": {\n \"munin\": {\n \"type\": \"http\",\n \"url\": \"https://m\"\n }\n }\n}\n"}, {"Kommentare bleiben", "{\n // Modell\n \"model\": \"x\"\n}\n", []string{"mcp", "munin"}, json.RawMessage(`{"enabled":true}`), "{\n // Modell\n \"model\": \"x\",\n \"mcp\": {\n \"munin\": {\n \"enabled\": true\n }\n }\n}\n"}, {"einzeilige Datei bleibt einzeilig", `{"a": 1}`, []string{"b"}, json.RawMessage(`{"c": 2}`), `{"a": 1, "b": {"c":2}}` + "\n"}, {"vorhandenen Wert ersetzen", "{\n \"a\": 1,\n \"b\": 2\n}\n", []string{"a"}, json.RawMessage(`[1,2]`), "{\n \"a\": [\n 1,\n 2\n ],\n \"b\": 2\n}\n"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { d, err := readJson([]byte(tt.before), tt.before == "") if err != nil { t.Fatal(err) } if err := d.set(tt.path, tt.value); err != nil { t.Fatal(err) } if got := string(d.bytes()); got != tt.expected { t.Errorf("\n got:\n%s\nwant:\n%s", got, tt.expected) } }) } } func TestJsonList(t *testing.T) { entry := json.RawMessage(`".hugin/rules/*.md"`) tests := []struct{ name, before, expected string }{ {"Liste fehlt", "{\n \"model\": \"x\"\n}\n", "{\n \"model\": \"x\",\n \"instructions\": [\n \".hugin/rules/*.md\"\n ]\n}\n"}, {"einzeilige Liste", "{\n \"instructions\": [\"docs/a.md\"]\n}\n", "{\n \"instructions\": [\"docs/a.md\", \".hugin/rules/*.md\"]\n}\n"}, {"mehrzeilige Liste", "{\n \"instructions\": [\n \"docs/a.md\"\n ]\n}\n", "{\n \"instructions\": [\n \"docs/a.md\",\n \".hugin/rules/*.md\"\n ]\n}\n"}, {"schon vorhanden", "{\"instructions\": [\".hugin/rules/*.md\"]}\n", "{\"instructions\": [\".hugin/rules/*.md\"]}\n"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { d, _ := readJson([]byte(tt.before), false) if err := d.addToList([]string{"instructions"}, entry); err != nil { t.Fatal(err) } if got := string(d.bytes()); got != tt.expected { t.Errorf("\n got:\n%s\nwant:\n%s", got, tt.expected) } if err := d.removeFromList([]string{"instructions"}, entry); err != nil { t.Fatal(err) } value, ok := d.read([]string{"instructions"}) if items, _ := value.([]any); ok && (len(items) == 0 || index(items, entry) >= 0) { t.Errorf("Eintrag nicht entfernt oder leere Liste übrig: %v", value) } }) } } func TestJsonSpecialCharsInKey(t *testing.T) { d, _ := readJson(nil, true) if err := d.set([]string{"a/b", "c~d", "e.f"}, json.RawMessage(`1`)); err != nil { t.Fatal(err) } if value, ok := d.read([]string{"a/b", "c~d", "e.f"}); !ok || value != float64(1) { t.Errorf("lesen: %v %v\n%s", value, ok, d.bytes()) } }