test(handlers): add unit tests for conflict resolution logic

Add table-driven tests for the conflict handler's source selection
methods: GetMostRecentSource, GetHighestProgressSource, and
GetEarliestSource. Covers cases where each device wins, ties, and
missing/invalid data.
This commit is contained in:
2026-04-20 20:43:04 -04:00
parent 77cbbf600b
commit 6820208a36
+309
View File
@@ -0,0 +1,309 @@
package handlers
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestGetMostRecentSource_KOReaderMoreRecent(t *testing.T) {
handler := &ConflictHandler{}
conflictData := map[string]ConflictSourceData{
"koreader": {
Source: "koreader",
Timestamp: time.Date(2026, 1, 30, 20, 10, 0, 0, time.UTC),
Data: map[string]interface{}{
"percentage": 0.45,
"epubcfi": "epubcfi(/6/4/2:15)",
},
},
"kobo": {
Source: "kobo",
Timestamp: time.Date(2026, 1, 30, 20, 5, 0, 0, time.UTC),
Data: map[string]interface{}{
"percentage": 0.42,
"page": float64(89),
},
},
}
source, data := handler.getMostRecentSource(conflictData)
assert.Equal(t, "koreader", source)
assert.Equal(t, 0.45, data["percentage"])
}
func TestGetMostRecentSource_KoboMoreRecent(t *testing.T) {
handler := &ConflictHandler{}
conflictData := map[string]ConflictSourceData{
"koreader": {
Source: "koreader",
Timestamp: time.Date(2026, 1, 30, 20, 5, 0, 0, time.UTC),
Data: map[string]interface{}{
"percentage": 0.45,
},
},
"kobo": {
Source: "kobo",
Timestamp: time.Date(2026, 1, 30, 20, 15, 0, 0, time.UTC),
Data: map[string]interface{}{
"percentage": 0.42,
},
},
}
source, data := handler.getMostRecentSource(conflictData)
assert.Equal(t, "kobo", source)
assert.Equal(t, 0.42, data["percentage"])
}
func TestGetMostRecentSource_SingleSource(t *testing.T) {
handler := &ConflictHandler{}
conflictData := map[string]ConflictSourceData{
"koreader": {
Source: "koreader",
Timestamp: time.Date(2026, 1, 30, 20, 10, 0, 0, time.UTC),
Data: map[string]interface{}{
"percentage": 0.50,
},
},
}
source, data := handler.getMostRecentSource(conflictData)
assert.Equal(t, "koreader", source)
assert.Equal(t, 0.50, data["percentage"])
}
func TestGetMostRecentSource_SameTimestamp(t *testing.T) {
handler := &ConflictHandler{}
ts := time.Date(2026, 1, 30, 20, 10, 0, 0, time.UTC)
conflictData := map[string]ConflictSourceData{
"koreader": {
Source: "koreader",
Timestamp: ts,
Data: map[string]interface{}{
"percentage": 0.45,
},
},
"kobo": {
Source: "kobo",
Timestamp: ts,
Data: map[string]interface{}{
"percentage": 0.42,
},
},
}
source, _ := handler.getMostRecentSource(conflictData)
assert.Contains(t, []string{"koreader", "kobo"}, source)
}
func TestGetMostRecentSource_EmptyData(t *testing.T) {
handler := &ConflictHandler{}
conflictData := map[string]ConflictSourceData{}
source, data := handler.getMostRecentSource(conflictData)
assert.Equal(t, "", source)
assert.Nil(t, data)
}
func TestGetHighestProgressSource_KOReaderHigher(t *testing.T) {
handler := &ConflictHandler{}
conflictData := map[string]ConflictSourceData{
"koreader": {
Source: "koreader",
Data: map[string]interface{}{
"percentage": 0.75,
},
},
"kobo": {
Source: "kobo",
Data: map[string]interface{}{
"percentage": 0.42,
},
},
}
source, data := handler.getHighestProgressSource(conflictData)
assert.Equal(t, "koreader", source)
assert.Equal(t, 0.75, data["percentage"])
}
func TestGetHighestProgressSource_KoboHigher(t *testing.T) {
handler := &ConflictHandler{}
conflictData := map[string]ConflictSourceData{
"koreader": {
Source: "koreader",
Data: map[string]interface{}{
"percentage": 0.30,
},
},
"kobo": {
Source: "kobo",
Data: map[string]interface{}{
"percentage": 0.90,
},
},
}
source, data := handler.getHighestProgressSource(conflictData)
assert.Equal(t, "kobo", source)
assert.Equal(t, 0.90, data["percentage"])
}
func TestGetHighestProgressSource_SingleSource(t *testing.T) {
handler := &ConflictHandler{}
conflictData := map[string]ConflictSourceData{
"koreader": {
Source: "koreader",
Data: map[string]interface{}{
"percentage": 0.50,
},
},
}
source, data := handler.getHighestProgressSource(conflictData)
assert.Equal(t, "koreader", source)
assert.Equal(t, 0.50, data["percentage"])
}
func TestGetHighestProgressSource_EmptyData(t *testing.T) {
handler := &ConflictHandler{}
conflictData := map[string]ConflictSourceData{}
source, data := handler.getHighestProgressSource(conflictData)
assert.Equal(t, "", source)
assert.Nil(t, data)
}
func TestGetHighestProgressSource_NoPercentageField(t *testing.T) {
handler := &ConflictHandler{}
conflictData := map[string]ConflictSourceData{
"koreader": {
Source: "koreader",
Data: map[string]interface{}{},
},
}
source, data := handler.getHighestProgressSource(conflictData)
assert.Equal(t, "", source)
assert.Nil(t, data)
}
func TestGetHighestProgressSource_MixedPercentageTypes(t *testing.T) {
handler := &ConflictHandler{}
conflictData := map[string]ConflictSourceData{
"koreader": {
Source: "koreader",
Data: map[string]interface{}{
"percentage": 0.60,
},
},
"kobo": {
Source: "kobo",
Data: map[string]interface{}{
"percentage": float64(0.80),
},
},
}
source, data := handler.getHighestProgressSource(conflictData)
assert.Equal(t, "kobo", source)
assert.Equal(t, float64(0.80), data["percentage"])
}
func TestGetHighestProgressSource_BothZero(t *testing.T) {
handler := &ConflictHandler{}
conflictData := map[string]ConflictSourceData{
"koreader": {
Source: "koreader",
Data: map[string]interface{}{
"percentage": 0.0,
},
},
"kobo": {
Source: "kobo",
Data: map[string]interface{}{
"percentage": 0.0,
},
},
}
source, data := handler.getHighestProgressSource(conflictData)
assert.NotEmpty(t, source)
assert.NotNil(t, data)
assert.Equal(t, 0.0, data["percentage"])
}
func TestGetHighestProgressSource_ThreeWayConflict(t *testing.T) {
handler := &ConflictHandler{}
conflictData := map[string]ConflictSourceData{
"koreader": {
Source: "koreader",
Data: map[string]interface{}{
"percentage": 0.45,
},
},
"kobo": {
Source: "kobo",
Data: map[string]interface{}{
"percentage": 0.92,
},
},
"web": {
Source: "web",
Data: map[string]interface{}{
"percentage": 0.70,
},
},
}
source, data := handler.getHighestProgressSource(conflictData)
assert.Equal(t, "kobo", source)
assert.Equal(t, 0.92, data["percentage"])
}
func TestGetMostRecentSource_ThreeWayConflict(t *testing.T) {
handler := &ConflictHandler{}
conflictData := map[string]ConflictSourceData{
"koreader": {
Source: "koreader",
Timestamp: time.Date(2026, 1, 30, 20, 5, 0, 0, time.UTC),
Data: map[string]interface{}{
"percentage": 0.45,
},
},
"kobo": {
Source: "kobo",
Timestamp: time.Date(2026, 1, 30, 20, 20, 0, 0, time.UTC),
Data: map[string]interface{}{
"percentage": 0.92,
},
},
"web": {
Source: "web",
Timestamp: time.Date(2026, 1, 30, 20, 10, 0, 0, time.UTC),
Data: map[string]interface{}{
"percentage": 0.70,
},
},
}
source, data := handler.getMostRecentSource(conflictData)
assert.Equal(t, "kobo", source)
assert.Equal(t, 0.92, data["percentage"])
}