|
4 | 4 | "encoding/json" |
5 | 5 | "os" |
6 | 6 | "path/filepath" |
| 7 | + "regexp" |
| 8 | + "strings" |
7 | 9 | "testing" |
8 | 10 | ) |
9 | 11 |
|
@@ -656,3 +658,59 @@ func TestInitializer_OpenCode_FullRun(t *testing.T) { |
656 | 658 | t.Error("Plugin not created") |
657 | 659 | } |
658 | 660 | } |
| 661 | + |
| 662 | +// TestInitializer_GenerateTwBrief tests that tw-brief skill is generated with correct content |
| 663 | +func TestInitializer_GenerateTwBrief(t *testing.T) { |
| 664 | + tmpDir := t.TempDir() |
| 665 | + init := NewInitializer(tmpDir) |
| 666 | + |
| 667 | + // Run initialization with opencode |
| 668 | + err := init.Run(false, []string{"opencode"}) |
| 669 | + if err != nil { |
| 670 | + t.Fatalf("Run failed: %v", err) |
| 671 | + } |
| 672 | + |
| 673 | + // Verify tw-brief skill exists |
| 674 | + skillPath := filepath.Join(tmpDir, ".opencode", "skills", "tw-brief", "SKILL.md") |
| 675 | + content, err := os.ReadFile(skillPath) |
| 676 | + if err != nil { |
| 677 | + t.Fatalf("Failed to read tw-brief SKILL.md: %v", err) |
| 678 | + } |
| 679 | + |
| 680 | + contentStr := string(content) |
| 681 | + |
| 682 | + // Verify frontmatter structure |
| 683 | + if !strings.HasPrefix(contentStr, "---\n") { |
| 684 | + t.Error("SKILL.md missing frontmatter start marker") |
| 685 | + } |
| 686 | + |
| 687 | + // Verify required frontmatter fields |
| 688 | + if !strings.Contains(contentStr, "name: tw-brief") { |
| 689 | + t.Error("SKILL.md missing 'name: tw-brief' field") |
| 690 | + } |
| 691 | + if !strings.Contains(contentStr, "description:") { |
| 692 | + t.Error("SKILL.md missing 'description' field") |
| 693 | + } |
| 694 | + |
| 695 | + // Verify description mentions project knowledge or brief |
| 696 | + if !strings.Contains(strings.ToLower(contentStr), "brief") && !strings.Contains(strings.ToLower(contentStr), "knowledge") { |
| 697 | + t.Error("SKILL.md description should mention 'brief' or 'knowledge'") |
| 698 | + } |
| 699 | + |
| 700 | + // Verify the skill invokes taskwing slash command |
| 701 | + if !strings.Contains(contentStr, "!taskwing slash brief") { |
| 702 | + t.Error("SKILL.md should contain '!taskwing slash brief' directive") |
| 703 | + } |
| 704 | + |
| 705 | + // Verify directory name matches frontmatter name (skill naming convention) |
| 706 | + dirName := filepath.Base(filepath.Dir(skillPath)) |
| 707 | + if dirName != "tw-brief" { |
| 708 | + t.Errorf("Directory name %q doesn't match skill name 'tw-brief'", dirName) |
| 709 | + } |
| 710 | + |
| 711 | + // Verify name matches regex pattern: ^[a-z0-9]+(-[a-z0-9]+)*$ |
| 712 | + namePattern := regexp.MustCompile(`^[a-z0-9]+(-[a-z0-9]+)*$`) |
| 713 | + if !namePattern.MatchString("tw-brief") { |
| 714 | + t.Error("Skill name 'tw-brief' doesn't match required pattern") |
| 715 | + } |
| 716 | +} |
0 commit comments