import Testing import Foundation @testable import Mobile_Music_Assistant // MARK: - imageProxyURL @Suite("MAService.imageProxyURL") struct ImageProxyURLTests { private var service: MAService { MAService() } @Test("Returns nil for nil path") func nilPath() { let s = service #expect(s.imageProxyURL(path: nil) == nil) } @Test("Returns nil for empty path") func emptyPath() { let s = service #expect(s.imageProxyURL(path: "") == nil) } @Test("Returns nil when no server URL is configured") func noServerURL() { // Fresh MAService with cleared credentials has no serverURL let s = service s.authManager.logout() #expect(s.imageProxyURL(path: "/some/path") == nil) } @Test("Builds correct URL with path and size") func buildsURL() throws { let s = service s.authManager.logout() try s.authManager.saveToken(serverURL: URL(string: "http://192.168.1.1:8095")!, token: "tok") defer { s.authManager.logout() } let url = try #require(s.imageProxyURL(path: "/img/art.jpg", size: 256)) #expect(url.host == "192.168.1.1") #expect(url.path == "/imageproxy") let query = url.query ?? "" #expect(query.contains("size=256")) #expect(query.contains("path=")) } @Test("Double-encodes special characters in path") func doubleEncodesPath() throws { let s = service s.authManager.logout() try s.authManager.saveToken(serverURL: URL(string: "http://192.168.1.1:8095")!, token: "tok") defer { s.authManager.logout() } let url = try #require(s.imageProxyURL(path: "http://cdn.example.com/img?x=1&y=2")) let query = url.query ?? "" // The path param must be double-encoded — raw '?' and '&' must not appear unencoded #expect(!query.contains("path=http://cdn")) #expect(query.contains("path=")) } @Test("Appends provider when given") func appendsProvider() throws { let s = service s.authManager.logout() try s.authManager.saveToken(serverURL: URL(string: "http://192.168.1.1:8095")!, token: "tok") defer { s.authManager.logout() } let url = try #require(s.imageProxyURL(path: "/art.jpg", provider: "spotify", size: 128)) let query = url.query ?? "" #expect(query.contains("provider=spotify")) } @Test("Omits provider param when provider is nil") func omitsProviderWhenNil() throws { let s = service s.authManager.logout() try s.authManager.saveToken(serverURL: URL(string: "http://192.168.1.1:8095")!, token: "tok") defer { s.authManager.logout() } let url = try #require(s.imageProxyURL(path: "/art.jpg", provider: nil, size: 128)) #expect(!(url.query ?? "").contains("provider=")) } @Test("Default size is 256") func defaultSize() throws { let s = service s.authManager.logout() try s.authManager.saveToken(serverURL: URL(string: "http://192.168.1.1:8095")!, token: "tok") defer { s.authManager.logout() } let url = try #require(s.imageProxyURL(path: "/art.jpg")) #expect((url.query ?? "").contains("size=256")) } } // MARK: - MAAuthManager @Suite("MAAuthManager") struct MAAuthManagerTests { @Test("After logout, isAuthenticated is false") func notAuthenticatedAfterLogout() { let auth = MAAuthManager() auth.logout() #expect(auth.isAuthenticated == false) #expect(auth.currentToken == nil) #expect(auth.serverURL == nil) } @Test("saveToken sets serverURL and token") func saveTokenSetsCredentials() throws { let auth = MAAuthManager() auth.logout() defer { auth.logout() } let url = URL(string: "http://192.168.1.1:8095")! try auth.saveToken(serverURL: url, token: "mytoken123") #expect(auth.isAuthenticated == true) #expect(auth.currentToken == "mytoken123") #expect(auth.serverURL == url) } @Test("logout clears all credentials") func logoutClearsCredentials() throws { let auth = MAAuthManager() try auth.saveToken(serverURL: URL(string: "http://192.168.1.1:8095")!, token: "tok") auth.logout() #expect(auth.isAuthenticated == false) #expect(auth.currentToken == nil) } }