Skip to content

Commit 90fa87e

Browse files
committed
feat: add tests
1 parent 2778279 commit 90fa87e

2 files changed

Lines changed: 469 additions & 0 deletions

File tree

cmd/create_test.go

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

317+
// TestCreateCommand_InvalidLanguageTemplateCombinations tests that invalid
318+
// language/template combinations fail with appropriate error messages
319+
func TestCreateCommand_InvalidLanguageTemplateCombinations(t *testing.T) {
320+
tests := []struct {
321+
name string
322+
language string
323+
template string
324+
errContains string
325+
}{
326+
{
327+
name: "browser-use not available for typescript",
328+
language: create.LanguageTypeScript,
329+
template: create.TemplateBrowserUse,
330+
errContains: "template not found: typescript/browser-use",
331+
},
332+
{
333+
name: "stagehand not available for python",
334+
language: create.LanguagePython,
335+
template: create.TemplateStagehand,
336+
errContains: "template not found: python/stagehand",
337+
},
338+
{
339+
name: "magnitude not available for python",
340+
language: create.LanguagePython,
341+
template: create.TemplateMagnitude,
342+
errContains: "template not found: python/magnitude",
343+
},
344+
{
345+
name: "gemini-cua not available for python",
346+
language: create.LanguagePython,
347+
template: create.TemplateGeminiCUA,
348+
errContains: "template not found: python/gemini-cua",
349+
},
350+
{
351+
name: "invalid language",
352+
language: "ruby",
353+
template: create.TemplateSampleApp,
354+
errContains: "template not found: ruby/sample-app",
355+
},
356+
{
357+
name: "invalid template",
358+
language: create.LanguageTypeScript,
359+
template: "nonexistent-template",
360+
errContains: "template not found: typescript/nonexistent-template",
361+
},
362+
}
363+
364+
for _, tt := range tests {
365+
t.Run(tt.name, func(t *testing.T) {
366+
tmpDir := t.TempDir()
367+
368+
orgDir, err := os.Getwd()
369+
require.NoError(t, err)
370+
371+
err = os.Chdir(tmpDir)
372+
require.NoError(t, err)
373+
374+
t.Cleanup(func() {
375+
os.Chdir(orgDir)
376+
})
377+
378+
c := CreateCmd{}
379+
err = c.Create(context.Background(), CreateInput{
380+
Name: "test-app",
381+
Language: tt.language,
382+
Template: tt.template,
383+
})
384+
385+
require.Error(t, err, "should fail with invalid language/template combination")
386+
assert.Contains(t, err.Error(), tt.errContains, "error message should contain expected text")
387+
})
388+
}
389+
}
390+
391+
// TestCreateCommand_ValidateAllTemplateCombinations validates that only valid
392+
// language/template combinations are defined in the Templates map
393+
func TestCreateCommand_ValidateAllTemplateCombinations(t *testing.T) {
394+
// This test ensures data consistency between Templates and actual template availability
395+
for templateKey, templateInfo := range create.Templates {
396+
for _, lang := range templateInfo.Languages {
397+
t.Run(lang+"/"+templateKey, func(t *testing.T) {
398+
tmpDir := t.TempDir()
399+
appPath := filepath.Join(tmpDir, "test-app")
400+
401+
err := os.MkdirAll(appPath, DIR_PERM)
402+
require.NoError(t, err)
403+
404+
// This should succeed for all combinations defined in Templates
405+
err = create.CopyTemplateFiles(appPath, lang, templateKey)
406+
require.NoError(t, err, "Template %s should be available for language %s as defined in Templates map", templateKey, lang)
407+
})
408+
}
409+
}
410+
}
411+
412+
// TestCreateCommand_InvalidLanguageShorthand tests that invalid language shorthands
413+
// are handled appropriately
414+
func TestCreateCommand_InvalidLanguageShorthand(t *testing.T) {
415+
tests := []struct {
416+
name string
417+
languageInput string
418+
expectedNormalized string
419+
}{
420+
{
421+
name: "ts shorthand normalizes to typescript",
422+
languageInput: "ts",
423+
expectedNormalized: create.LanguageTypeScript,
424+
},
425+
{
426+
name: "py shorthand normalizes to python",
427+
languageInput: "py",
428+
expectedNormalized: create.LanguagePython,
429+
},
430+
{
431+
name: "typescript remains typescript",
432+
languageInput: "typescript",
433+
expectedNormalized: create.LanguageTypeScript,
434+
},
435+
{
436+
name: "python remains python",
437+
languageInput: "python",
438+
expectedNormalized: create.LanguagePython,
439+
},
440+
{
441+
name: "invalid shorthand remains unchanged",
442+
languageInput: "js",
443+
expectedNormalized: "js",
444+
},
445+
}
446+
447+
for _, tt := range tests {
448+
t.Run(tt.name, func(t *testing.T) {
449+
normalized := create.NormalizeLanguage(tt.languageInput)
450+
assert.Equal(t, tt.expectedNormalized, normalized)
451+
})
452+
}
453+
}
454+
455+
// TestCreateCommand_TemplateNotAvailableForLanguage tests specific cases where
456+
// templates are not available for certain languages
457+
func TestCreateCommand_TemplateNotAvailableForLanguage(t *testing.T) {
458+
// Map of templates to languages they should NOT be available for
459+
unavailableCombinations := map[string][]string{
460+
create.TemplateBrowserUse: {create.LanguageTypeScript},
461+
create.TemplateStagehand: {create.LanguagePython},
462+
create.TemplateMagnitude: {create.LanguagePython},
463+
create.TemplateGeminiCUA: {create.LanguagePython},
464+
}
465+
466+
for template, unavailableLanguages := range unavailableCombinations {
467+
for _, lang := range unavailableLanguages {
468+
t.Run(template+"/"+lang, func(t *testing.T) {
469+
// Verify the template info doesn't list this language
470+
templateInfo, exists := create.Templates[template]
471+
require.True(t, exists, "Template %s should exist in Templates map", template)
472+
473+
assert.NotContains(t, templateInfo.Languages, lang,
474+
"Template %s should not list %s as a supported language", template, lang)
475+
476+
// Verify copying fails
477+
tmpDir := t.TempDir()
478+
appPath := filepath.Join(tmpDir, "test-app")
479+
err := os.MkdirAll(appPath, DIR_PERM)
480+
require.NoError(t, err)
481+
482+
err = create.CopyTemplateFiles(appPath, lang, template)
483+
require.Error(t, err, "Should fail to copy %s template for %s", template, lang)
484+
})
485+
}
486+
}
487+
}
488+
489+
// TestCreateCommand_AllTemplatesHaveDeployCommands ensures that all templates
490+
// have corresponding deploy commands defined
491+
func TestCreateCommand_AllTemplatesHaveDeployCommands(t *testing.T) {
492+
for templateKey, templateInfo := range create.Templates {
493+
for _, lang := range templateInfo.Languages {
494+
t.Run(lang+"/"+templateKey, func(t *testing.T) {
495+
deployCmd := create.GetDeployCommand(lang, templateKey)
496+
assert.NotEmpty(t, deployCmd, "Deploy command should exist for %s/%s", lang, templateKey)
497+
498+
// Verify deploy command starts with "kernel deploy"
499+
assert.Contains(t, deployCmd, "kernel deploy", "Deploy command should start with 'kernel deploy'")
500+
501+
// Verify it contains the entry point
502+
switch lang {
503+
case create.LanguageTypeScript:
504+
assert.Contains(t, deployCmd, "index.ts", "TypeScript deploy command should contain index.ts")
505+
case create.LanguagePython:
506+
assert.Contains(t, deployCmd, "main.py", "Python deploy command should contain main.py")
507+
}
508+
})
509+
}
510+
}
511+
}
512+
513+
// TestCreateCommand_AllTemplatesHaveInvokeSamples ensures that all templates
514+
// have corresponding invoke samples defined
515+
func TestCreateCommand_AllTemplatesHaveInvokeSamples(t *testing.T) {
516+
for templateKey, templateInfo := range create.Templates {
517+
for _, lang := range templateInfo.Languages {
518+
t.Run(lang+"/"+templateKey, func(t *testing.T) {
519+
invokeCmd := create.GetInvokeSample(lang, templateKey)
520+
assert.NotEmpty(t, invokeCmd, "Invoke sample should exist for %s/%s", lang, templateKey)
521+
522+
// Verify invoke command starts with "kernel invoke"
523+
assert.Contains(t, invokeCmd, "kernel invoke", "Invoke command should start with 'kernel invoke'")
524+
})
525+
}
526+
}
527+
}
528+
317529
func getTemplateInfo() []struct {
318530
name string
319531
language string

0 commit comments

Comments
 (0)