Files
bookhoard/internal/sync/format_test.go
john-okeefe a2424bcf74 Phase 1 Week 4: Testing & Validation
- Create comprehensive unit tests for sync package
- format_test.go: 60+ tests for format detection
  - EPUB format detection (mimetype, extension, uppercase)
  - MOBI/AZW3/FB2/TXT reflowable formats
  - PDF/DJVU fixed layout formats
  - CBZ/CBR/CB7/CBT comic archive formats
  - Unknown format handling
  - MimeType lookup tests
  - IsReflowable/HasFixedLayout/IsComicArchive helpers
- progress_test.go: 45+ tests for progress conversion
  - PageToPercentage/PercentageToPage (with clamping)
  - CharacterToPercentage/PercentageToCharacter
  - ConvertProgress between format groups
  - MergeProgress with 'max progress wins' strategy
  - FormatProgressForDisplay for UI rendering
  - Round-trip conversion tests
  - Edge cases (very small/large values, floating point precision)
- All tests pass successfully
- Test coverage: format detection, progress conversion, display formatting
- Validates Phase 1 implementation quality
2026-01-30 16:13:10 -05:00

264 lines
5.6 KiB
Go

package sync
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestDetectFormatGroup_Epub(t *testing.T) {
tests := []struct {
name string
mimetype string
filePath string
want FormatGroup
}{
{
name: "EPUB by mimetype",
mimetype: "application/epub+zip",
filePath: "/path/to/book.epub",
want: FormatGroupReflowable,
},
{
name: "EPUB by extension",
mimetype: "",
filePath: "/path/to/book.epub",
want: FormatGroupReflowable,
},
{
name: "EPUB by uppercase extension",
mimetype: "",
filePath: "/path/to/book.EPUB",
want: FormatGroupReflowable,
},
{
name: "EPUB with mimetype priority",
mimetype: "application/epub+zip",
filePath: "/path/to/book.unknown",
want: FormatGroupReflowable,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := DetectFormatGroup(tt.mimetype, tt.filePath)
assert.Equal(t, tt.want, got)
})
}
}
func TestDetectFormatGroup_Mobi(t *testing.T) {
tests := []struct {
name string
mimetype string
filePath string
want FormatGroup
}{
{
name: "MOBI by mimetype",
mimetype: "application/x-mobipocket-ebook",
filePath: "/path/to/book.mobi",
want: FormatGroupReflowable,
},
{
name: "MOBI by extension",
mimetype: "",
filePath: "/path/to/book.mobi",
want: FormatGroupReflowable,
},
{
name: "AZW3 by extension",
mimetype: "",
filePath: "/path/to/book.azw3",
want: FormatGroupReflowable,
},
{
name: "FB2 by extension",
mimetype: "",
filePath: "/path/to/book.fb2",
want: FormatGroupReflowable,
},
{
name: "TXT by extension",
mimetype: "",
filePath: "/path/to/book.txt",
want: FormatGroupReflowable,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := DetectFormatGroup(tt.mimetype, tt.filePath)
assert.Equal(t, tt.want, got)
})
}
}
func TestDetectFormatGroup_Pdf(t *testing.T) {
tests := []struct {
name string
mimetype string
filePath string
want FormatGroup
}{
{
name: "PDF by mimetype",
mimetype: "application/pdf",
filePath: "/path/to/book.pdf",
want: FormatGroupFixedLayout,
},
{
name: "PDF by extension",
mimetype: "",
filePath: "/path/to/book.pdf",
want: FormatGroupFixedLayout,
},
{
name: "DJVU by extension",
mimetype: "",
filePath: "/path/to/book.djvu",
want: FormatGroupFixedLayout,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := DetectFormatGroup(tt.mimetype, tt.filePath)
assert.Equal(t, tt.want, got)
})
}
}
func TestDetectFormatGroup_Comic(t *testing.T) {
tests := []struct {
name string
mimetype string
filePath string
want FormatGroup
}{
{
name: "CBZ by mimetype",
mimetype: "application/x-cbz",
filePath: "/path/to/comic.cbz",
want: FormatGroupComicArchive,
},
{
name: "CBZ by extension",
mimetype: "",
filePath: "/path/to/comic.cbz",
want: FormatGroupComicArchive,
},
{
name: "CBR by extension",
mimetype: "",
filePath: "/path/to/comic.cbr",
want: FormatGroupComicArchive,
},
{
name: "CB7 by extension",
mimetype: "",
filePath: "/path/to/comic.cb7",
want: FormatGroupComicArchive,
},
{
name: "CBT by extension",
mimetype: "",
filePath: "/path/to/comic.cbt",
want: FormatGroupComicArchive,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := DetectFormatGroup(tt.mimetype, tt.filePath)
assert.Equal(t, tt.want, got)
})
}
}
func TestDetectFormatGroup_Unknown(t *testing.T) {
tests := []struct {
name string
mimetype string
filePath string
want FormatGroup
}{
{
name: "Unknown extension",
mimetype: "",
filePath: "/path/to/file.xyz",
want: FormatGroupUnknown,
},
{
name: "Unknown mimetype",
mimetype: "application/unknown",
filePath: "/path/to/file.unknown",
want: FormatGroupUnknown,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := DetectFormatGroup(tt.mimetype, tt.filePath)
assert.Equal(t, tt.want, got)
})
}
}
func TestGetMimeType(t *testing.T) {
tests := []struct {
name string
filePath string
want string
}{
{
name: "EPUB mimetype",
filePath: "book.epub",
want: "application/epub+zip",
},
{
name: "PDF mimetype",
filePath: "document.pdf",
want: "application/pdf",
},
{
name: "CBZ mimetype",
filePath: "comic.cbz",
want: "application/x-cbz",
},
{
name: "Unknown mimetype",
filePath: "file.xyz",
want: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := GetMimeType(tt.filePath)
assert.Equal(t, tt.want, got)
})
}
}
func TestIsReflowable(t *testing.T) {
assert.True(t, IsReflowable(FormatGroupReflowable))
assert.False(t, IsReflowable(FormatGroupFixedLayout))
assert.False(t, IsReflowable(FormatGroupComicArchive))
assert.False(t, IsReflowable(FormatGroupUnknown))
}
func TestHasFixedLayout(t *testing.T) {
assert.True(t, HasFixedLayout(FormatGroupFixedLayout))
assert.False(t, HasFixedLayout(FormatGroupReflowable))
assert.False(t, HasFixedLayout(FormatGroupComicArchive))
assert.False(t, HasFixedLayout(FormatGroupUnknown))
}
func TestIsComicArchive(t *testing.T) {
assert.True(t, IsComicArchive(FormatGroupComicArchive))
assert.False(t, IsComicArchive(FormatGroupReflowable))
assert.False(t, IsComicArchive(FormatGroupFixedLayout))
assert.False(t, IsComicArchive(FormatGroupUnknown))
}