test: update device authentication tests
- Change Kobo sync endpoints to use URL token authentication - Update OPDS tests to use device tokens instead of user tokens - Support both Bearer and query parameter authentication methods - Return error when test user already exists instead of deleting - Prevent test interference from cleanup operations - Improve test isolation and reliability
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
package bookhoard/cmd/server/tests
|
||||
package main
|
||||
|
||||
import (
|
||||
"bookhoard/internal/handlers"
|
||||
@@ -31,8 +31,7 @@ func TestKoboInitialization(t *testing.T) {
|
||||
deviceSetup := setupDeviceTest(t)
|
||||
koboDevice := deviceSetup.CreateDevice(t, "Test Kobo", "kobo", "kobo-clara-test")
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/sync/kobo/v1/initialization", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+koboDevice.AuthToken)
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/sync/kobo/"+koboDevice.AuthToken+"/v1/initialization", nil)
|
||||
req.Header.Set("x-kobo-device", fmt.Sprintf(`{"DeviceId":"%s","Model":"Kobo Clara","SerialNumber":"%s"}`,
|
||||
koboDevice.ID.String(), koboDevice.Identifier))
|
||||
|
||||
@@ -61,8 +60,7 @@ func TestKoboLibrarySync(t *testing.T) {
|
||||
deviceSetup := setupDeviceTest(t)
|
||||
koboDevice := deviceSetup.CreateDevice(t, "Test Kobo", "kobo", "kobo-clara-test")
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/sync/kobo/v1/initialization", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+koboDevice.AuthToken)
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/sync/kobo/"+koboDevice.AuthToken+"/v1/initialization", nil)
|
||||
req.Header.Set("x-kobo-device", fmt.Sprintf(`{"DeviceId":"%s","Model":"Kobo Clara","SerialNumber":"%s"}`,
|
||||
koboDevice.ID.String(), koboDevice.Identifier))
|
||||
|
||||
@@ -126,9 +124,8 @@ func TestKoboMarkupSync(t *testing.T) {
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(reqBody)
|
||||
req, _ := http.NewRequest("POST", setup.Server.URL+"/api/sync/kobo/markup", bytes.NewReader(body))
|
||||
req, _ := http.NewRequest("POST", setup.Server.URL+"/api/sync/kobo/"+koboDevice.AuthToken+"/markup", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+koboDevice.AuthToken)
|
||||
req.Header.Set("x-kobo-device", fmt.Sprintf(`{"DeviceId":"%s","Model":"Kobo Clara","SerialNumber":"%s"}`,
|
||||
koboDevice.ID.String(), koboDevice.Identifier))
|
||||
|
||||
@@ -181,9 +178,8 @@ func TestKoboBookmarkSync(t *testing.T) {
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(reqBody)
|
||||
req, _ := http.NewRequest("POST", setup.Server.URL+"/api/sync/kobo/bookmark", bytes.NewReader(body))
|
||||
req, _ := http.NewRequest("POST", setup.Server.URL+"/api/sync/kobo/"+koboDevice.AuthToken+"/bookmark", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+koboDevice.AuthToken)
|
||||
req.Header.Set("x-kobo-device", fmt.Sprintf(`{"DeviceId":"%s","Model":"Kobo Clara","SerialNumber":"%s"}`,
|
||||
koboDevice.ID.String(), koboDevice.Identifier))
|
||||
|
||||
@@ -225,9 +221,8 @@ func TestKoboAnalyticsGettests(t *testing.T) {
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(reqBody)
|
||||
req, _ := http.NewRequest("POST", setup.Server.URL+"/api/sync/kobo/v1/analytics/gettests", bytes.NewReader(body))
|
||||
req, _ := http.NewRequest("POST", setup.Server.URL+"/api/sync/kobo/"+koboDevice.AuthToken+"/v1/analytics/gettests", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+koboDevice.AuthToken)
|
||||
req.Header.Set("x-kobo-device", fmt.Sprintf(`{"DeviceId":"%s","Model":"Kobo Clara","SerialNumber":"%s"}`,
|
||||
koboDevice.ID.String(), koboDevice.Identifier))
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
func TestOPDSEndpoints(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
_ = createTestMediaItemID(t, setup.Server, token)
|
||||
client := &http.Client{}
|
||||
|
||||
t.Run("GetDeviceCatalog_WithoutDeviceAuth", func(t *testing.T) {
|
||||
@@ -38,18 +39,36 @@ func TestOPDSEndpoints(t *testing.T) {
|
||||
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("GetDeviceCatalog_ValidDevice", func(t *testing.T) {
|
||||
deviceID := uuid.New()
|
||||
t.Run("GetDeviceCatalog_ValidDevice_BearerToken", func(t *testing.T) {
|
||||
// Create a device with auth token
|
||||
deviceSetup := setupDeviceTest(t)
|
||||
device := deviceSetup.CreateDevice(t, "Test OPDS Device", "koreader", "opds-bearer-test")
|
||||
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+deviceID.String()+"/catalog", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+token)
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+device.ID.String()+"/catalog", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+device.AuthToken)
|
||||
|
||||
resp, err := client.Do(httpReq)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Should return either 200 (OK with empty catalog) or 404 (device not found)
|
||||
assert.True(t, resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNotFound)
|
||||
// Should return 200 with catalog (even if empty)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("GetDeviceCatalog_ValidDevice_QueryToken", func(t *testing.T) {
|
||||
// Create a device with auth token
|
||||
deviceSetup := setupDeviceTest(t)
|
||||
device := deviceSetup.CreateDevice(t, "Test OPDS Device", "kobo", "opds-query-test")
|
||||
|
||||
// Test query parameter authentication
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+device.ID.String()+"/catalog?token="+device.AuthToken, nil)
|
||||
|
||||
resp, err := client.Do(httpReq)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Should return 200 with catalog (even if empty)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("SearchDeviceCatalog_InvalidDeviceID", func(t *testing.T) {
|
||||
@@ -63,17 +82,19 @@ func TestOPDSEndpoints(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("SearchDeviceCatalog_ValidDevice", func(t *testing.T) {
|
||||
deviceID := uuid.New()
|
||||
// Create a device with auth token
|
||||
deviceSetup := setupDeviceTest(t)
|
||||
device := deviceSetup.CreateDevice(t, "Test OPDS Device", "koreader", "opds-search-test")
|
||||
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+deviceID.String()+"/search?q=test", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+token)
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+device.ID.String()+"/search?q=test", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+device.AuthToken)
|
||||
|
||||
resp, err := client.Do(httpReq)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Should return 200 or 404
|
||||
assert.True(t, resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNotFound)
|
||||
// Should return 200 (even if empty results)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("GetDeviceNavigation_InvalidDeviceID", func(t *testing.T) {
|
||||
@@ -87,10 +108,11 @@ func TestOPDSEndpoints(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("GetDeviceNavigation_ValidDevice", func(t *testing.T) {
|
||||
deviceID := uuid.New()
|
||||
deviceSetup := setupDeviceTest(t)
|
||||
device := deviceSetup.CreateDevice(t, "Test OPDS Device", "koreader", "opds-nav-test")
|
||||
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+deviceID.String()+"/nav", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+token)
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+device.ID.String()+"/nav", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+device.AuthToken)
|
||||
|
||||
resp, err := client.Do(httpReq)
|
||||
require.NoError(t, err)
|
||||
@@ -122,11 +144,12 @@ func TestOPDSEndpoints(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("DownloadBook_ValidIDs", func(t *testing.T) {
|
||||
deviceID := uuid.New()
|
||||
deviceSetup := setupDeviceTest(t)
|
||||
device := deviceSetup.CreateDevice(t, "Test OPDS Device", "koreader", "opds-download-test")
|
||||
bookID := createTestMediaItemID(t, setup.Server, token)
|
||||
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+deviceID.String()+"/download/"+bookID, nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+token)
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+device.ID.String()+"/download/"+bookID, nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+device.AuthToken)
|
||||
|
||||
resp, err := client.Do(httpReq)
|
||||
require.NoError(t, err)
|
||||
@@ -158,11 +181,12 @@ func TestOPDSEndpoints(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("GetCoverImage_ValidIDs", func(t *testing.T) {
|
||||
deviceID := uuid.New()
|
||||
deviceSetup := setupDeviceTest(t)
|
||||
device := deviceSetup.CreateDevice(t, "Test OPDS Device", "koreader", "opds-cover-test")
|
||||
bookID := createTestMediaItemID(t, setup.Server, token)
|
||||
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+deviceID.String()+"/cover/"+bookID, nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+token)
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+device.ID.String()+"/cover/"+bookID, nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+device.AuthToken)
|
||||
|
||||
resp, err := client.Do(httpReq)
|
||||
require.NoError(t, err)
|
||||
@@ -184,11 +208,12 @@ func TestOPDSEndpoints(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("ListFormats_ValidDeviceID", func(t *testing.T) {
|
||||
deviceID := uuid.New()
|
||||
deviceSetup := setupDeviceTest(t)
|
||||
device := deviceSetup.CreateDevice(t, "Test OPDS Device", "koreader", "opds-formats-test")
|
||||
bookID := createTestMediaItemID(t, setup.Server, token)
|
||||
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+deviceID.String()+"/formats/"+bookID, nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+token)
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+device.ID.String()+"/formats/"+bookID, nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+device.AuthToken)
|
||||
|
||||
resp, err := client.Do(httpReq)
|
||||
require.NoError(t, err)
|
||||
@@ -206,12 +231,13 @@ func TestOPDSConversion(t *testing.T) {
|
||||
client := &http.Client{}
|
||||
|
||||
t.Run("DownloadKEPUB_FormatParameter", func(t *testing.T) {
|
||||
deviceID := uuid.New()
|
||||
deviceSetup := setupDeviceTest(t)
|
||||
device := deviceSetup.CreateDevice(t, "Test OPDS Device", "kobo", "opds-kepub-test")
|
||||
bookID := createTestMediaItemID(t, setup.Server, token)
|
||||
|
||||
// Request KEPUB format
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+deviceID.String()+"/download/"+bookID+"?format=kepub", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+token)
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+device.ID.String()+"/download/"+bookID+"?format=kepub", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+device.AuthToken)
|
||||
|
||||
resp, err := client.Do(httpReq)
|
||||
require.NoError(t, err)
|
||||
@@ -223,12 +249,13 @@ func TestOPDSConversion(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("DownloadEPUB_DefaultFormat", func(t *testing.T) {
|
||||
deviceID := uuid.New()
|
||||
deviceSetup := setupDeviceTest(t)
|
||||
device := deviceSetup.CreateDevice(t, "Test OPDS Device", "koreader", "opds-epub-test")
|
||||
bookID := createTestMediaItemID(t, setup.Server, token)
|
||||
|
||||
// Request default format (no format parameter)
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+deviceID.String()+"/download/"+bookID, nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+token)
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+device.ID.String()+"/download/"+bookID, nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+device.AuthToken)
|
||||
|
||||
resp, err := client.Do(httpReq)
|
||||
require.NoError(t, err)
|
||||
@@ -239,12 +266,13 @@ func TestOPDSConversion(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Download_UnsupportedFormat", func(t *testing.T) {
|
||||
deviceID := uuid.New()
|
||||
deviceSetup := setupDeviceTest(t)
|
||||
device := deviceSetup.CreateDevice(t, "Test OPDS Device", "koreader", "opds-unsupported-test")
|
||||
bookID := createTestMediaItemID(t, setup.Server, token)
|
||||
|
||||
// Request unsupported format
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+deviceID.String()+"/download/"+bookID+"?format=pdf", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+token)
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+device.ID.String()+"/download/"+bookID+"?format=pdf", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+device.AuthToken)
|
||||
|
||||
resp, err := client.Do(httpReq)
|
||||
require.NoError(t, err)
|
||||
@@ -259,42 +287,46 @@ func TestOPDSConversion(t *testing.T) {
|
||||
func TestOPDSEdgeCases(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
_ = token // Used for creating media items in device setup
|
||||
client := &http.Client{}
|
||||
|
||||
t.Run("Catalog_EmptyLibrary", func(t *testing.T) {
|
||||
deviceID := uuid.New()
|
||||
deviceSetup := setupDeviceTest(t)
|
||||
device := deviceSetup.CreateDevice(t, "Test OPDS Device", "koreader", "opds-edge-empty")
|
||||
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+deviceID.String()+"/catalog", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+token)
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+device.ID.String()+"/catalog", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+device.AuthToken)
|
||||
|
||||
resp, err := client.Do(httpReq)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Should return empty catalog, not error
|
||||
assert.True(t, resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNotFound)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("Search_SpecialCharacters", func(t *testing.T) {
|
||||
deviceID := uuid.New()
|
||||
deviceSetup := setupDeviceTest(t)
|
||||
device := deviceSetup.CreateDevice(t, "Test OPDS Device", "koreader", "opds-edge-special")
|
||||
|
||||
// Search with special characters
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+deviceID.String()+"/search?q=test%20%26%20more", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+token)
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+device.ID.String()+"/search?q=test%20%26%20more", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+device.AuthToken)
|
||||
|
||||
resp, err := client.Do(httpReq)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Should handle special characters
|
||||
assert.True(t, resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNotFound)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("Search_EmptyQuery", func(t *testing.T) {
|
||||
deviceID := uuid.New()
|
||||
deviceSetup := setupDeviceTest(t)
|
||||
device := deviceSetup.CreateDevice(t, "Test OPDS Device", "koreader", "opds-edge-emptyq")
|
||||
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+deviceID.String()+"/search?q=", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+token)
|
||||
httpReq, _ := http.NewRequest("GET", setup.Server.URL+"/opds/devices/"+device.ID.String()+"/search?q=", nil)
|
||||
httpReq.Header.Set("Authorization", "Bearer "+device.AuthToken)
|
||||
|
||||
resp, err := client.Do(httpReq)
|
||||
require.NoError(t, err)
|
||||
|
||||
Reference in New Issue
Block a user