Skip to content

Commit bbf7d7b

Browse files
committed
test: add comprehensive VSCode settings transformation tests
- Add real-world test case for .vscode/settings.json transformation - Test actual repo name replacement in gopls formatting.local setting - Add DirectoryRealTransformChain for testing with actual transformers - Verify end-to-end transformation behavior matches expected output
1 parent 10a121c commit bbf7d7b

2 files changed

Lines changed: 207 additions & 0 deletions

File tree

internal/sync/directory_transform_test.go

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"time"
1212

1313
"github.com/sirupsen/logrus"
14+
"github.com/stretchr/testify/mock"
1415
"github.com/stretchr/testify/suite"
1516

1617
"github.com/mrz1836/go-broadcast/internal/config"
@@ -22,6 +23,7 @@ import (
2223
// Test error variables
2324
var (
2425
ErrGitTreeNotImplemented = errors.New("git tree not implemented in mock")
26+
ErrFileNotFound = errors.New("file not found")
2527
)
2628

2729
// DirectoryTransformTestSuite tests comprehensive directory transformation scenarios
@@ -1041,3 +1043,147 @@ func (m *DirectoryMockTransformChain) Transform(_ context.Context, content []byt
10411043

10421044
return []byte(result), nil
10431045
}
1046+
1047+
// DirectoryRealTransformChain provides a real transform chain for testing actual transformations
1048+
type DirectoryRealTransformChain struct {
1049+
transformers []transform.Transformer
1050+
}
1051+
1052+
// Add implements the Chain interface
1053+
func (m *DirectoryRealTransformChain) Add(transformer transform.Transformer) transform.Chain {
1054+
m.transformers = append(m.transformers, transformer)
1055+
return m
1056+
}
1057+
1058+
// Transformers implements the Chain interface
1059+
func (m *DirectoryRealTransformChain) Transformers() []transform.Transformer {
1060+
if len(m.transformers) == 0 {
1061+
// Initialize with the real repo transformer
1062+
m.transformers = append(m.transformers, transform.NewRepoTransformer())
1063+
}
1064+
return m.transformers
1065+
}
1066+
1067+
// Transform implements the real Transform method using actual transformers
1068+
func (m *DirectoryRealTransformChain) Transform(_ context.Context, content []byte, transformCtx transform.Context) ([]byte, error) {
1069+
result := content
1070+
1071+
// Apply all transformers in the chain
1072+
for _, transformer := range m.Transformers() {
1073+
var err error
1074+
result, err = transformer.Transform(result, transformCtx)
1075+
if err != nil {
1076+
return nil, fmt.Errorf("transformation failed with %s: %w", transformer.Name(), err)
1077+
}
1078+
}
1079+
1080+
return result, nil
1081+
}
1082+
1083+
// TestVSCodeSettingsRealWorldTransformation tests the specific case reported
1084+
// where .vscode/settings.json wasn't being transformed correctly during sync
1085+
func (suite *DirectoryTransformTestSuite) TestVSCodeSettingsRealWorldTransformation() {
1086+
ctx := context.Background()
1087+
1088+
// Create a temporary source directory with .vscode/settings.json
1089+
tmpDir := suite.T().TempDir()
1090+
vscodeDir := filepath.Join(tmpDir, ".vscode")
1091+
suite.Require().NoError(os.MkdirAll(vscodeDir, 0o750))
1092+
1093+
// Write the exact content from the real .vscode/settings.json file
1094+
settingsContent := `{
1095+
"[go]": {
1096+
"editor.formatOnSave": true,
1097+
"editor.codeActionsOnSave": {
1098+
"source.organizeImports": "explicit"
1099+
}
1100+
},
1101+
"[go.mod]": {
1102+
"editor.formatOnSave": true,
1103+
"editor.codeActionsOnSave": {
1104+
"source.organizeImports": "explicit"
1105+
}
1106+
},
1107+
"go.useLanguageServer": true,
1108+
"gopls": {
1109+
"formatting.local": "github.com/mrz1836/go-broadcast",
1110+
"formatting.gofumpt": true
1111+
},
1112+
"go.lintTool": "golangci-lint",
1113+
"go.lintFlags": ["--verbose"],
1114+
"[go][go.mod]": {
1115+
"editor.codeActionsOnSave": {
1116+
"source.organizeImports": "explicit"
1117+
}
1118+
}
1119+
}`
1120+
settingsPath := filepath.Join(vscodeDir, "settings.json")
1121+
suite.Require().NoError(os.WriteFile(settingsPath, []byte(settingsContent), 0o600))
1122+
1123+
// Configure the directory mapping for .vscode
1124+
dirMapping := config.DirectoryMapping{
1125+
Src: ".vscode",
1126+
Dest: ".vscode",
1127+
Transform: config.Transform{
1128+
RepoName: true,
1129+
},
1130+
}
1131+
1132+
// Set up target config for go-pre-commit repository
1133+
targetConfig := config.TargetConfig{
1134+
Repo: "mrz1836/go-pre-commit",
1135+
Transform: config.Transform{
1136+
RepoName: true,
1137+
},
1138+
}
1139+
1140+
sourceState := &state.SourceState{
1141+
Repo: "mrz1836/go-broadcast",
1142+
}
1143+
1144+
// Create a real engine with the actual repo transformer and a mock GitHub client
1145+
mockGHClient := gh.NewMockClient()
1146+
// Configure mock to return "file not found" for any GetFile call so all files are treated as new
1147+
mockGHClient.On("GetFile", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return((*gh.FileContent)(nil), ErrFileNotFound)
1148+
1149+
realEngine := &Engine{
1150+
transform: &DirectoryRealTransformChain{},
1151+
gh: mockGHClient,
1152+
}
1153+
1154+
// Process the directory mapping
1155+
changes, err := suite.processor.ProcessDirectoryMapping(
1156+
ctx, tmpDir, dirMapping, targetConfig, sourceState, realEngine,
1157+
)
1158+
1159+
suite.Require().NoError(err)
1160+
suite.Require().Len(changes, 1, "Should have exactly one file change for settings.json")
1161+
1162+
change := changes[0]
1163+
suite.Equal(".vscode/settings.json", change.Path)
1164+
1165+
// Verify the transformation happened correctly
1166+
transformedContent := string(change.Content)
1167+
originalContent := string(change.OriginalContent)
1168+
1169+
// Key assertion: formatting.local should be transformed
1170+
suite.Contains(transformedContent, `"formatting.local": "github.com/mrz1836/go-pre-commit"`,
1171+
"Should transform formatting.local to target repo")
1172+
suite.NotContains(transformedContent, `"formatting.local": "github.com/mrz1836/go-broadcast"`,
1173+
"Should not contain original repo in formatting.local")
1174+
1175+
// Verify the original content contained the source repo
1176+
suite.Contains(originalContent, `"formatting.local": "github.com/mrz1836/go-broadcast"`,
1177+
"Original content should contain source repo")
1178+
1179+
// Verify no other content was changed (except the transformation)
1180+
suite.Contains(transformedContent, `"go.useLanguageServer": true`)
1181+
suite.Contains(transformedContent, `"go.lintTool": "golangci-lint"`)
1182+
suite.Contains(transformedContent, `"formatting.gofumpt": true`)
1183+
1184+
suite.logger.WithFields(logrus.Fields{
1185+
"original_length": len(originalContent),
1186+
"transformed_length": len(transformedContent),
1187+
"file_path": change.Path,
1188+
}).Info("VSCode settings transformation test completed successfully")
1189+
}

internal/transform/repo_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,67 @@ The go-broadcast tool is amazing!`,
236236
The go-coverage tool is amazing!`,
237237
wantError: false,
238238
},
239+
{
240+
name: "real world vscode settings with full content",
241+
content: `{
242+
"[go]": {
243+
"editor.formatOnSave": true,
244+
"editor.codeActionsOnSave": {
245+
"source.organizeImports": "explicit"
246+
}
247+
},
248+
"[go.mod]": {
249+
"editor.formatOnSave": true,
250+
"editor.codeActionsOnSave": {
251+
"source.organizeImports": "explicit"
252+
}
253+
},
254+
"go.useLanguageServer": true,
255+
"gopls": {
256+
"formatting.local": "github.com/mrz1836/go-broadcast",
257+
"formatting.gofumpt": true
258+
},
259+
"go.lintTool": "golangci-lint",
260+
"go.lintFlags": ["--verbose"],
261+
"[go][go.mod]": {
262+
"editor.codeActionsOnSave": {
263+
"source.organizeImports": "explicit"
264+
}
265+
}
266+
}`,
267+
ctx: Context{
268+
SourceRepo: "mrz1836/go-broadcast",
269+
TargetRepo: "mrz1836/go-pre-commit",
270+
FilePath: ".vscode/settings.json",
271+
},
272+
wantContent: `{
273+
"[go]": {
274+
"editor.formatOnSave": true,
275+
"editor.codeActionsOnSave": {
276+
"source.organizeImports": "explicit"
277+
}
278+
},
279+
"[go.mod]": {
280+
"editor.formatOnSave": true,
281+
"editor.codeActionsOnSave": {
282+
"source.organizeImports": "explicit"
283+
}
284+
},
285+
"go.useLanguageServer": true,
286+
"gopls": {
287+
"formatting.local": "github.com/mrz1836/go-pre-commit",
288+
"formatting.gofumpt": true
289+
},
290+
"go.lintTool": "golangci-lint",
291+
"go.lintFlags": ["--verbose"],
292+
"[go][go.mod]": {
293+
"editor.codeActionsOnSave": {
294+
"source.organizeImports": "explicit"
295+
}
296+
}
297+
}`,
298+
wantError: false,
299+
},
239300
}
240301

241302
for _, tt := range tests {

0 commit comments

Comments
 (0)