package opds import ( "testing" ) func TestNewFeed(t *testing.T) { feed := NewFeed("urn:uuid:test-id", "Test Feed") if feed.ID != "urn:uuid:test-id" { t.Errorf("expected ID to be 'urn:uuid:test-id', got '%s'", feed.ID) } if feed.Title != "Test Feed" { t.Errorf("expected Title to be 'Test Feed', got '%s'", feed.Title) } if feed.Xmlns != "http://www.w3.org/2005/Atom" { t.Errorf("expected Xmlns to be 'http://www.w3.org/2005/Atom', got '%s'", feed.Xmlns) } if feed.OpdsNS != "http://opds-spec.org/2010/" { t.Errorf("expected OpdsNS to be 'http://opds-spec.org/2010/', got '%s'", feed.OpdsNS) } } func TestFeedAddLink(t *testing.T) { feed := NewFeed("urn:uuid:test-id", "Test Feed") feed.AddLink("http://example.com", "application/atom+xml", "self") if len(feed.Links) != 1 { t.Fatalf("expected 1 link, got %d", len(feed.Links)) } link := feed.Links[0] if link.Href != "http://example.com" { t.Errorf("expected Href to be 'http://example.com', got '%s'", link.Href) } if link.Type != "application/atom+xml" { t.Errorf("expected Type to be 'application/atom+xml', got '%s'", link.Type) } if link.Rel != "self" { t.Errorf("expected Rel to be 'self', got '%s'", link.Rel) } } func TestFeedAddEntry(t *testing.T) { feed := NewFeed("urn:uuid:test-id", "Test Feed") entry := NewEntry("urn:uuid:book-id", "Test Book", "Test Author", "2023-01-01T00:00:00Z") feed.AddEntry(entry) if len(feed.Entries) != 1 { t.Fatalf("expected 1 entry, got %d", len(feed.Entries)) } if feed.Entries[0].ID != "urn:uuid:book-id" { t.Errorf("expected entry ID to be 'urn:uuid:book-id', got '%s'", feed.Entries[0].ID) } } func TestNewEntry(t *testing.T) { entry := NewEntry("urn:uuid:test-id", "Test Title", "Test Author", "2023-01-01T00:00:00Z") if entry.ID != "urn:uuid:test-id" { t.Errorf("expected ID to be 'urn:uuid:test-id', got '%s'", entry.ID) } if entry.Title != "Test Title" { t.Errorf("expected Title to be 'Test Title', got '%s'", entry.Title) } if entry.Creator != "Test Author" { t.Errorf("expected Creator to be 'Test Author', got '%s'", entry.Creator) } if entry.Updated != "2023-01-01T00:00:00Z" { t.Errorf("expected Updated to be '2023-01-01T00:00:00Z', got '%s'", entry.Updated) } } func TestEntryAddAcquisitionLink(t *testing.T) { entry := NewEntry("urn:uuid:test-id", "Test Title", "Test Author", "2023-01-01T00:00:00Z") entry.AddAcquisitionLink("http://example.com/book.epub", "application/epub+zip") if len(entry.Links) != 1 { t.Fatalf("expected 1 link, got %d", len(entry.Links)) } link := entry.Links[0] if link.Href != "http://example.com/book.epub" { t.Errorf("expected Href to be 'http://example.com/book.epub', got '%s'", link.Href) } if link.Rel != "http://opds-spec.org/acquisition/open-access" { t.Errorf("expected Rel to be 'http://opds-spec.org/acquisition/open-access', got '%s'", link.Rel) } } func TestEntryAddAlternateLink(t *testing.T) { entry := NewEntry("urn:uuid:test-id", "Test Title", "Test Author", "2023-01-01T00:00:00Z") entry.AddAlternateLink("http://example.com/book.kepub.epub", "application/vnd.kobo+xml+zip") if len(entry.Links) != 1 { t.Fatalf("expected 1 link, got %d", len(entry.Links)) } link := entry.Links[0] if link.Rel != "alternate" { t.Errorf("expected Rel to be 'alternate', got '%s'", link.Rel) } } func TestEntrySetIdentifier(t *testing.T) { entry := NewEntry("urn:uuid:test-id", "Test Title", "Test Author", "2023-01-01T00:00:00Z") entry.SetIdentifier("book-uuid-123") if entry.Identifier == nil { t.Fatal("expected Identifier to be set, but it was nil") } if entry.Identifier.ID != "bookhoard" { t.Errorf("expected Identifier ID to be 'bookhoard', got '%s'", entry.Identifier.ID) } if entry.Identifier.Content != "book-uuid-123" { t.Errorf("expected Identifier Content to be 'book-uuid-123', got '%s'", entry.Identifier.Content) } } func TestEntryAddMetadata(t *testing.T) { entry := NewEntry("urn:uuid:test-id", "Test Title", "Test Author", "2023-01-01T00:00:00Z") entry.AddMetadata("bookhoard:sha256", "abc123...") if len(entry.Metadata) != 1 { t.Fatalf("expected 1 metadata item, got %d", len(entry.Metadata)) } meta := entry.Metadata[0] if meta.Property != "bookhoard:sha256" { t.Errorf("expected Property to be 'bookhoard:sha256', got '%s'", meta.Property) } if meta.Content != "abc123..." { t.Errorf("expected Content to be 'abc123...', got '%s'", meta.Content) } } func TestEntryAddCategory(t *testing.T) { entry := NewEntry("urn:uuid:test-id", "Test Title", "Test Author", "2023-01-01T00:00:00Z") entry.AddCategory("http://example.com/collections", "Science Fiction") if len(entry.Categories) != 1 { t.Fatalf("expected 1 category, got %d", len(entry.Categories)) } category := entry.Categories[0] if category.Scheme != "http://example.com/collections" { t.Errorf("expected Scheme to be 'http://example.com/collections', got '%s'", category.Scheme) } if category.Term != "Science Fiction" { t.Errorf("expected Term to be 'Science Fiction', got '%s'", category.Term) } } func TestEntrySetSummary(t *testing.T) { entry := NewEntry("urn:uuid:test-id", "Test Title", "Test Author", "2023-01-01T00:00:00Z") entry.SetSummary("This is a test book") if entry.Summary != "This is a test book" { t.Errorf("expected Summary to be 'This is a test book', got '%s'", entry.Summary) } } func TestFeedGenerateXML(t *testing.T) { feed := NewFeed("urn:uuid:test-id", "Test Feed") feed.AddLink("http://example.com", "application/atom+xml", "self") entry := NewEntry("urn:uuid:book-id", "Test Book", "Test Author", "2023-01-01T00:00:00Z") entry.AddAcquisitionLink("http://example.com/book.epub", "application/epub+zip") entry.SetIdentifier("book-uuid-123") entry.AddMetadata("bookhoard:sha256", "abc123...") feed.AddEntry(entry) output, err := feed.GenerateXML() if err != nil { t.Fatalf("failed to generate XML: %v", err) } outputStr := string(output) // Check for essential OPDS elements requiredStrings := []string{ `urn:uuid:test-id`, `Test Feed`, ``, `urn:uuid:book-id`, `Test Book`, `Test Author`, `book-uuid-123`, `abc123...`, } for _, required := range requiredStrings { if !contains(outputStr, required) { t.Errorf("generated XML missing required string: %s", required) } } } func TestNewErrorFeed(t *testing.T) { feed := NewErrorFeed("Test error message") if feed.Title != "Error" { t.Errorf("expected Title to be 'Error', got '%s'", feed.Title) } if len(feed.Entries) != 1 { t.Fatalf("expected 1 entry in error feed, got %d", len(feed.Entries)) } if feed.Entries[0].Summary != "Test error message" { t.Errorf("expected error message to be 'Test error message', got '%s'", feed.Entries[0].Summary) } } func contains(s, substr string) bool { return len(s) >= len(substr) && indexOf(s, substr) >= 0 } func indexOf(s, substr string) int { for i := 0; i <= len(s)-len(substr); i++ { if s[i:i+len(substr)] == substr { return i } } return -1 }