Skip to content

Commit 6129873

Browse files
committed
feat: add tests
1 parent 3048406 commit 6129873

File tree

2 files changed

+469
-0
lines changed

2 files changed

+469
-0
lines changed

cmd/create_test.go

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,218 @@ func TestCreateCommand_DirectoryOverwrite(t *testing.T) {
412412
assert.FileExists(t, filepath.Join(appPath, "index.ts"), "new index.ts should exist")
413413
}
414414

415+
// TestCreateCommand_InvalidLanguageTemplateCombinations tests that invalid
416+
// language/template combinations fail with appropriate error messages
417+
func TestCreateCommand_InvalidLanguageTemplateCombinations(t *testing.T) {
418+
tests := []struct {
419+
name string
420+
language string
421+
template string
422+
errContains string
423+
}{
424+
{
425+
name: "browser-use not available for typescript",
426+
language: create.LanguageTypeScript,
427+
template: create.TemplateBrowserUse,
428+
errContains: "template not found: typescript/browser-use",
429+
},
430+
{
431+
name: "stagehand not available for python",
432+
language: create.LanguagePython,
433+
template: create.TemplateStagehand,
434+
errContains: "template not found: python/stagehand",
435+
},
436+
{
437+
name: "magnitude not available for python",
438+
language: create.LanguagePython,
439+
template: create.TemplateMagnitude,
440+
errContains: "template not found: python/magnitude",
441+
},
442+
{
443+
name: "gemini-cua not available for python",
444+
language: create.LanguagePython,
445+
template: create.TemplateGeminiCUA,
446+
errContains: "template not found: python/gemini-cua",
447+
},
448+
{
449+
name: "invalid language",
450+
language: "ruby",
451+
template: create.TemplateSampleApp,
452+
errContains: "template not found: ruby/sample-app",
453+
},
454+
{
455+
name: "invalid template",
456+
language: create.LanguageTypeScript,
457+
template: "nonexistent-template",
458+
errContains: "template not found: typescript/nonexistent-template",
459+
},
460+
}
461+
462+
for _, tt := range tests {
463+
t.Run(tt.name, func(t *testing.T) {
464+
tmpDir := t.TempDir()
465+
466+
orgDir, err := os.Getwd()
467+
require.NoError(t, err)
468+
469+
err = os.Chdir(tmpDir)
470+
require.NoError(t, err)
471+
472+
t.Cleanup(func() {
473+
os.Chdir(orgDir)
474+
})
475+
476+
c := CreateCmd{}
477+
err = c.Create(context.Background(), CreateInput{
478+
Name: "test-app",
479+
Language: tt.language,
480+
Template: tt.template,
481+
})
482+
483+
require.Error(t, err, "should fail with invalid language/template combination")
484+
assert.Contains(t, err.Error(), tt.errContains, "error message should contain expected text")
485+
})
486+
}
487+
}
488+
489+
// TestCreateCommand_ValidateAllTemplateCombinations validates that only valid
490+
// language/template combinations are defined in the Templates map
491+
func TestCreateCommand_ValidateAllTemplateCombinations(t *testing.T) {
492+
// This test ensures data consistency between Templates and actual template availability
493+
for templateKey, templateInfo := range create.Templates {
494+
for _, lang := range templateInfo.Languages {
495+
t.Run(lang+"/"+templateKey, func(t *testing.T) {
496+
tmpDir := t.TempDir()
497+
appPath := filepath.Join(tmpDir, "test-app")
498+
499+
err := os.MkdirAll(appPath, DIR_PERM)
500+
require.NoError(t, err)
501+
502+
// This should succeed for all combinations defined in Templates
503+
err = create.CopyTemplateFiles(appPath, lang, templateKey)
504+
require.NoError(t, err, "Template %s should be available for language %s as defined in Templates map", templateKey, lang)
505+
})
506+
}
507+
}
508+
}
509+
510+
// TestCreateCommand_InvalidLanguageShorthand tests that invalid language shorthands
511+
// are handled appropriately
512+
func TestCreateCommand_InvalidLanguageShorthand(t *testing.T) {
513+
tests := []struct {
514+
name string
515+
languageInput string
516+
expectedNormalized string
517+
}{
518+
{
519+
name: "ts shorthand normalizes to typescript",
520+
languageInput: "ts",
521+
expectedNormalized: create.LanguageTypeScript,
522+
},
523+
{
524+
name: "py shorthand normalizes to python",
525+
languageInput: "py",
526+
expectedNormalized: create.LanguagePython,
527+
},
528+
{
529+
name: "typescript remains typescript",
530+
languageInput: "typescript",
531+
expectedNormalized: create.LanguageTypeScript,
532+
},
533+
{
534+
name: "python remains python",
535+
languageInput: "python",
536+
expectedNormalized: create.LanguagePython,
537+
},
538+
{
539+
name: "invalid shorthand remains unchanged",
540+
languageInput: "js",
541+
expectedNormalized: "js",
542+
},
543+
}
544+
545+
for _, tt := range tests {
546+
t.Run(tt.name, func(t *testing.T) {
547+
normalized := create.NormalizeLanguage(tt.languageInput)
548+
assert.Equal(t, tt.expectedNormalized, normalized)
549+
})
550+
}
551+
}
552+
553+
// TestCreateCommand_TemplateNotAvailableForLanguage tests specific cases where
554+
// templates are not available for certain languages
555+
func TestCreateCommand_TemplateNotAvailableForLanguage(t *testing.T) {
556+
// Map of templates to languages they should NOT be available for
557+
unavailableCombinations := map[string][]string{
558+
create.TemplateBrowserUse: {create.LanguageTypeScript},
559+
create.TemplateStagehand: {create.LanguagePython},
560+
create.TemplateMagnitude: {create.LanguagePython},
561+
create.TemplateGeminiCUA: {create.LanguagePython},
562+
}
563+
564+
for template, unavailableLanguages := range unavailableCombinations {
565+
for _, lang := range unavailableLanguages {
566+
t.Run(template+"/"+lang, func(t *testing.T) {
567+
// Verify the template info doesn't list this language
568+
templateInfo, exists := create.Templates[template]
569+
require.True(t, exists, "Template %s should exist in Templates map", template)
570+
571+
assert.NotContains(t, templateInfo.Languages, lang,
572+
"Template %s should not list %s as a supported language", template, lang)
573+
574+
// Verify copying fails
575+
tmpDir := t.TempDir()
576+
appPath := filepath.Join(tmpDir, "test-app")
577+
err := os.MkdirAll(appPath, DIR_PERM)
578+
require.NoError(t, err)
579+
580+
err = create.CopyTemplateFiles(appPath, lang, template)
581+
require.Error(t, err, "Should fail to copy %s template for %s", template, lang)
582+
})
583+
}
584+
}
585+
}
586+
587+
// TestCreateCommand_AllTemplatesHaveDeployCommands ensures that all templates
588+
// have corresponding deploy commands defined
589+
func TestCreateCommand_AllTemplatesHaveDeployCommands(t *testing.T) {
590+
for templateKey, templateInfo := range create.Templates {
591+
for _, lang := range templateInfo.Languages {
592+
t.Run(lang+"/"+templateKey, func(t *testing.T) {
593+
deployCmd := create.GetDeployCommand(lang, templateKey)
594+
assert.NotEmpty(t, deployCmd, "Deploy command should exist for %s/%s", lang, templateKey)
595+
596+
// Verify deploy command starts with "kernel deploy"
597+
assert.Contains(t, deployCmd, "kernel deploy", "Deploy command should start with 'kernel deploy'")
598+
599+
// Verify it contains the entry point
600+
switch lang {
601+
case create.LanguageTypeScript:
602+
assert.Contains(t, deployCmd, "index.ts", "TypeScript deploy command should contain index.ts")
603+
case create.LanguagePython:
604+
assert.Contains(t, deployCmd, "main.py", "Python deploy command should contain main.py")
605+
}
606+
})
607+
}
608+
}
609+
}
610+
611+
// TestCreateCommand_AllTemplatesHaveInvokeSamples ensures that all templates
612+
// have corresponding invoke samples defined
613+
func TestCreateCommand_AllTemplatesHaveInvokeSamples(t *testing.T) {
614+
for templateKey, templateInfo := range create.Templates {
615+
for _, lang := range templateInfo.Languages {
616+
t.Run(lang+"/"+templateKey, func(t *testing.T) {
617+
invokeCmd := create.GetInvokeSample(lang, templateKey)
618+
assert.NotEmpty(t, invokeCmd, "Invoke sample should exist for %s/%s", lang, templateKey)
619+
620+
// Verify invoke command starts with "kernel invoke"
621+
assert.Contains(t, invokeCmd, "kernel invoke", "Invoke command should start with 'kernel invoke'")
622+
})
623+
}
624+
}
625+
}
626+
415627
func getTemplateInfo() []struct {
416628
name string
417629
language string

0 commit comments

Comments
 (0)