/internal/importer/importer_test.go: remove skipped tests
This commit is contained in:
@@ -153,10 +153,10 @@ func TestFieldComparator_StringConversion(t *testing.T) {
|
|||||||
fc := newFieldComparator()
|
fc := newFieldComparator()
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
value interface{}
|
value interface{}
|
||||||
wantStr string
|
wantStr string
|
||||||
wantOk bool
|
wantOk bool
|
||||||
}{
|
}{
|
||||||
{"string", "hello", "hello", true},
|
{"string", "hello", "hello", true},
|
||||||
{"string pointer", stringPtr("world"), "world", true},
|
{"string pointer", stringPtr("world"), "world", true},
|
||||||
@@ -436,67 +436,67 @@ func TestRenameImportedIssuePrefixes(t *testing.T) {
|
|||||||
|
|
||||||
func TestReplaceBoundaryAware(t *testing.T) {
|
func TestReplaceBoundaryAware(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
text string
|
text string
|
||||||
oldID string
|
oldID string
|
||||||
newID string
|
newID string
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "simple replacement",
|
name: "simple replacement",
|
||||||
text: "See old-1 for details",
|
text: "See old-1 for details",
|
||||||
oldID: "old-1",
|
oldID: "old-1",
|
||||||
newID: "new-1",
|
newID: "new-1",
|
||||||
want: "See new-1 for details",
|
want: "See new-1 for details",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple occurrences",
|
name: "multiple occurrences",
|
||||||
text: "old-1 and old-1 again",
|
text: "old-1 and old-1 again",
|
||||||
oldID: "old-1",
|
oldID: "old-1",
|
||||||
newID: "new-1",
|
newID: "new-1",
|
||||||
want: "new-1 and new-1 again",
|
want: "new-1 and new-1 again",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no match substring prefix",
|
name: "no match substring prefix",
|
||||||
text: "old-10 should not match",
|
text: "old-10 should not match",
|
||||||
oldID: "old-1",
|
oldID: "old-1",
|
||||||
newID: "new-1",
|
newID: "new-1",
|
||||||
want: "old-10 should not match",
|
want: "old-10 should not match",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "match at end of longer ID",
|
name: "match at end of longer ID",
|
||||||
text: "should not match old-1 at end",
|
text: "should not match old-1 at end",
|
||||||
oldID: "old-1",
|
oldID: "old-1",
|
||||||
newID: "new-1",
|
newID: "new-1",
|
||||||
want: "should not match new-1 at end",
|
want: "should not match new-1 at end",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "boundary at start",
|
name: "boundary at start",
|
||||||
text: "old-1 starts here",
|
text: "old-1 starts here",
|
||||||
oldID: "old-1",
|
oldID: "old-1",
|
||||||
newID: "new-1",
|
newID: "new-1",
|
||||||
want: "new-1 starts here",
|
want: "new-1 starts here",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "boundary at end",
|
name: "boundary at end",
|
||||||
text: "ends with old-1",
|
text: "ends with old-1",
|
||||||
oldID: "old-1",
|
oldID: "old-1",
|
||||||
newID: "new-1",
|
newID: "new-1",
|
||||||
want: "ends with new-1",
|
want: "ends with new-1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "boundary punctuation",
|
name: "boundary punctuation",
|
||||||
text: "See (old-1) and [old-1] or {old-1}",
|
text: "See (old-1) and [old-1] or {old-1}",
|
||||||
oldID: "old-1",
|
oldID: "old-1",
|
||||||
newID: "new-1",
|
newID: "new-1",
|
||||||
want: "See (new-1) and [new-1] or {new-1}",
|
want: "See (new-1) and [new-1] or {new-1}",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no occurrence",
|
name: "no occurrence",
|
||||||
text: "No match here",
|
text: "No match here",
|
||||||
oldID: "old-1",
|
oldID: "old-1",
|
||||||
newID: "new-1",
|
newID: "new-1",
|
||||||
want: "No match here",
|
want: "No match here",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,9 +547,9 @@ func TestIsValidIDSuffix(t *testing.T) {
|
|||||||
{"abc.1.2.3", true},
|
{"abc.1.2.3", true},
|
||||||
{"1.5", true},
|
{"1.5", true},
|
||||||
// Invalid suffixes
|
// Invalid suffixes
|
||||||
{"", false}, // Empty string
|
{"", false}, // Empty string
|
||||||
{"A3F8", false}, // Uppercase not allowed
|
{"A3F8", false}, // Uppercase not allowed
|
||||||
{"@#$!", false}, // Special characters not allowed
|
{"@#$!", false}, // Special characters not allowed
|
||||||
{"abc-def", false}, // Hyphens not allowed in suffix
|
{"abc-def", false}, // Hyphens not allowed in suffix
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -569,7 +569,7 @@ func stringPtr(s string) *string {
|
|||||||
|
|
||||||
func TestImportIssues_Basic(t *testing.T) {
|
func TestImportIssues_Basic(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// Create temp database
|
// Create temp database
|
||||||
tmpDB := t.TempDir() + "/test.db"
|
tmpDB := t.TempDir() + "/test.db"
|
||||||
store, err := sqlite.New(context.Background(), tmpDB)
|
store, err := sqlite.New(context.Background(), tmpDB)
|
||||||
@@ -577,12 +577,12 @@ func TestImportIssues_Basic(t *testing.T) {
|
|||||||
t.Fatalf("Failed to create store: %v", err)
|
t.Fatalf("Failed to create store: %v", err)
|
||||||
}
|
}
|
||||||
defer store.Close()
|
defer store.Close()
|
||||||
|
|
||||||
// Set config prefix
|
// Set config prefix
|
||||||
if err := store.SetConfig(ctx, "issue_prefix", "test"); err != nil {
|
if err := store.SetConfig(ctx, "issue_prefix", "test"); err != nil {
|
||||||
t.Fatalf("Failed to set prefix: %v", err)
|
t.Fatalf("Failed to set prefix: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import single issue
|
// Import single issue
|
||||||
issues := []*types.Issue{
|
issues := []*types.Issue{
|
||||||
{
|
{
|
||||||
@@ -594,16 +594,16 @@ func TestImportIssues_Basic(t *testing.T) {
|
|||||||
IssueType: types.TypeTask,
|
IssueType: types.TypeTask,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := ImportIssues(ctx, tmpDB, store, issues, Options{})
|
result, err := ImportIssues(ctx, tmpDB, store, issues, Options{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Import failed: %v", err)
|
t.Fatalf("Import failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.Created != 1 {
|
if result.Created != 1 {
|
||||||
t.Errorf("Expected 1 created, got %d", result.Created)
|
t.Errorf("Expected 1 created, got %d", result.Created)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify issue was created
|
// Verify issue was created
|
||||||
retrieved, err := store.GetIssue(ctx, "test-abc123")
|
retrieved, err := store.GetIssue(ctx, "test-abc123")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -616,18 +616,18 @@ func TestImportIssues_Basic(t *testing.T) {
|
|||||||
|
|
||||||
func TestImportIssues_Update(t *testing.T) {
|
func TestImportIssues_Update(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
tmpDB := t.TempDir() + "/test.db"
|
tmpDB := t.TempDir() + "/test.db"
|
||||||
store, err := sqlite.New(context.Background(), tmpDB)
|
store, err := sqlite.New(context.Background(), tmpDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create store: %v", err)
|
t.Fatalf("Failed to create store: %v", err)
|
||||||
}
|
}
|
||||||
defer store.Close()
|
defer store.Close()
|
||||||
|
|
||||||
if err := store.SetConfig(ctx, "issue_prefix", "test"); err != nil {
|
if err := store.SetConfig(ctx, "issue_prefix", "test"); err != nil {
|
||||||
t.Fatalf("Failed to set prefix: %v", err)
|
t.Fatalf("Failed to set prefix: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create initial issue
|
// Create initial issue
|
||||||
issue1 := &types.Issue{
|
issue1 := &types.Issue{
|
||||||
ID: "test-abc123",
|
ID: "test-abc123",
|
||||||
@@ -638,12 +638,12 @@ func TestImportIssues_Update(t *testing.T) {
|
|||||||
IssueType: types.TypeTask,
|
IssueType: types.TypeTask,
|
||||||
}
|
}
|
||||||
issue1.ContentHash = issue1.ComputeContentHash()
|
issue1.ContentHash = issue1.ComputeContentHash()
|
||||||
|
|
||||||
err = store.CreateIssue(ctx, issue1, "test")
|
err = store.CreateIssue(ctx, issue1, "test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create initial issue: %v", err)
|
t.Fatalf("Failed to create initial issue: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import updated version with newer timestamp
|
// Import updated version with newer timestamp
|
||||||
issue2 := &types.Issue{
|
issue2 := &types.Issue{
|
||||||
ID: "test-abc123",
|
ID: "test-abc123",
|
||||||
@@ -656,18 +656,18 @@ func TestImportIssues_Update(t *testing.T) {
|
|||||||
UpdatedAt: time.Now().Add(time.Hour), // Newer than issue1
|
UpdatedAt: time.Now().Add(time.Hour), // Newer than issue1
|
||||||
}
|
}
|
||||||
issue2.ContentHash = issue2.ComputeContentHash()
|
issue2.ContentHash = issue2.ComputeContentHash()
|
||||||
|
|
||||||
result, err := ImportIssues(ctx, tmpDB, store, []*types.Issue{issue2}, Options{})
|
result, err := ImportIssues(ctx, tmpDB, store, []*types.Issue{issue2}, Options{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Import failed: %v", err)
|
t.Fatalf("Import failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The importer detects this as both a collision (1) and then upserts it (creates=1)
|
// The importer detects this as both a collision (1) and then upserts it (creates=1)
|
||||||
// Total updates = collision count + actual upserts
|
// Total updates = collision count + actual upserts
|
||||||
if result.Updated == 0 && result.Created == 0 {
|
if result.Updated == 0 && result.Created == 0 {
|
||||||
t.Error("Expected some updates or creates")
|
t.Error("Expected some updates or creates")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify update
|
// Verify update
|
||||||
retrieved, err := store.GetIssue(ctx, "test-abc123")
|
retrieved, err := store.GetIssue(ctx, "test-abc123")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -680,18 +680,18 @@ func TestImportIssues_Update(t *testing.T) {
|
|||||||
|
|
||||||
func TestImportIssues_DryRun(t *testing.T) {
|
func TestImportIssues_DryRun(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
tmpDB := t.TempDir() + "/test.db"
|
tmpDB := t.TempDir() + "/test.db"
|
||||||
store, err := sqlite.New(context.Background(), tmpDB)
|
store, err := sqlite.New(context.Background(), tmpDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create store: %v", err)
|
t.Fatalf("Failed to create store: %v", err)
|
||||||
}
|
}
|
||||||
defer store.Close()
|
defer store.Close()
|
||||||
|
|
||||||
if err := store.SetConfig(ctx, "issue_prefix", "test"); err != nil {
|
if err := store.SetConfig(ctx, "issue_prefix", "test"); err != nil {
|
||||||
t.Fatalf("Failed to set prefix: %v", err)
|
t.Fatalf("Failed to set prefix: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
issues := []*types.Issue{
|
issues := []*types.Issue{
|
||||||
{
|
{
|
||||||
ID: "test-abc123",
|
ID: "test-abc123",
|
||||||
@@ -701,13 +701,13 @@ func TestImportIssues_DryRun(t *testing.T) {
|
|||||||
IssueType: types.TypeTask,
|
IssueType: types.TypeTask,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dry run returns early when no collisions, so it reports what would be created
|
// Dry run returns early when no collisions, so it reports what would be created
|
||||||
result, err := ImportIssues(ctx, tmpDB, store, issues, Options{DryRun: true})
|
result, err := ImportIssues(ctx, tmpDB, store, issues, Options{DryRun: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Import failed: %v", err)
|
t.Fatalf("Import failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should report that 1 issue would be created
|
// Should report that 1 issue would be created
|
||||||
if result.Created != 1 {
|
if result.Created != 1 {
|
||||||
t.Errorf("Expected 1 would be created in dry run, got %d", result.Created)
|
t.Errorf("Expected 1 would be created in dry run, got %d", result.Created)
|
||||||
@@ -716,18 +716,18 @@ func TestImportIssues_DryRun(t *testing.T) {
|
|||||||
|
|
||||||
func TestImportIssues_Dependencies(t *testing.T) {
|
func TestImportIssues_Dependencies(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
tmpDB := t.TempDir() + "/test.db"
|
tmpDB := t.TempDir() + "/test.db"
|
||||||
store, err := sqlite.New(context.Background(), tmpDB)
|
store, err := sqlite.New(context.Background(), tmpDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create store: %v", err)
|
t.Fatalf("Failed to create store: %v", err)
|
||||||
}
|
}
|
||||||
defer store.Close()
|
defer store.Close()
|
||||||
|
|
||||||
if err := store.SetConfig(ctx, "issue_prefix", "test"); err != nil {
|
if err := store.SetConfig(ctx, "issue_prefix", "test"); err != nil {
|
||||||
t.Fatalf("Failed to set prefix: %v", err)
|
t.Fatalf("Failed to set prefix: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
issues := []*types.Issue{
|
issues := []*types.Issue{
|
||||||
{
|
{
|
||||||
ID: "test-abc123",
|
ID: "test-abc123",
|
||||||
@@ -747,16 +747,16 @@ func TestImportIssues_Dependencies(t *testing.T) {
|
|||||||
IssueType: types.TypeTask,
|
IssueType: types.TypeTask,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := ImportIssues(ctx, tmpDB, store, issues, Options{})
|
result, err := ImportIssues(ctx, tmpDB, store, issues, Options{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Import failed: %v", err)
|
t.Fatalf("Import failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.Created != 2 {
|
if result.Created != 2 {
|
||||||
t.Errorf("Expected 2 created, got %d", result.Created)
|
t.Errorf("Expected 2 created, got %d", result.Created)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify dependency was created
|
// Verify dependency was created
|
||||||
deps, err := store.GetDependencies(ctx, "test-abc123")
|
deps, err := store.GetDependencies(ctx, "test-abc123")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -769,18 +769,18 @@ func TestImportIssues_Dependencies(t *testing.T) {
|
|||||||
|
|
||||||
func TestImportIssues_Labels(t *testing.T) {
|
func TestImportIssues_Labels(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
tmpDB := t.TempDir() + "/test.db"
|
tmpDB := t.TempDir() + "/test.db"
|
||||||
store, err := sqlite.New(context.Background(), tmpDB)
|
store, err := sqlite.New(context.Background(), tmpDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create store: %v", err)
|
t.Fatalf("Failed to create store: %v", err)
|
||||||
}
|
}
|
||||||
defer store.Close()
|
defer store.Close()
|
||||||
|
|
||||||
if err := store.SetConfig(ctx, "issue_prefix", "test"); err != nil {
|
if err := store.SetConfig(ctx, "issue_prefix", "test"); err != nil {
|
||||||
t.Fatalf("Failed to set prefix: %v", err)
|
t.Fatalf("Failed to set prefix: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
issues := []*types.Issue{
|
issues := []*types.Issue{
|
||||||
{
|
{
|
||||||
ID: "test-abc123",
|
ID: "test-abc123",
|
||||||
@@ -791,16 +791,16 @@ func TestImportIssues_Labels(t *testing.T) {
|
|||||||
Labels: []string{"bug", "critical"},
|
Labels: []string{"bug", "critical"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := ImportIssues(ctx, tmpDB, store, issues, Options{})
|
result, err := ImportIssues(ctx, tmpDB, store, issues, Options{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Import failed: %v", err)
|
t.Fatalf("Import failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.Created != 1 {
|
if result.Created != 1 {
|
||||||
t.Errorf("Expected 1 created, got %d", result.Created)
|
t.Errorf("Expected 1 created, got %d", result.Created)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify labels were created
|
// Verify labels were created
|
||||||
retrieved, err := store.GetIssue(ctx, "test-abc123")
|
retrieved, err := store.GetIssue(ctx, "test-abc123")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -811,17 +811,7 @@ func TestImportIssues_Labels(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetOrCreateStore_ExistingStore(t *testing.T) {
|
// NOTE: getOrCreateStore was removed; importer now requires an initialized store.
|
||||||
t.Skip("getOrCreateStore removed: importer now requires a store")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetOrCreateStore_NewStore(t *testing.T) {
|
|
||||||
t.Skip("getOrCreateStore removed: importer now requires a store")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetOrCreateStore_EmptyPath(t *testing.T) {
|
|
||||||
t.Skip("getOrCreateStore removed: importer now requires a store")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestImportIssues_RequiresStore(t *testing.T) {
|
func TestImportIssues_RequiresStore(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
@@ -853,7 +843,7 @@ func TestGetPrefixList(t *testing.T) {
|
|||||||
want: []string{},
|
want: []string{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
got := GetPrefixList(tt.prefixes)
|
got := GetPrefixList(tt.prefixes)
|
||||||
@@ -972,7 +962,7 @@ func TestValidateNoDuplicateExternalRefs(t *testing.T) {
|
|||||||
|
|
||||||
func TestConcurrentExternalRefImports(t *testing.T) {
|
func TestConcurrentExternalRefImports(t *testing.T) {
|
||||||
t.Skip("TODO(bd-gpe7): Test hangs due to database deadlock - needs investigation")
|
t.Skip("TODO(bd-gpe7): Test hangs due to database deadlock - needs investigation")
|
||||||
|
|
||||||
t.Run("sequential imports with same external_ref are detected as updates", func(t *testing.T) {
|
t.Run("sequential imports with same external_ref are detected as updates", func(t *testing.T) {
|
||||||
store, err := sqlite.New(context.Background(), ":memory:")
|
store, err := sqlite.New(context.Background(), ":memory:")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -986,7 +976,7 @@ func TestConcurrentExternalRefImports(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
externalRef := "JIRA-100"
|
externalRef := "JIRA-100"
|
||||||
|
|
||||||
issue1 := &types.Issue{
|
issue1 := &types.Issue{
|
||||||
ID: "bd-1",
|
ID: "bd-1",
|
||||||
Title: "First import",
|
Title: "First import",
|
||||||
@@ -1144,7 +1134,7 @@ func TestImportOrphanSkip_CountMismatch(t *testing.T) {
|
|||||||
UpdatedAt: now,
|
UpdatedAt: now,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: "test-orphan.1", // Child of non-existent parent
|
ID: "test-orphan.1", // Child of non-existent parent
|
||||||
Title: "Orphaned Child",
|
Title: "Orphaned Child",
|
||||||
Status: types.StatusOpen,
|
Status: types.StatusOpen,
|
||||||
Priority: 2,
|
Priority: 2,
|
||||||
|
|||||||
Reference in New Issue
Block a user