test(linear): add comprehensive tests for mapping and client functions
Added tests for: - DefaultMappingConfig - PriorityToBeads/PriorityToLinear - StateToBeadsStatus/ParseBeadsStatus - StatusToLinearStateType - LabelToIssueType/ParseIssueType - RelationToBeadsDep - IssueToBeads (with parent/child handling) - BuildLinearToLocalUpdates - LoadMappingConfig - BuildLinearDescription - NewClient/WithEndpoint/WithHTTPClient - ExtractLinearIdentifier - IsLinearExternalRef Linear package coverage improved from 14.3% to ~50%. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
package linear
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCanonicalizeLinearExternalRef(t *testing.T) {
|
||||
tests := []struct {
|
||||
@@ -39,3 +43,130 @@ func TestCanonicalizeLinearExternalRef(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
client := NewClient("test-api-key", "test-team-id")
|
||||
|
||||
if client.APIKey != "test-api-key" {
|
||||
t.Errorf("APIKey = %q, want %q", client.APIKey, "test-api-key")
|
||||
}
|
||||
if client.TeamID != "test-team-id" {
|
||||
t.Errorf("TeamID = %q, want %q", client.TeamID, "test-team-id")
|
||||
}
|
||||
if client.Endpoint != DefaultAPIEndpoint {
|
||||
t.Errorf("Endpoint = %q, want %q", client.Endpoint, DefaultAPIEndpoint)
|
||||
}
|
||||
if client.HTTPClient == nil {
|
||||
t.Error("HTTPClient should not be nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithEndpoint(t *testing.T) {
|
||||
client := NewClient("key", "team")
|
||||
customEndpoint := "https://custom.linear.app/graphql"
|
||||
|
||||
newClient := client.WithEndpoint(customEndpoint)
|
||||
|
||||
if newClient.Endpoint != customEndpoint {
|
||||
t.Errorf("Endpoint = %q, want %q", newClient.Endpoint, customEndpoint)
|
||||
}
|
||||
// Original should be unchanged
|
||||
if client.Endpoint != DefaultAPIEndpoint {
|
||||
t.Errorf("Original endpoint changed: %q", client.Endpoint)
|
||||
}
|
||||
// Other fields preserved
|
||||
if newClient.APIKey != "key" {
|
||||
t.Errorf("APIKey not preserved: %q", newClient.APIKey)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithHTTPClient(t *testing.T) {
|
||||
client := NewClient("key", "team")
|
||||
customHTTPClient := &http.Client{Timeout: 60 * time.Second}
|
||||
|
||||
newClient := client.WithHTTPClient(customHTTPClient)
|
||||
|
||||
if newClient.HTTPClient != customHTTPClient {
|
||||
t.Error("HTTPClient not set correctly")
|
||||
}
|
||||
// Other fields preserved
|
||||
if newClient.APIKey != "key" {
|
||||
t.Errorf("APIKey not preserved: %q", newClient.APIKey)
|
||||
}
|
||||
if newClient.Endpoint != DefaultAPIEndpoint {
|
||||
t.Errorf("Endpoint not preserved: %q", newClient.Endpoint)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractLinearIdentifier(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
externalRef string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "standard URL",
|
||||
externalRef: "https://linear.app/team/issue/PROJ-123",
|
||||
want: "PROJ-123",
|
||||
},
|
||||
{
|
||||
name: "URL with slug",
|
||||
externalRef: "https://linear.app/team/issue/PROJ-456/some-title-here",
|
||||
want: "PROJ-456",
|
||||
},
|
||||
{
|
||||
name: "URL with trailing slash",
|
||||
externalRef: "https://linear.app/team/issue/ABC-789/",
|
||||
want: "ABC-789",
|
||||
},
|
||||
{
|
||||
name: "non-linear URL",
|
||||
externalRef: "https://jira.example.com/browse/PROJ-123",
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "empty string",
|
||||
externalRef: "",
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "malformed URL",
|
||||
externalRef: "not-a-url",
|
||||
want: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := ExtractLinearIdentifier(tt.externalRef)
|
||||
if got != tt.want {
|
||||
t.Errorf("ExtractLinearIdentifier(%q) = %q, want %q", tt.externalRef, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsLinearExternalRef(t *testing.T) {
|
||||
tests := []struct {
|
||||
ref string
|
||||
want bool
|
||||
}{
|
||||
{"https://linear.app/team/issue/PROJ-123", true},
|
||||
{"https://linear.app/team/issue/PROJ-123/slug", true},
|
||||
{"https://jira.example.com/browse/PROJ-123", false},
|
||||
{"https://github.com/org/repo/issues/123", false},
|
||||
{"", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.ref, func(t *testing.T) {
|
||||
got := IsLinearExternalRef(tt.ref)
|
||||
if got != tt.want {
|
||||
t.Errorf("IsLinearExternalRef(%q) = %v, want %v", tt.ref, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Note: BuildStateCache and FindStateForBeadsStatus require API calls
|
||||
// and would need mocking to test. Skipping unit tests for those.
|
||||
|
||||
@@ -142,3 +142,460 @@ func TestNormalizeIssueForLinearHashCanonicalizesExternalRef(t *testing.T) {
|
||||
func hasPrefix(s, prefix string) bool {
|
||||
return len(s) >= len(prefix) && s[:len(prefix)] == prefix
|
||||
}
|
||||
|
||||
func TestDefaultMappingConfig(t *testing.T) {
|
||||
config := DefaultMappingConfig()
|
||||
|
||||
// Check priority mappings
|
||||
if config.PriorityMap["0"] != 4 {
|
||||
t.Errorf("PriorityMap[0] = %d, want 4", config.PriorityMap["0"])
|
||||
}
|
||||
if config.PriorityMap["1"] != 0 {
|
||||
t.Errorf("PriorityMap[1] = %d, want 0", config.PriorityMap["1"])
|
||||
}
|
||||
|
||||
// Check state mappings
|
||||
if config.StateMap["backlog"] != "open" {
|
||||
t.Errorf("StateMap[backlog] = %s, want open", config.StateMap["backlog"])
|
||||
}
|
||||
if config.StateMap["started"] != "in_progress" {
|
||||
t.Errorf("StateMap[started] = %s, want in_progress", config.StateMap["started"])
|
||||
}
|
||||
if config.StateMap["completed"] != "closed" {
|
||||
t.Errorf("StateMap[completed] = %s, want closed", config.StateMap["completed"])
|
||||
}
|
||||
|
||||
// Check label type mappings
|
||||
if config.LabelTypeMap["bug"] != "bug" {
|
||||
t.Errorf("LabelTypeMap[bug] = %s, want bug", config.LabelTypeMap["bug"])
|
||||
}
|
||||
if config.LabelTypeMap["feature"] != "feature" {
|
||||
t.Errorf("LabelTypeMap[feature] = %s, want feature", config.LabelTypeMap["feature"])
|
||||
}
|
||||
|
||||
// Check relation mappings
|
||||
if config.RelationMap["blocks"] != "blocks" {
|
||||
t.Errorf("RelationMap[blocks] = %s, want blocks", config.RelationMap["blocks"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityToBeads(t *testing.T) {
|
||||
config := DefaultMappingConfig()
|
||||
|
||||
tests := []struct {
|
||||
linearPriority int
|
||||
want int
|
||||
}{
|
||||
{0, 4}, // No priority -> Backlog
|
||||
{1, 0}, // Urgent -> Critical
|
||||
{2, 1}, // High -> High
|
||||
{3, 2}, // Medium -> Medium
|
||||
{4, 3}, // Low -> Low
|
||||
{5, 2}, // Unknown -> Medium (default)
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := PriorityToBeads(tt.linearPriority, config)
|
||||
if got != tt.want {
|
||||
t.Errorf("PriorityToBeads(%d) = %d, want %d", tt.linearPriority, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityToLinear(t *testing.T) {
|
||||
config := DefaultMappingConfig()
|
||||
|
||||
tests := []struct {
|
||||
beadsPriority int
|
||||
want int
|
||||
}{
|
||||
{0, 1}, // Critical -> Urgent
|
||||
{1, 2}, // High -> High
|
||||
{2, 3}, // Medium -> Medium
|
||||
{3, 4}, // Low -> Low
|
||||
{4, 0}, // Backlog -> No priority
|
||||
{5, 3}, // Unknown -> Medium (default)
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := PriorityToLinear(tt.beadsPriority, config)
|
||||
if got != tt.want {
|
||||
t.Errorf("PriorityToLinear(%d) = %d, want %d", tt.beadsPriority, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStateToBeadsStatus(t *testing.T) {
|
||||
config := DefaultMappingConfig()
|
||||
|
||||
tests := []struct {
|
||||
state *State
|
||||
want types.Status
|
||||
}{
|
||||
{nil, types.StatusOpen},
|
||||
{&State{Type: "backlog", Name: "Backlog"}, types.StatusOpen},
|
||||
{&State{Type: "unstarted", Name: "Todo"}, types.StatusOpen},
|
||||
{&State{Type: "started", Name: "In Progress"}, types.StatusInProgress},
|
||||
{&State{Type: "completed", Name: "Done"}, types.StatusClosed},
|
||||
{&State{Type: "canceled", Name: "Cancelled"}, types.StatusClosed},
|
||||
{&State{Type: "unknown", Name: "Unknown"}, types.StatusOpen}, // Default
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := StateToBeadsStatus(tt.state, config)
|
||||
if got != tt.want {
|
||||
stateName := "nil"
|
||||
if tt.state != nil {
|
||||
stateName = tt.state.Type
|
||||
}
|
||||
t.Errorf("StateToBeadsStatus(%s) = %v, want %v", stateName, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseBeadsStatus(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
want types.Status
|
||||
}{
|
||||
{"open", types.StatusOpen},
|
||||
{"OPEN", types.StatusOpen},
|
||||
{"in_progress", types.StatusInProgress},
|
||||
{"in-progress", types.StatusInProgress},
|
||||
{"inprogress", types.StatusInProgress},
|
||||
{"blocked", types.StatusBlocked},
|
||||
{"closed", types.StatusClosed},
|
||||
{"CLOSED", types.StatusClosed},
|
||||
{"unknown", types.StatusOpen}, // Default
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := ParseBeadsStatus(tt.input)
|
||||
if got != tt.want {
|
||||
t.Errorf("ParseBeadsStatus(%q) = %v, want %v", tt.input, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatusToLinearStateType(t *testing.T) {
|
||||
tests := []struct {
|
||||
status types.Status
|
||||
want string
|
||||
}{
|
||||
{types.StatusOpen, "unstarted"},
|
||||
{types.StatusInProgress, "started"},
|
||||
{types.StatusBlocked, "started"},
|
||||
{types.StatusClosed, "completed"},
|
||||
{types.Status("unknown"), "unstarted"}, // Unknown -> default
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := StatusToLinearStateType(tt.status)
|
||||
if got != tt.want {
|
||||
t.Errorf("StatusToLinearStateType(%v) = %q, want %q", tt.status, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLabelToIssueType(t *testing.T) {
|
||||
config := DefaultMappingConfig()
|
||||
|
||||
tests := []struct {
|
||||
labels *Labels
|
||||
want types.IssueType
|
||||
}{
|
||||
{nil, types.TypeTask},
|
||||
{&Labels{Nodes: []Label{}}, types.TypeTask},
|
||||
{&Labels{Nodes: []Label{{Name: "bug"}}}, types.TypeBug},
|
||||
{&Labels{Nodes: []Label{{Name: "Bug"}}}, types.TypeBug},
|
||||
{&Labels{Nodes: []Label{{Name: "feature"}}}, types.TypeFeature},
|
||||
{&Labels{Nodes: []Label{{Name: "epic"}}}, types.TypeEpic},
|
||||
{&Labels{Nodes: []Label{{Name: "chore"}}}, types.TypeChore},
|
||||
{&Labels{Nodes: []Label{{Name: "random"}, {Name: "bug"}}}, types.TypeBug},
|
||||
{&Labels{Nodes: []Label{{Name: "contains-bug-keyword"}}}, types.TypeBug},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := LabelToIssueType(tt.labels, config)
|
||||
if got != tt.want {
|
||||
t.Errorf("LabelToIssueType(%v) = %v, want %v", tt.labels, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseIssueType(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
want types.IssueType
|
||||
}{
|
||||
{"bug", types.TypeBug},
|
||||
{"BUG", types.TypeBug},
|
||||
{"feature", types.TypeFeature},
|
||||
{"task", types.TypeTask},
|
||||
{"epic", types.TypeEpic},
|
||||
{"chore", types.TypeChore},
|
||||
{"unknown", types.TypeTask}, // Default
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := ParseIssueType(tt.input)
|
||||
if got != tt.want {
|
||||
t.Errorf("ParseIssueType(%q) = %v, want %v", tt.input, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRelationToBeadsDep(t *testing.T) {
|
||||
config := DefaultMappingConfig()
|
||||
|
||||
tests := []struct {
|
||||
relationType string
|
||||
want string
|
||||
}{
|
||||
{"blocks", "blocks"},
|
||||
{"blockedBy", "blocks"},
|
||||
{"duplicate", "duplicates"},
|
||||
{"related", "related"},
|
||||
{"unknown", "related"}, // Default
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := RelationToBeadsDep(tt.relationType, config)
|
||||
if got != tt.want {
|
||||
t.Errorf("RelationToBeadsDep(%q) = %q, want %q", tt.relationType, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssueToBeads(t *testing.T) {
|
||||
config := DefaultMappingConfig()
|
||||
|
||||
linearIssue := &Issue{
|
||||
ID: "uuid-123",
|
||||
Identifier: "PROJ-123",
|
||||
Title: "Test Issue",
|
||||
Description: "Test description",
|
||||
URL: "https://linear.app/team/issue/PROJ-123/test-issue",
|
||||
Priority: 2, // High
|
||||
State: &State{Type: "started", Name: "In Progress"},
|
||||
Assignee: &User{Name: "John Doe", Email: "john@example.com"},
|
||||
Labels: &Labels{Nodes: []Label{{Name: "bug"}}},
|
||||
CreatedAt: "2024-01-15T10:00:00Z",
|
||||
UpdatedAt: "2024-01-16T12:00:00Z",
|
||||
}
|
||||
|
||||
result := IssueToBeads(linearIssue, config)
|
||||
issue := result.Issue.(*types.Issue)
|
||||
|
||||
if issue.Title != "Test Issue" {
|
||||
t.Errorf("Title = %q, want %q", issue.Title, "Test Issue")
|
||||
}
|
||||
if issue.Description != "Test description" {
|
||||
t.Errorf("Description = %q, want %q", issue.Description, "Test description")
|
||||
}
|
||||
if issue.Priority != 1 { // High in beads
|
||||
t.Errorf("Priority = %d, want 1", issue.Priority)
|
||||
}
|
||||
if issue.Status != types.StatusInProgress {
|
||||
t.Errorf("Status = %v, want %v", issue.Status, types.StatusInProgress)
|
||||
}
|
||||
if issue.Assignee != "john@example.com" {
|
||||
t.Errorf("Assignee = %q, want %q", issue.Assignee, "john@example.com")
|
||||
}
|
||||
if issue.IssueType != types.TypeBug {
|
||||
t.Errorf("IssueType = %v, want %v", issue.IssueType, types.TypeBug)
|
||||
}
|
||||
if issue.ExternalRef == nil {
|
||||
t.Error("ExternalRef should not be nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssueToBeadsWithParent(t *testing.T) {
|
||||
config := DefaultMappingConfig()
|
||||
|
||||
linearIssue := &Issue{
|
||||
ID: "uuid-456",
|
||||
Identifier: "PROJ-456",
|
||||
Title: "Child Issue",
|
||||
Description: "Child description",
|
||||
URL: "https://linear.app/team/issue/PROJ-456",
|
||||
Priority: 3,
|
||||
State: &State{Type: "unstarted", Name: "Todo"},
|
||||
Parent: &Parent{ID: "uuid-123", Identifier: "PROJ-123"},
|
||||
CreatedAt: "2024-01-15T10:00:00Z",
|
||||
UpdatedAt: "2024-01-16T12:00:00Z",
|
||||
}
|
||||
|
||||
result := IssueToBeads(linearIssue, config)
|
||||
|
||||
if len(result.Dependencies) != 1 {
|
||||
t.Fatalf("Expected 1 dependency, got %d", len(result.Dependencies))
|
||||
}
|
||||
if result.Dependencies[0].Type != "parent-child" {
|
||||
t.Errorf("Dependency type = %q, want %q", result.Dependencies[0].Type, "parent-child")
|
||||
}
|
||||
if result.Dependencies[0].FromLinearID != "PROJ-456" {
|
||||
t.Errorf("FromLinearID = %q, want %q", result.Dependencies[0].FromLinearID, "PROJ-456")
|
||||
}
|
||||
if result.Dependencies[0].ToLinearID != "PROJ-123" {
|
||||
t.Errorf("ToLinearID = %q, want %q", result.Dependencies[0].ToLinearID, "PROJ-123")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildLinearToLocalUpdates(t *testing.T) {
|
||||
config := DefaultMappingConfig()
|
||||
|
||||
linearIssue := &Issue{
|
||||
ID: "uuid-123",
|
||||
Identifier: "PROJ-123",
|
||||
Title: "Updated Title",
|
||||
Description: "Updated description",
|
||||
Priority: 1, // Urgent
|
||||
State: &State{Type: "completed", Name: "Done"},
|
||||
Assignee: &User{Name: "Jane Doe", Email: "jane@example.com"},
|
||||
Labels: &Labels{Nodes: []Label{{Name: "feature"}, {Name: "priority"}}},
|
||||
UpdatedAt: "2024-01-20T15:00:00Z",
|
||||
CompletedAt: "2024-01-20T14:00:00Z",
|
||||
}
|
||||
|
||||
updates := BuildLinearToLocalUpdates(linearIssue, config)
|
||||
|
||||
if updates["title"] != "Updated Title" {
|
||||
t.Errorf("title = %v, want %q", updates["title"], "Updated Title")
|
||||
}
|
||||
if updates["description"] != "Updated description" {
|
||||
t.Errorf("description = %v, want %q", updates["description"], "Updated description")
|
||||
}
|
||||
if updates["priority"] != 0 { // Critical in beads
|
||||
t.Errorf("priority = %v, want 0", updates["priority"])
|
||||
}
|
||||
if updates["status"] != "closed" {
|
||||
t.Errorf("status = %v, want %q", updates["status"], "closed")
|
||||
}
|
||||
if updates["assignee"] != "jane@example.com" {
|
||||
t.Errorf("assignee = %v, want %q", updates["assignee"], "jane@example.com")
|
||||
}
|
||||
|
||||
labels, ok := updates["labels"].([]string)
|
||||
if !ok || len(labels) != 2 {
|
||||
t.Errorf("labels = %v, want 2 labels", updates["labels"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildLinearToLocalUpdatesNoAssignee(t *testing.T) {
|
||||
config := DefaultMappingConfig()
|
||||
|
||||
linearIssue := &Issue{
|
||||
ID: "uuid-123",
|
||||
Identifier: "PROJ-123",
|
||||
Title: "No Assignee",
|
||||
Description: "Test",
|
||||
Priority: 3,
|
||||
State: &State{Type: "unstarted", Name: "Todo"},
|
||||
Assignee: nil,
|
||||
UpdatedAt: "2024-01-20T15:00:00Z",
|
||||
}
|
||||
|
||||
updates := BuildLinearToLocalUpdates(linearIssue, config)
|
||||
|
||||
if updates["assignee"] != "" {
|
||||
t.Errorf("assignee = %v, want empty string", updates["assignee"])
|
||||
}
|
||||
}
|
||||
|
||||
// mockConfigLoader implements ConfigLoader for testing
|
||||
type mockConfigLoader struct {
|
||||
config map[string]string
|
||||
}
|
||||
|
||||
func (m *mockConfigLoader) GetAllConfig() (map[string]string, error) {
|
||||
return m.config, nil
|
||||
}
|
||||
|
||||
func TestLoadMappingConfig(t *testing.T) {
|
||||
loader := &mockConfigLoader{
|
||||
config: map[string]string{
|
||||
"linear.priority_map.0": "3",
|
||||
"linear.state_map.custom": "in_progress",
|
||||
"linear.label_type_map.story": "feature",
|
||||
"linear.relation_map.parent": "parent-child",
|
||||
},
|
||||
}
|
||||
|
||||
config := LoadMappingConfig(loader)
|
||||
|
||||
// Check custom priority mapping
|
||||
if config.PriorityMap["0"] != 3 {
|
||||
t.Errorf("PriorityMap[0] = %d, want 3", config.PriorityMap["0"])
|
||||
}
|
||||
|
||||
// Check custom state mapping
|
||||
if config.StateMap["custom"] != "in_progress" {
|
||||
t.Errorf("StateMap[custom] = %s, want in_progress", config.StateMap["custom"])
|
||||
}
|
||||
|
||||
// Check custom label type mapping
|
||||
if config.LabelTypeMap["story"] != "feature" {
|
||||
t.Errorf("LabelTypeMap[story] = %s, want feature", config.LabelTypeMap["story"])
|
||||
}
|
||||
|
||||
// Check custom relation mapping
|
||||
if config.RelationMap["parent"] != "parent-child" {
|
||||
t.Errorf("RelationMap[parent] = %s, want parent-child", config.RelationMap["parent"])
|
||||
}
|
||||
|
||||
// Check that defaults are preserved
|
||||
if config.StateMap["started"] != "in_progress" {
|
||||
t.Errorf("StateMap[started] = %s, want in_progress (default preserved)", config.StateMap["started"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadMappingConfigNilLoader(t *testing.T) {
|
||||
config := LoadMappingConfig(nil)
|
||||
|
||||
// Should return defaults
|
||||
if config.PriorityMap["1"] != 0 {
|
||||
t.Errorf("Expected default priority map with nil loader")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildLinearDescription(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
issue *types.Issue
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "description only",
|
||||
issue: &types.Issue{Description: "Basic description"},
|
||||
want: "Basic description",
|
||||
},
|
||||
{
|
||||
name: "with acceptance criteria",
|
||||
issue: &types.Issue{
|
||||
Description: "Main description",
|
||||
AcceptanceCriteria: "- Must do X\n- Must do Y",
|
||||
},
|
||||
want: "Main description\n\n## Acceptance Criteria\n- Must do X\n- Must do Y",
|
||||
},
|
||||
{
|
||||
name: "with all fields",
|
||||
issue: &types.Issue{
|
||||
Description: "Main description",
|
||||
AcceptanceCriteria: "AC here",
|
||||
Design: "Design notes",
|
||||
Notes: "Additional notes",
|
||||
},
|
||||
want: "Main description\n\n## Acceptance Criteria\nAC here\n\n## Design\nDesign notes\n\n## Notes\nAdditional notes",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := BuildLinearDescription(tt.issue)
|
||||
if got != tt.want {
|
||||
t.Errorf("BuildLinearDescription() = %q, want %q", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user