package processor import ( "cook/utils" "testing" ) func TestSurgicalJSONEditing(t *testing.T) { tests := []struct { name string content string luaCode string expected string }{ { name: "Modify single field", content: `{ "name": "test", "value": 42, "description": "original" }`, luaCode: ` data.value = 84 modified = true `, expected: `{ "name": "test", "value": 84, "description": "original" }`, }, { name: "Add new field", content: `{ "name": "test", "value": 42 }`, luaCode: ` data.newField = "added" modified = true `, expected: `{ "name": "test", "value": 42 ,"newField":"added"}`, // sjson.Set() adds new fields in compact format }, { name: "Modify nested field", content: `{ "config": { "settings": { "enabled": false, "timeout": 30 } } }`, luaCode: ` data.config.settings.enabled = true data.config.settings.timeout = 60 modified = true `, expected: `{ "config": { "settings": { "enabled": true, "timeout": 60 } } }`, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { command := utils.ModifyCommand{ Name: "test", Lua: tt.luaCode, } commands, err := ProcessJSON(tt.content, command, "test.json") if err != nil { t.Fatalf("ProcessJSON failed: %v", err) } if len(commands) == 0 { t.Fatal("Expected at least one command") } // Apply the commands result := tt.content for _, cmd := range commands { result = result[:cmd.From] + cmd.With + result[cmd.To:] } // Check the actual result matches expected if result != tt.expected { t.Errorf("Expected:\n%s\n\nGot:\n%s", tt.expected, result) } }) } } func TestSurgicalJSONPreservesFormatting(t *testing.T) { // Test that surgical editing preserves the original formatting structure content := `{ "Defaults": { "Behaviour": "None", "Description": "", "DisplayName": "", "FlavorText": "", "Icon": "None", "MaxStack": 1, "Override_Glow_Icon": "None", "Weight": 0, "bAllowZeroWeight": false }, "RowStruct": "/Script/Icarus.ItemableData", "Rows": [ { "Description": "NSLOCTEXT(\"D_Itemable\", \"Item_Fiber-Description\", \"A bundle of soft fiber, highly useful.\")", "DisplayName": "NSLOCTEXT(\"D_Itemable\", \"Item_Fiber-DisplayName\", \"Fiber\")", "FlavorText": "NSLOCTEXT(\"D_Itemable\", \"Item_Fiber-FlavorText\", \"Fiber is collected from bast, the strong inner bark of certain flowering plants.\")", "Icon": "/Game/Assets/2DArt/UI/Items/Item_Icons/Resources/ITEM_Fibre.ITEM_Fibre", "MaxStack": 1000000, "Name": "Item_Fiber", "Weight": 10 } ] }` expected := `{ "Defaults": { "Behaviour": "None", "Description": "", "DisplayName": "", "FlavorText": "", "Icon": "None", "MaxStack": 1, "Override_Glow_Icon": "None", "Weight": 0, "bAllowZeroWeight": false }, "RowStruct": "/Script/Icarus.ItemableData", "Rows": [ { "Description": "NSLOCTEXT(\"D_Itemable\", \"Item_Fiber-Description\", \"A bundle of soft fiber, highly useful.\")", "DisplayName": "NSLOCTEXT(\"D_Itemable\", \"Item_Fiber-DisplayName\", \"Fiber\")", "FlavorText": "NSLOCTEXT(\"D_Itemable\", \"Item_Fiber-FlavorText\", \"Fiber is collected from bast, the strong inner bark of certain flowering plants.\")", "Icon": "/Game/Assets/2DArt/UI/Items/Item_Icons/Resources/ITEM_Fibre.ITEM_Fibre", "MaxStack": 1000000, "Name": "Item_Fiber", "Weight": 500 } ] }` command := utils.ModifyCommand{ Name: "test", Lua: ` -- Modify the weight of the first item data.Rows[1].Weight = 500 modified = true `, } commands, err := ProcessJSON(content, command, "test.json") if err != nil { t.Fatalf("ProcessJSON failed: %v", err) } if len(commands) == 0 { t.Fatal("Expected at least one command") } // Apply the commands result := content for _, cmd := range commands { result = result[:cmd.From] + cmd.With + result[cmd.To:] } // Check that the result matches expected (preserves formatting and changes weight) if result != expected { t.Errorf("Expected:\n%s\n\nGot:\n%s", expected, result) } } func TestRetardedJSONEditing(t *testing.T) { original := `{ "RowStruct": "/Script/Icarus.ItemableData", "Defaults": { "Behaviour": "None", "DisplayName": "", "Icon": "None", "Override_Glow_Icon": "None", "Description": "", "FlavorText": "", "Weight": 0, "bAllowZeroWeight": false, "MaxStack": 1 }, "Rows": [ { "DisplayName": "NSLOCTEXT(\"D_Itemable\", \"Item_Fiber-DisplayName\", \"Fiber\")", "Icon": "/Game/Assets/2DArt/UI/Items/Item_Icons/Resources/ITEM_Fibre.ITEM_Fibre", "Description": "NSLOCTEXT(\"D_Itemable\", \"Item_Fiber-Description\", \"A bundle of soft fiber, highly useful.\")", "FlavorText": "NSLOCTEXT(\"D_Itemable\", \"Item_Fiber-FlavorText\", \"Fiber is collected from bast, the strong inner bark of certain flowering plants.\")", "Weight": 10, "MaxStack": 200, "Name": "Item_Fiber" } ] }` expected := `{ "RowStruct": "/Script/Icarus.ItemableData", "Defaults": { "Behaviour": "None", "DisplayName": "", "Icon": "None", "Override_Glow_Icon": "None", "Description": "", "FlavorText": "", "Weight": 0, "bAllowZeroWeight": false, "MaxStack": 1 }, "Rows": [ { "DisplayName": "NSLOCTEXT(\"D_Itemable\", \"Item_Fiber-DisplayName\", \"Fiber\")", "Icon": "/Game/Assets/2DArt/UI/Items/Item_Icons/Resources/ITEM_Fibre.ITEM_Fibre", "Description": "NSLOCTEXT(\"D_Itemable\", \"Item_Fiber-Description\", \"A bundle of soft fiber, highly useful.\")", "FlavorText": "NSLOCTEXT(\"D_Itemable\", \"Item_Fiber-FlavorText\", \"Fiber is collected from bast, the strong inner bark of certain flowering plants.\")", "Weight": 10, "MaxStack": 1000000, "Name": "Item_Fiber" } ] }` command := utils.ModifyCommand{ Name: "test", Lua: ` for _, row in ipairs(data.Rows) do if row.MaxStack then if string.find(row.Name, "Carrot") or string.find(row.Name, "Potato") then row.MaxStack = 25 else row.MaxStack = row.MaxStack * 10000 if row.MaxStack > 1000000 then row.MaxStack = 1000000 end end end end `, } commands, err := ProcessJSON(original, command, "test.json") if err != nil { t.Fatalf("ProcessJSON failed: %v", err) } if len(commands) == 0 { t.Fatal("Expected at least one command") } // Apply the commands result := original for _, cmd := range commands { result = result[:cmd.From] + cmd.With + result[cmd.To:] } // Check that the weight was changed if result != expected { t.Errorf("Expected:\n%s\nGot:\n%s", expected, result) } }