github.com/speakeasy-api/sdk-gen-config@v1.14.2/io_test.go (about) 1 package config 2 3 import ( 4 "os" 5 "path/filepath" 6 "testing" 7 8 "github.com/speakeasy-api/sdk-gen-config/workspace" 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 ) 12 13 const testDir = "gen/test" 14 15 func TestLoad_Success(t *testing.T) { 16 getUUID = func() string { 17 return "123" 18 } 19 20 type args struct { 21 langs []string 22 configDir string 23 targetDir string 24 genYaml string 25 lockFile string 26 configSubDir string 27 } 28 tests := []struct { 29 name string 30 args args 31 want *Config 32 }{ 33 { 34 name: "creates config file and lock file if it doesn't exist in the .speakeasy dir", 35 args: args{ 36 langs: []string{"go"}, 37 configDir: testDir, 38 targetDir: testDir, 39 configSubDir: ".speakeasy", 40 }, 41 want: &Config{ 42 Config: &Configuration{ 43 ConfigVersion: Version, 44 Languages: map[string]LanguageConfig{ 45 "go": { 46 Version: "0.0.1", 47 }, 48 }, 49 Generation: Generation{ 50 SDKClassName: "SDK", 51 MaintainOpenAPIOrder: true, 52 UsageSnippets: &UsageSnippets{ 53 OptionalPropertyRendering: "withExample", 54 }, 55 Fixes: &Fixes{ 56 NameResolutionDec2023: true, 57 ParameterOrderingFeb2024: true, 58 RequestResponseComponentNamesFeb2024: true, 59 }, 60 Auth: &Auth{ 61 OAuth2ClientCredentialsEnabled: true, 62 }, 63 UseClassNamesForArrayFields: true, 64 }, 65 New: map[string]bool{ 66 "go": true, 67 }, 68 }, 69 ConfigPath: filepath.Join(os.TempDir(), testDir, ".speakeasy/gen.yaml"), 70 LockFile: &LockFile{ 71 LockVersion: Version, 72 ID: "123", 73 Management: Management{}, 74 Features: make(map[string]map[string]string), 75 }, 76 }, 77 }, 78 { 79 name: "loads and upgrades pre v1.0.0 config file", 80 args: args{ 81 langs: []string{"go"}, 82 configDir: testDir, 83 targetDir: testDir, 84 genYaml: readTestFile(t, "pre-v100-gen.yaml"), 85 }, 86 want: &Config{ 87 Config: &Configuration{ 88 ConfigVersion: Version, 89 Languages: map[string]LanguageConfig{ 90 "go": { 91 Version: "1.3.0", 92 Cfg: map[string]any{ 93 "packageName": "github.com/speakeasy-api/speakeasy-client-sdk-go", 94 }, 95 }, 96 }, 97 Generation: Generation{ 98 BaseServerURL: "https://api.prod.speakeasyapi.dev", 99 SDKClassName: "speakeasy", 100 UsageSnippets: &UsageSnippets{ 101 OptionalPropertyRendering: "withExample", 102 }, 103 Fixes: &Fixes{ 104 NameResolutionDec2023: false, 105 ParameterOrderingFeb2024: false, 106 RequestResponseComponentNamesFeb2024: false, 107 }, 108 Auth: &Auth{ 109 OAuth2ClientCredentialsEnabled: false, 110 }, 111 }, 112 New: map[string]bool{}, 113 }, 114 ConfigPath: filepath.Join(os.TempDir(), testDir, "gen.yaml"), 115 LockFile: &LockFile{ 116 LockVersion: Version, 117 ID: "123", 118 Management: Management{ 119 DocChecksum: "2bba3b8f9d211b02569b3f9aff0d34b4", 120 DocVersion: "0.3.0", 121 SpeakeasyVersion: "1.3.1", 122 ReleaseVersion: "1.3.0", 123 }, 124 Features: make(map[string]map[string]string), 125 }, 126 }, 127 }, 128 { 129 name: "loads v1.0.0 config file", 130 args: args{ 131 langs: []string{"go"}, 132 configDir: testDir, 133 targetDir: testDir, 134 genYaml: readTestFile(t, "v100-gen.yaml"), 135 configSubDir: ".speakeasy", 136 }, 137 want: &Config{ 138 Config: &Configuration{ 139 ConfigVersion: Version, 140 Languages: map[string]LanguageConfig{ 141 "go": { 142 Version: "1.3.0", 143 Cfg: map[string]any{ 144 "packageName": "github.com/speakeasy-api/speakeasy-client-sdk-go", 145 }, 146 }, 147 }, 148 Generation: Generation{ 149 BaseServerURL: "https://api.prod.speakeasyapi.dev", 150 SDKClassName: "speakeasy", 151 UsageSnippets: &UsageSnippets{ 152 OptionalPropertyRendering: "withExample", 153 }, 154 Fixes: &Fixes{ 155 NameResolutionDec2023: false, 156 ParameterOrderingFeb2024: false, 157 RequestResponseComponentNamesFeb2024: false, 158 }, 159 Auth: &Auth{ 160 OAuth2ClientCredentialsEnabled: false, 161 }, 162 }, 163 New: map[string]bool{}, 164 }, 165 ConfigPath: filepath.Join(os.TempDir(), testDir, ".speakeasy/gen.yaml"), 166 LockFile: &LockFile{ 167 LockVersion: Version, 168 ID: "123", 169 Management: Management{ 170 DocChecksum: "2bba3b8f9d211b02569b3f9aff0d34b4", 171 DocVersion: "0.3.0", 172 SpeakeasyVersion: "1.3.1", 173 ReleaseVersion: "1.3.0", 174 }, 175 Features: map[string]map[string]string{ 176 "go": { 177 "core": "2.90.0", 178 }, 179 }, 180 }, 181 }, 182 }, 183 { 184 name: "loads v2.0.0 config file", 185 args: args{ 186 langs: []string{"go"}, 187 configDir: testDir, 188 targetDir: testDir, 189 genYaml: readTestFile(t, "v200-gen.yaml"), 190 lockFile: readTestFile(t, "v200-gen.lock"), 191 configSubDir: ".speakeasy", 192 }, 193 want: &Config{ 194 Config: &Configuration{ 195 ConfigVersion: Version, 196 Languages: map[string]LanguageConfig{ 197 "go": { 198 Version: "1.3.0", 199 Cfg: map[string]any{ 200 "packageName": "github.com/speakeasy-api/speakeasy-client-sdk-go", 201 }, 202 }, 203 }, 204 Generation: Generation{ 205 BaseServerURL: "https://api.prod.speakeasyapi.dev", 206 SDKClassName: "speakeasy", 207 UsageSnippets: &UsageSnippets{ 208 OptionalPropertyRendering: "withExample", 209 }, 210 Fixes: &Fixes{ 211 NameResolutionDec2023: false, 212 ParameterOrderingFeb2024: false, 213 RequestResponseComponentNamesFeb2024: false, 214 }, 215 Auth: &Auth{ 216 OAuth2ClientCredentialsEnabled: false, 217 }, 218 }, 219 New: map[string]bool{}, 220 }, 221 ConfigPath: filepath.Join(os.TempDir(), testDir, ".speakeasy/gen.yaml"), 222 LockFile: &LockFile{ 223 LockVersion: Version, 224 ID: "0f8fad5b-d9cb-469f-a165-70867728950e", 225 Management: Management{ 226 DocChecksum: "2bba3b8f9d211b02569b3f9aff0d34b4", 227 DocVersion: "0.3.0", 228 SpeakeasyVersion: "1.3.1", 229 ReleaseVersion: "1.3.0", 230 }, 231 Features: map[string]map[string]string{ 232 "go": { 233 "core": "2.90.0", 234 }, 235 }, 236 }, 237 }, 238 }, 239 { 240 name: "loads v2.0.0 config file without existing lock file as a new sdk", 241 args: args{ 242 langs: []string{"go"}, 243 configDir: testDir, 244 targetDir: testDir, 245 genYaml: readTestFile(t, "v200-gen.yaml"), 246 configSubDir: ".speakeasy", 247 }, 248 want: &Config{ 249 Config: &Configuration{ 250 ConfigVersion: Version, 251 Languages: map[string]LanguageConfig{ 252 "go": { 253 Version: "1.3.0", 254 Cfg: map[string]any{ 255 "packageName": "github.com/speakeasy-api/speakeasy-client-sdk-go", 256 }, 257 }, 258 }, 259 Generation: Generation{ 260 BaseServerURL: "https://api.prod.speakeasyapi.dev", 261 SDKClassName: "speakeasy", 262 UsageSnippets: &UsageSnippets{ 263 OptionalPropertyRendering: "withExample", 264 }, 265 Fixes: &Fixes{ 266 NameResolutionDec2023: true, 267 ParameterOrderingFeb2024: true, 268 RequestResponseComponentNamesFeb2024: true, 269 }, 270 Auth: &Auth{ 271 OAuth2ClientCredentialsEnabled: true, 272 }, 273 MaintainOpenAPIOrder: true, 274 UseClassNamesForArrayFields: true, 275 }, 276 New: map[string]bool{ 277 "go": true, 278 }, 279 }, 280 ConfigPath: filepath.Join(os.TempDir(), testDir, ".speakeasy/gen.yaml"), 281 LockFile: &LockFile{ 282 LockVersion: Version, 283 ID: "123", 284 Management: Management{}, 285 Features: make(map[string]map[string]string), 286 }, 287 }, 288 }, 289 { 290 name: "loads v2.0.0 config file without existing lock file as a new sdk from .gen folder", 291 args: args{ 292 langs: []string{"go"}, 293 configDir: testDir, 294 targetDir: testDir, 295 genYaml: readTestFile(t, "v200-gen.yaml"), 296 configSubDir: ".gen", 297 }, 298 want: &Config{ 299 Config: &Configuration{ 300 ConfigVersion: Version, 301 Languages: map[string]LanguageConfig{ 302 "go": { 303 Version: "1.3.0", 304 Cfg: map[string]any{ 305 "packageName": "github.com/speakeasy-api/speakeasy-client-sdk-go", 306 }, 307 }, 308 }, 309 Generation: Generation{ 310 BaseServerURL: "https://api.prod.speakeasyapi.dev", 311 SDKClassName: "speakeasy", 312 UsageSnippets: &UsageSnippets{ 313 OptionalPropertyRendering: "withExample", 314 }, 315 Fixes: &Fixes{ 316 NameResolutionDec2023: true, 317 ParameterOrderingFeb2024: true, 318 RequestResponseComponentNamesFeb2024: true, 319 }, 320 Auth: &Auth{ 321 OAuth2ClientCredentialsEnabled: true, 322 }, 323 MaintainOpenAPIOrder: true, 324 UseClassNamesForArrayFields: true, 325 }, 326 New: map[string]bool{ 327 "go": true, 328 }, 329 }, 330 ConfigPath: filepath.Join(os.TempDir(), testDir, ".gen/gen.yaml"), 331 LockFile: &LockFile{ 332 LockVersion: Version, 333 ID: "123", 334 Management: Management{}, 335 Features: make(map[string]map[string]string), 336 }, 337 }, 338 }, 339 { 340 name: "loads v2.0.0 config file from higher level directory", 341 args: args{ 342 langs: []string{"go"}, 343 configDir: filepath.Dir(testDir), 344 targetDir: testDir, 345 genYaml: readTestFile(t, "v200-gen.yaml"), 346 lockFile: readTestFile(t, "v200-gen.lock"), 347 }, 348 want: &Config{ 349 Config: &Configuration{ 350 ConfigVersion: Version, 351 Languages: map[string]LanguageConfig{ 352 "go": { 353 Version: "1.3.0", 354 Cfg: map[string]any{ 355 "packageName": "github.com/speakeasy-api/speakeasy-client-sdk-go", 356 }, 357 }, 358 }, 359 Generation: Generation{ 360 BaseServerURL: "https://api.prod.speakeasyapi.dev", 361 SDKClassName: "speakeasy", 362 UsageSnippets: &UsageSnippets{ 363 OptionalPropertyRendering: "withExample", 364 }, 365 Fixes: &Fixes{ 366 NameResolutionDec2023: false, 367 ParameterOrderingFeb2024: false, 368 RequestResponseComponentNamesFeb2024: false, 369 }, 370 Auth: &Auth{ 371 OAuth2ClientCredentialsEnabled: false, 372 }, 373 }, 374 New: map[string]bool{}, 375 }, 376 ConfigPath: filepath.Join(os.TempDir(), filepath.Dir(testDir), "gen.yaml"), 377 LockFile: &LockFile{ 378 LockVersion: Version, 379 ID: "0f8fad5b-d9cb-469f-a165-70867728950e", 380 Management: Management{ 381 DocChecksum: "2bba3b8f9d211b02569b3f9aff0d34b4", 382 DocVersion: "0.3.0", 383 SpeakeasyVersion: "1.3.1", 384 ReleaseVersion: "1.3.0", 385 }, 386 Features: map[string]map[string]string{ 387 "go": { 388 "core": "2.90.0", 389 }, 390 }, 391 }, 392 }, 393 }, 394 { 395 name: "loads v100 config file and detects new config for language", 396 args: args{ 397 langs: []string{"go", "typescript"}, 398 configDir: testDir, 399 targetDir: testDir, 400 genYaml: readTestFile(t, "v100-gen.yaml"), 401 }, 402 want: &Config{ 403 Config: &Configuration{ 404 ConfigVersion: Version, 405 Languages: map[string]LanguageConfig{ 406 "go": { 407 Version: "1.3.0", 408 Cfg: map[string]any{ 409 "packageName": "github.com/speakeasy-api/speakeasy-client-sdk-go", 410 }, 411 }, 412 "typescript": { 413 Version: "0.0.1", 414 }, 415 }, 416 Generation: Generation{ 417 BaseServerURL: "https://api.prod.speakeasyapi.dev", 418 SDKClassName: "speakeasy", 419 UsageSnippets: &UsageSnippets{ 420 OptionalPropertyRendering: "withExample", 421 }, 422 Fixes: &Fixes{ 423 NameResolutionDec2023: false, 424 ParameterOrderingFeb2024: false, 425 RequestResponseComponentNamesFeb2024: false, 426 }, 427 Auth: &Auth{ 428 OAuth2ClientCredentialsEnabled: false, 429 }, 430 }, 431 New: map[string]bool{ 432 "typescript": true, 433 }, 434 }, 435 ConfigPath: filepath.Join(os.TempDir(), testDir, "gen.yaml"), 436 LockFile: &LockFile{ 437 LockVersion: Version, 438 ID: "123", 439 Management: Management{ 440 DocChecksum: "2bba3b8f9d211b02569b3f9aff0d34b4", 441 DocVersion: "0.3.0", 442 SpeakeasyVersion: "1.3.1", 443 ReleaseVersion: "1.3.0", 444 }, 445 Features: map[string]map[string]string{ 446 "go": { 447 "core": "2.90.0", 448 }, 449 }, 450 }, 451 }, 452 }, 453 { 454 name: "loads v2.0.0 config file and detects new config for language", 455 args: args{ 456 langs: []string{"go", "typescript"}, 457 configDir: testDir, 458 targetDir: testDir, 459 genYaml: readTestFile(t, "v200-gen.yaml"), 460 lockFile: readTestFile(t, "v200-gen.lock"), 461 configSubDir: ".speakeasy", 462 }, 463 want: &Config{ 464 Config: &Configuration{ 465 ConfigVersion: Version, 466 Languages: map[string]LanguageConfig{ 467 "go": { 468 Version: "1.3.0", 469 Cfg: map[string]any{ 470 "packageName": "github.com/speakeasy-api/speakeasy-client-sdk-go", 471 }, 472 }, 473 "typescript": { 474 Version: "0.0.1", 475 }, 476 }, 477 Generation: Generation{ 478 BaseServerURL: "https://api.prod.speakeasyapi.dev", 479 SDKClassName: "speakeasy", 480 UsageSnippets: &UsageSnippets{ 481 OptionalPropertyRendering: "withExample", 482 }, 483 Fixes: &Fixes{ 484 NameResolutionDec2023: false, 485 ParameterOrderingFeb2024: false, 486 RequestResponseComponentNamesFeb2024: false, 487 }, 488 Auth: &Auth{ 489 OAuth2ClientCredentialsEnabled: false, 490 }, 491 }, 492 New: map[string]bool{ 493 "typescript": true, 494 }, 495 }, 496 ConfigPath: filepath.Join(os.TempDir(), testDir, ".speakeasy/gen.yaml"), 497 LockFile: &LockFile{ 498 LockVersion: Version, 499 ID: "0f8fad5b-d9cb-469f-a165-70867728950e", 500 Management: Management{ 501 DocChecksum: "2bba3b8f9d211b02569b3f9aff0d34b4", 502 DocVersion: "0.3.0", 503 SpeakeasyVersion: "1.3.1", 504 ReleaseVersion: "1.3.0", 505 }, 506 Features: map[string]map[string]string{ 507 "go": { 508 "core": "2.90.0", 509 }, 510 }, 511 }, 512 }, 513 }, 514 } 515 for _, tt := range tests { 516 t.Run(tt.name, func(t *testing.T) { 517 configDir := filepath.Join(os.TempDir(), tt.args.configDir) 518 if tt.args.configSubDir != "" { 519 configDir = filepath.Join(configDir, tt.args.configSubDir) 520 } 521 targetDir := filepath.Join(os.TempDir(), tt.args.targetDir) 522 523 lockFileDir := filepath.Join(targetDir, tt.args.configSubDir) 524 if tt.args.configSubDir == "" { 525 lockFileDir = filepath.Join(targetDir, ".speakeasy") 526 } 527 528 err := createTempFile(configDir, "gen.yaml", tt.args.genYaml) 529 require.NoError(t, err) 530 531 err = createTempFile(lockFileDir, "gen.lock", tt.args.lockFile) 532 require.NoError(t, err) 533 534 defer os.RemoveAll(configDir) 535 defer os.RemoveAll(targetDir) 536 537 opts := []Option{ 538 WithUpgradeFunc(testUpdateLang), 539 } 540 541 for _, lang := range tt.args.langs { 542 opts = append(opts, WithLanguages(lang)) 543 } 544 545 cfg, err := Load(targetDir, opts...) 546 assert.NoError(t, err) 547 assert.Equal(t, tt.want, cfg) 548 _, err = os.Stat(filepath.Join(configDir, "gen.yaml")) 549 assert.NoError(t, err) 550 _, err = os.Stat(filepath.Join(lockFileDir, "gen.lock")) 551 assert.NoError(t, err) 552 }) 553 } 554 } 555 556 func TestLoad_BackwardsCompatibility_Success(t *testing.T) { 557 getUUID = func() string { 558 return "123" 559 } 560 561 // Create new config file in .speakeasy dir 562 speakeasyDir := filepath.Join(os.TempDir(), testDir, workspace.SpeakeasyFolder) 563 err := createTempFile(speakeasyDir, "gen.yaml", readTestFile(t, "v200-gen.yaml")) 564 require.NoError(t, err) 565 566 // Create old config file in root dir 567 rootDir := filepath.Join(os.TempDir(), testDir) 568 err = createTempFile(rootDir, "gen.yaml", readTestFile(t, "v100-gen.yaml")) 569 require.NoError(t, err) 570 571 defer os.RemoveAll(speakeasyDir) 572 defer os.RemoveAll(rootDir) 573 574 opts := []Option{ 575 WithUpgradeFunc(testUpdateLang), 576 } 577 578 opts = append(opts, WithLanguages("go")) 579 580 cfg, err := Load(rootDir, opts...) 581 assert.NoError(t, err) 582 assert.Equal(t, &Config{ 583 Config: &Configuration{ 584 ConfigVersion: Version, 585 Languages: map[string]LanguageConfig{ 586 "go": { 587 Version: "1.3.0", 588 Cfg: map[string]any{ 589 "packageName": "github.com/speakeasy-api/speakeasy-client-sdk-go", 590 }, 591 }, 592 }, 593 Generation: Generation{ 594 BaseServerURL: "https://api.prod.speakeasyapi.dev", 595 SDKClassName: "speakeasy", 596 UsageSnippets: &UsageSnippets{ 597 OptionalPropertyRendering: "withExample", 598 }, 599 Fixes: &Fixes{ 600 NameResolutionDec2023: false, 601 ParameterOrderingFeb2024: false, 602 RequestResponseComponentNamesFeb2024: false, 603 }, 604 Auth: &Auth{ 605 OAuth2ClientCredentialsEnabled: false, 606 }, 607 }, 608 New: map[string]bool{}, 609 }, 610 ConfigPath: filepath.Join(os.TempDir(), testDir, "gen.yaml"), 611 LockFile: &LockFile{ 612 LockVersion: Version, 613 ID: "123", 614 Management: Management{ 615 DocChecksum: "2bba3b8f9d211b02569b3f9aff0d34b4", 616 DocVersion: "0.3.0", 617 SpeakeasyVersion: "1.3.1", 618 ReleaseVersion: "1.3.0", 619 }, 620 Features: map[string]map[string]string{ 621 "go": { 622 "core": "2.90.0", 623 }, 624 }, 625 }, 626 }, cfg) 627 _, err = os.Stat(filepath.Join(rootDir, "gen.yaml")) 628 assert.NoError(t, err) 629 _, err = os.Stat(filepath.Join(speakeasyDir, "gen.lock")) 630 assert.NoError(t, err) 631 } 632 633 func createTempFile(dir string, fileName, contents string) error { 634 if err := os.MkdirAll(dir, os.ModePerm); err != nil { 635 return err 636 } 637 638 if contents != "" { 639 tmpFile := filepath.Join(dir, fileName) 640 if err := os.WriteFile(tmpFile, []byte(contents), os.ModePerm); err != nil { 641 return err 642 } 643 } 644 645 return nil 646 } 647 648 func readTestFile(t *testing.T, file string) string { 649 t.Helper() 650 data, err := os.ReadFile(filepath.Join("testdata", file)) 651 if err != nil { 652 t.Fatal(err) 653 } 654 655 return string(data) 656 }