1417 lines
40 KiB
Go
1417 lines
40 KiB
Go
// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package client
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
type roundTripperFunc func(req *http.Request) (*http.Response, error)
|
|
|
|
func (fn roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
return fn(req)
|
|
}
|
|
|
|
func newFakeHTTPClient(
|
|
t *testing.T,
|
|
fn func(t *testing.T, req *http.Request) *http.Response,
|
|
) *http.Client {
|
|
return &http.Client{
|
|
Transport: roundTripperFunc(
|
|
func(req *http.Request) (*http.Response, error) {
|
|
return fn(t, req), nil
|
|
}),
|
|
}
|
|
}
|
|
|
|
func jsonResponseFrom(
|
|
t *testing.T,
|
|
status int,
|
|
headers http.Header,
|
|
body any,
|
|
) *http.Response {
|
|
data, err := json.Marshal(body)
|
|
if err != nil {
|
|
t.Fatalf("Unable to marshal body: %v", err)
|
|
}
|
|
|
|
return &http.Response{
|
|
StatusCode: status,
|
|
Body: io.NopCloser(bytes.NewBuffer(data)),
|
|
Header: headers,
|
|
}
|
|
}
|
|
|
|
func asJSON(data any) string {
|
|
json, err := json.MarshalIndent(data, "", " ")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return string(json)
|
|
}
|
|
|
|
func expectRequest(
|
|
t *testing.T,
|
|
method string,
|
|
url string,
|
|
checkBody func(r io.Reader),
|
|
req *http.Request,
|
|
) {
|
|
if req.Method != method {
|
|
t.Fatalf("Expected method to be %s, got %s", method, req.Method)
|
|
}
|
|
|
|
if req.URL.String() != url {
|
|
t.Fatalf("Expected URL path to be %s, got %s", url, req.URL)
|
|
}
|
|
|
|
if checkBody != nil {
|
|
checkBody(req.Body)
|
|
}
|
|
}
|
|
|
|
func expectFromJSON[T any](
|
|
t *testing.T,
|
|
r io.Reader,
|
|
expected *T,
|
|
) {
|
|
var got T
|
|
if err := json.NewDecoder(r).Decode(&got); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(&got, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(got))
|
|
}
|
|
}
|
|
|
|
func TestHealthcheck(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/healthcheck", nil, req)
|
|
return &http.Response{
|
|
StatusCode: http.StatusOK,
|
|
Body: io.NopCloser(bytes.NewBufferString("OK")),
|
|
}
|
|
})))
|
|
if err := client.HealthcheckContext(t.Context()); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestVersion(t *testing.T) {
|
|
expected := &VersionResponse{
|
|
Version: "1.0.0",
|
|
Commit: "1234567890",
|
|
BuildDate: "2021-01-01T00:00:00Z",
|
|
GoVersion: "go1.20",
|
|
Compiler: "gc",
|
|
Arch: "amd64",
|
|
OS: "linux",
|
|
}
|
|
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/version", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.VersionContext(t.Context())
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestMe(t *testing.T) {
|
|
expected := &User{
|
|
ID: 1,
|
|
Username: "test",
|
|
Password: "password",
|
|
IsAdmin: false,
|
|
Theme: "light",
|
|
Language: "en",
|
|
Timezone: "UTC",
|
|
EntryDirection: "asc",
|
|
EntryOrder: "created_at",
|
|
Stylesheet: "default",
|
|
CustomJS: "custom.js",
|
|
GoogleID: "google-id",
|
|
OpenIDConnectID: "openid-connect-id",
|
|
EntriesPerPage: 10,
|
|
KeyboardShortcuts: true,
|
|
ShowReadingTime: true,
|
|
EntrySwipe: true,
|
|
GestureNav: "horizontal",
|
|
DisplayMode: "read",
|
|
DefaultReadingSpeed: 1,
|
|
CJKReadingSpeed: 1,
|
|
DefaultHomePage: "home",
|
|
CategoriesSortingOrder: "asc",
|
|
MarkReadOnView: true,
|
|
MediaPlaybackRate: 1.0,
|
|
BlockFilterEntryRules: "block",
|
|
KeepFilterEntryRules: "keep",
|
|
ExternalFontHosts: "https://fonts.googleapis.com",
|
|
AlwaysOpenExternalLinks: true,
|
|
OpenExternalLinksInNewTab: true,
|
|
}
|
|
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/me", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.MeContext(t.Context())
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestUsers(t *testing.T) {
|
|
expected := Users{
|
|
{
|
|
ID: 1,
|
|
Username: "test1",
|
|
},
|
|
{
|
|
ID: 2,
|
|
Username: "test2",
|
|
},
|
|
}
|
|
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/users", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.UsersContext(t.Context())
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestUserByID(t *testing.T) {
|
|
expected := &User{
|
|
ID: 1,
|
|
Username: "test",
|
|
}
|
|
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/users/1", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.UserByIDContext(t.Context(), 1)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestUserByUsername(t *testing.T) {
|
|
expected := &User{
|
|
ID: 1,
|
|
Username: "test",
|
|
}
|
|
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/users/test", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.UserByUsernameContext(t.Context(), "test")
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestCreateUser(t *testing.T) {
|
|
expected := &User{
|
|
ID: 1,
|
|
Username: "test",
|
|
Password: "password",
|
|
IsAdmin: true,
|
|
}
|
|
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
exp := UserCreationRequest{
|
|
Username: "test",
|
|
Password: "password",
|
|
IsAdmin: true,
|
|
}
|
|
expectRequest(
|
|
t,
|
|
http.MethodPost,
|
|
"http://mf/v1/users",
|
|
func(r io.Reader) {
|
|
expectFromJSON(t, r, &exp)
|
|
},
|
|
req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.CreateUserContext(t.Context(), "test", "password", true)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestUpdateUser(t *testing.T) {
|
|
expected := &User{
|
|
ID: 1,
|
|
Username: "test",
|
|
Password: "password",
|
|
IsAdmin: true,
|
|
}
|
|
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/users/1", func(r io.Reader) {
|
|
expectFromJSON(t, r, &UserModificationRequest{
|
|
Username: &expected.Username,
|
|
Password: &expected.Password,
|
|
})
|
|
}, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.UpdateUserContext(t.Context(), 1, &UserModificationRequest{
|
|
Username: &expected.Username,
|
|
Password: &expected.Password,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestDeleteUser(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodDelete, "http://mf/v1/users/1", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, nil)
|
|
})))
|
|
if err := client.DeleteUserContext(t.Context(), 1); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestAPIKeys(t *testing.T) {
|
|
expected := APIKeys{
|
|
{
|
|
ID: 1,
|
|
Token: "token",
|
|
Description: "test",
|
|
},
|
|
{
|
|
ID: 2,
|
|
Token: "token2",
|
|
Description: "test2",
|
|
},
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/api-keys", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.APIKeysContext(t.Context())
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestCreateAPIKey(t *testing.T) {
|
|
expected := &APIKey{
|
|
ID: 42,
|
|
Token: "some-token",
|
|
Description: "desc",
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPost, "http://mf/v1/api-keys", func(r io.Reader) {
|
|
expectFromJSON(t, r, &APIKeyCreationRequest{
|
|
Description: "desc",
|
|
})
|
|
}, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.CreateAPIKeyContext(t.Context(), "desc")
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestDeleteAPIKey(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodDelete, "http://mf/v1/api-keys/1", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, nil)
|
|
})))
|
|
if err := client.DeleteAPIKeyContext(t.Context(), 1); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestMarkAllAsRead(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/users/1/mark-all-as-read", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, nil)
|
|
})))
|
|
if err := client.MarkAllAsReadContext(t.Context(), 1); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestIntegrationsStatus(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/integrations/status", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, struct {
|
|
HasIntegrations bool `json:"has_integrations"`
|
|
}{
|
|
HasIntegrations: true,
|
|
})
|
|
})))
|
|
status, err := client.IntegrationsStatusContext(t.Context())
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !status {
|
|
t.Fatalf("Expected integrations status to be true, got false")
|
|
}
|
|
}
|
|
|
|
func TestDiscover(t *testing.T) {
|
|
expected := Subscriptions{
|
|
{
|
|
URL: "http://example.com",
|
|
Title: "Example",
|
|
Type: "rss",
|
|
},
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPost, "http://mf/v1/discover", func(r io.Reader) {
|
|
expectFromJSON(t, r, &map[string]string{"url": "http://example.com"})
|
|
}, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.DiscoverContext(t.Context(), "http://example.com")
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestCategories(t *testing.T) {
|
|
expected := Categories{
|
|
{
|
|
ID: 1,
|
|
Title: "Example",
|
|
},
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/categories", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.CategoriesContext(t.Context())
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestCategoriesWithCounters(t *testing.T) {
|
|
feedCount := 1
|
|
totalUnread := 2
|
|
expected := Categories{
|
|
{
|
|
ID: 1,
|
|
Title: "Example",
|
|
FeedCount: &feedCount,
|
|
TotalUnread: &totalUnread,
|
|
},
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/categories?counts=true", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.CategoriesWithCountersContext(t.Context())
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestCreateCategory(t *testing.T) {
|
|
expected := &Category{
|
|
ID: 1,
|
|
Title: "Example",
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPost, "http://mf/v1/categories", func(r io.Reader) {
|
|
expectFromJSON(t, r, &CategoryCreationRequest{
|
|
Title: "Example",
|
|
})
|
|
}, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.CreateCategoryContext(t.Context(), "Example")
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestCreateCategoryWithOptions(t *testing.T) {
|
|
expected := &Category{
|
|
ID: 1,
|
|
Title: "Example",
|
|
HideGlobally: true,
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPost, "http://mf/v1/categories", func(r io.Reader) {
|
|
expectFromJSON(t, r, &CategoryCreationRequest{
|
|
Title: "Example",
|
|
HideGlobally: true,
|
|
})
|
|
}, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.CreateCategoryWithOptionsContext(t.Context(), &CategoryCreationRequest{
|
|
Title: "Example",
|
|
HideGlobally: true,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestUpdateCategory(t *testing.T) {
|
|
expected := &Category{
|
|
ID: 1,
|
|
Title: "Example",
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/categories/1", func(r io.Reader) {
|
|
expectFromJSON(t, r, &CategoryModificationRequest{
|
|
Title: &expected.Title,
|
|
})
|
|
}, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.UpdateCategoryContext(t.Context(), 1, "Example")
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestUpdateCategoryWithOptions(t *testing.T) {
|
|
expected := &Category{
|
|
ID: 1,
|
|
Title: "Example",
|
|
HideGlobally: true,
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/categories/1", func(r io.Reader) {
|
|
expectFromJSON(t, r, &CategoryModificationRequest{
|
|
Title: &expected.Title,
|
|
HideGlobally: &expected.HideGlobally,
|
|
})
|
|
}, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.UpdateCategoryWithOptionsContext(t.Context(), 1, &CategoryModificationRequest{
|
|
Title: &expected.Title,
|
|
HideGlobally: &expected.HideGlobally,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestMarkCategoryAsRead(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/categories/1/mark-all-as-read", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, nil)
|
|
})))
|
|
if err := client.MarkCategoryAsReadContext(t.Context(), 1); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestCategoryFeeds(t *testing.T) {
|
|
expected := Feeds{
|
|
{
|
|
ID: 1,
|
|
Title: "Example",
|
|
},
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/categories/1/feeds", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.CategoryFeedsContext(t.Context(), 1)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestDeleteCategory(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodDelete, "http://mf/v1/categories/1", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, nil)
|
|
})))
|
|
if err := client.DeleteCategoryContext(t.Context(), 1); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestRefreshCategory(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/categories/1/refresh", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, nil)
|
|
})))
|
|
if err := client.RefreshCategoryContext(t.Context(), 1); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestFeeds(t *testing.T) {
|
|
expected := Feeds{
|
|
{
|
|
ID: 1,
|
|
Title: "Example",
|
|
FeedURL: "http://example.com",
|
|
SiteURL: "http://example.com",
|
|
CheckedAt: time.Date(1970, 1, 1, 0, 7, 0, 0, time.UTC),
|
|
Disabled: false,
|
|
IgnoreHTTPCache: false,
|
|
AllowSelfSignedCertificates: false,
|
|
FetchViaProxy: false,
|
|
ScraperRules: "",
|
|
RewriteRules: "",
|
|
UrlRewriteRules: "",
|
|
BlocklistRules: "",
|
|
KeeplistRules: "",
|
|
BlockFilterEntryRules: "",
|
|
KeepFilterEntryRules: "",
|
|
Crawler: false,
|
|
UserAgent: "",
|
|
Cookie: "",
|
|
Username: "",
|
|
Password: "",
|
|
Category: &Category{
|
|
ID: 1,
|
|
Title: "Example",
|
|
},
|
|
HideGlobally: false,
|
|
DisableHTTP2: false,
|
|
ProxyURL: "",
|
|
},
|
|
{
|
|
ID: 2,
|
|
Title: "Example 2",
|
|
},
|
|
}
|
|
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/feeds", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.FeedsContext(t.Context())
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestExport(t *testing.T) {
|
|
expected := []byte("hello")
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/export", nil, req)
|
|
return &http.Response{
|
|
StatusCode: http.StatusOK,
|
|
Body: io.NopCloser(bytes.NewBufferString(string(expected))),
|
|
Header: http.Header{},
|
|
}
|
|
})))
|
|
res, err := client.ExportContext(t.Context())
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %+v, got %+v", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestImport(t *testing.T) {
|
|
expected := []byte("hello")
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(
|
|
t,
|
|
http.MethodPost,
|
|
"http://mf/v1/import",
|
|
func(r io.Reader) {
|
|
b, err := io.ReadAll(r)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !bytes.Equal(b, expected) {
|
|
t.Fatalf("expected %+v, got %+v", expected, b)
|
|
}
|
|
},
|
|
req)
|
|
return &http.Response{
|
|
StatusCode: http.StatusOK,
|
|
Header: http.Header{},
|
|
}
|
|
})))
|
|
if err := client.ImportContext(t.Context(), io.NopCloser(bytes.NewBufferString(string(expected)))); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestFeed(t *testing.T) {
|
|
expected := &Feed{
|
|
ID: 1,
|
|
Title: "Example",
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/feeds/1", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.FeedContext(t.Context(), 1)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestCreateFeed(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPost, "http://mf/v1/feeds", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, struct {
|
|
FeedID int64 `json:"feed_id"`
|
|
}{
|
|
FeedID: 1,
|
|
})
|
|
})))
|
|
id, err := client.CreateFeedContext(t.Context(), &FeedCreationRequest{
|
|
FeedURL: "http://example.com",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
|
|
if id != 1 {
|
|
t.Fatalf("Expected feed ID to be 1, got %d", id)
|
|
}
|
|
}
|
|
|
|
func TestUpdateFeed(t *testing.T) {
|
|
expected := &Feed{
|
|
ID: 1,
|
|
FeedURL: "http://example.com/",
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/feeds/1", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.UpdateFeedContext(t.Context(), 1, &FeedModificationRequest{
|
|
FeedURL: &expected.FeedURL,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestMarkFeedAsRead(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/feeds/1/mark-all-as-read", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, nil)
|
|
})))
|
|
if err := client.MarkFeedAsReadContext(t.Context(), 1); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestRefreshAllFeeds(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/feeds/refresh", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, nil)
|
|
})))
|
|
if err := client.RefreshAllFeedsContext(t.Context()); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestRefreshFeed(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/feeds/1/refresh", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, nil)
|
|
})))
|
|
if err := client.RefreshFeedContext(t.Context(), 1); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestDeleteFeed(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodDelete, "http://mf/v1/feeds/1", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, nil)
|
|
})))
|
|
if err := client.DeleteFeedContext(t.Context(), 1); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestFeedIcon(t *testing.T) {
|
|
expected := &FeedIcon{
|
|
ID: 1,
|
|
MimeType: "text/plain",
|
|
Data: "data",
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/feeds/1/icon", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.FeedIconContext(t.Context(), 1)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestFeedEntry(t *testing.T) {
|
|
expected := &Entry{
|
|
ID: 1,
|
|
Title: "Example",
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/feeds/1/entries/1", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.FeedEntryContext(t.Context(), 1, 1)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestCategoryEntry(t *testing.T) {
|
|
expected := &Entry{
|
|
ID: 1,
|
|
Title: "Example",
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/categories/1/entries/1", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.CategoryEntryContext(t.Context(), 1, 1)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestEntry(t *testing.T) {
|
|
expected := &Entry{
|
|
ID: 1,
|
|
Title: "Example",
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/entries/1", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.EntryContext(t.Context(), 1)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestEntries(t *testing.T) {
|
|
expected := &EntryResultSet{
|
|
Total: 1,
|
|
Entries: Entries{
|
|
{
|
|
ID: 1,
|
|
Title: "Example",
|
|
},
|
|
},
|
|
}
|
|
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/entries", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.EntriesContext(t.Context(), nil)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestFeedEntries(t *testing.T) {
|
|
expected := &EntryResultSet{
|
|
Total: 1,
|
|
Entries: Entries{
|
|
{
|
|
ID: 1,
|
|
Title: "Example",
|
|
},
|
|
},
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/feeds/1/entries?limit=10&offset=0", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.FeedEntriesContext(t.Context(), 1, &Filter{
|
|
Limit: 10,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestCategoryEntries(t *testing.T) {
|
|
expected := &EntryResultSet{
|
|
Total: 1,
|
|
Entries: Entries{
|
|
{
|
|
ID: 1,
|
|
Title: "Example",
|
|
},
|
|
},
|
|
}
|
|
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/categories/1/entries?limit=10&offset=0", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.CategoryEntriesContext(t.Context(), 1, &Filter{
|
|
Limit: 10,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestUpdateEntries(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/entries", nil, req)
|
|
expectFromJSON(t, req.Body, &struct {
|
|
EntryIDs []int64 `json:"entry_ids"`
|
|
Status string `json:"status"`
|
|
}{
|
|
EntryIDs: []int64{1, 2},
|
|
Status: "read",
|
|
})
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, nil)
|
|
})))
|
|
if err := client.UpdateEntriesContext(t.Context(), []int64{1, 2}, "read"); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestUpdateEntriesStarred(t *testing.T) {
|
|
starred := true
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/entries", nil, req)
|
|
expectFromJSON(t, req.Body, &struct {
|
|
EntryIDs []int64 `json:"entry_ids"`
|
|
Starred *bool `json:"starred"`
|
|
}{
|
|
EntryIDs: []int64{1, 2},
|
|
Starred: &starred,
|
|
})
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, nil)
|
|
})))
|
|
if err := client.UpdateEntriesStarredContext(t.Context(), []int64{1, 2}, true); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestUpdateEntry(t *testing.T) {
|
|
expected := &Entry{
|
|
ID: 1,
|
|
Title: "Example",
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/entries/1", nil, req)
|
|
expectFromJSON(t, req.Body, &EntryModificationRequest{
|
|
Title: &expected.Title,
|
|
})
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.UpdateEntryContext(t.Context(), 1, &EntryModificationRequest{
|
|
Title: &expected.Title,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestToggleStarred(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/entries/1/star", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, nil)
|
|
})))
|
|
if err := client.ToggleStarredContext(t.Context(), 1); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSaveEntry(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPost, "http://mf/v1/entries/1/save", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, nil)
|
|
})))
|
|
if err := client.SaveEntryContext(t.Context(), 1); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestFetchEntryOriginalContent(t *testing.T) {
|
|
expected := "Example"
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/entries/1/fetch-content", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, struct {
|
|
Content string `json:"content"`
|
|
}{
|
|
Content: expected,
|
|
})
|
|
})))
|
|
res, err := client.FetchEntryOriginalContentContext(t.Context(), 1)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if res != expected {
|
|
t.Fatalf("Expected %s, got %s", expected, res)
|
|
}
|
|
}
|
|
|
|
func TestFetchCounters(t *testing.T) {
|
|
expected := &FeedCounters{
|
|
ReadCounters: map[int64]int{
|
|
2: 1,
|
|
},
|
|
UnreadCounters: map[int64]int{
|
|
3: 1,
|
|
},
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/feeds/counters", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.FetchCountersContext(t.Context())
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestFlushHistory(t *testing.T) {
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/flush-history", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, nil)
|
|
})))
|
|
if err := client.FlushHistoryContext(t.Context()); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestIcon(t *testing.T) {
|
|
expected := &FeedIcon{
|
|
ID: 1,
|
|
MimeType: "text/plain",
|
|
Data: "data",
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/icons/1", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.IconContext(t.Context(), 1)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestEnclosure(t *testing.T) {
|
|
expected := &Enclosure{
|
|
ID: 1,
|
|
URL: "http://example.com",
|
|
MimeType: "text/plain",
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/enclosures/1", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.EnclosureContext(t.Context(), 1)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestUpdateEnclosure(t *testing.T) {
|
|
expected := &Enclosure{
|
|
ID: 1,
|
|
URL: "http://example.com",
|
|
MimeType: "text/plain",
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodPut, "http://mf/v1/enclosures/1", nil, req)
|
|
expectFromJSON(t, req.Body, &EnclosureUpdateRequest{
|
|
MediaProgression: 10,
|
|
})
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
if err := client.UpdateEnclosureContext(t.Context(), 1, &EnclosureUpdateRequest{
|
|
MediaProgression: 10,
|
|
}); err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func boolPtr(b bool) *bool { return &b }
|
|
|
|
func TestEntryIDsNoFilter(t *testing.T) {
|
|
expected := &EntryIDsResultSet{
|
|
Total: 2,
|
|
EntryIDs: []int64{1, 2},
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/entries/ids", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.EntryIDsContext(t.Context(), nil)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestEntryIDsWithPaginationFilter(t *testing.T) {
|
|
expected := &EntryIDsResultSet{
|
|
Total: 5,
|
|
EntryIDs: []int64{3},
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/entries/ids?limit=1&offset=2", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.EntryIDsContext(t.Context(), &EntryIDsFilter{Limit: 1, Offset: 2})
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestEntryIDsWithStarredFilter(t *testing.T) {
|
|
expected := &EntryIDsResultSet{
|
|
Total: 1,
|
|
EntryIDs: []int64{42},
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/entries/ids?starred=true", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.EntryIDsContext(t.Context(), &EntryIDsFilter{Starred: boolPtr(true)})
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestEntryIDsWithStatusFilter(t *testing.T) {
|
|
expected := &EntryIDsResultSet{
|
|
Total: 10,
|
|
EntryIDs: []int64{7, 8},
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/entries/ids?status=unread", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.EntryIDsContext(t.Context(), &EntryIDsFilter{Status: EntryStatusUnread})
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|
|
|
|
func TestEntryIDsWithCombinedFilter(t *testing.T) {
|
|
expected := &EntryIDsResultSet{
|
|
Total: 3,
|
|
EntryIDs: []int64{5},
|
|
}
|
|
client := NewClientWithOptions(
|
|
"http://mf",
|
|
WithHTTPClient(
|
|
newFakeHTTPClient(t, func(t *testing.T, req *http.Request) *http.Response {
|
|
expectRequest(t, http.MethodGet, "http://mf/v1/entries/ids?limit=2&offset=5&starred=false&status=read", nil, req)
|
|
return jsonResponseFrom(t, http.StatusOK, http.Header{}, expected)
|
|
})))
|
|
res, err := client.EntryIDsContext(t.Context(), &EntryIDsFilter{Limit: 2, Offset: 5, Starred: boolPtr(false), Status: EntryStatusRead})
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got %v", err)
|
|
}
|
|
if !reflect.DeepEqual(res, expected) {
|
|
t.Fatalf("Expected %s, got %s", asJSON(expected), asJSON(res))
|
|
}
|
|
}
|