| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
- // SPDX-License-Identifier: Apache-2.0
- package wallabag
- import (
- "encoding/json"
- "io"
- "net/http"
- "net/http/httptest"
- "strings"
- "testing"
- )
- func TestCreateEntry(t *testing.T) {
- entryURL := "https://example.com"
- entryTitle := "title"
- entryContent := "content"
- tags := "tag1,tag2,tag3"
- tests := []struct {
- name string
- username string
- password string
- clientID string
- clientSecret string
- tags string
- onlyURL bool
- entryURL string
- entryTitle string
- entryContent string
- serverResponse func(w http.ResponseWriter, r *http.Request)
- wantErr bool
- errContains string
- }{
- {
- name: "successful entry creation with url only",
- wantErr: false,
- onlyURL: true,
- username: "username",
- password: "password",
- clientID: "clientId",
- clientSecret: "clientSecret",
- tags: tags,
- entryURL: entryURL,
- entryTitle: entryTitle,
- entryContent: entryContent,
- serverResponse: func(w http.ResponseWriter, r *http.Request) {
- if strings.Contains(r.URL.Path, "/oauth/v2/token") {
- // Return success response
- w.WriteHeader(http.StatusOK)
- json.NewEncoder(w).Encode(map[string]any{
- "access_token": "test-token",
- "expires_in": 3600,
- "refresh_token": "token",
- "scope": "scope",
- "token_type": "token_type",
- })
- return
- }
- // Verify authorization header
- auth := r.Header.Get("Authorization")
- if auth != "Bearer test-token" {
- t.Errorf("Expected Authorization header 'Bearer test-token', got %s", auth)
- }
- // Verify content type
- contentType := r.Header.Get("Content-Type")
- if contentType != "application/json" {
- t.Errorf("Expected Content-Type 'application/json', got %s", contentType)
- }
- // Parse and verify request
- body, _ := io.ReadAll(r.Body)
- var req map[string]any
- if err := json.Unmarshal(body, &req); err != nil {
- t.Errorf("Failed to parse request body: %v", err)
- }
- if requstEntryURL := req["url"]; requstEntryURL != entryURL {
- t.Errorf("Expected entryURL %s, got %s", entryURL, requstEntryURL)
- }
- if requestEntryTitle := req["title"]; requestEntryTitle != entryTitle {
- t.Errorf("Expected entryTitle %s, got %s", entryTitle, requestEntryTitle)
- }
- if _, ok := req["content"]; ok {
- t.Errorf("Expected entryContent to be empty, got value")
- }
- if requestTags := req["tags"]; requestTags != tags {
- t.Errorf("Expected tags %s, got %s", tags, requestTags)
- } // Return success response
- w.WriteHeader(http.StatusOK)
- },
- errContains: "",
- },
- {
- name: "successful entry creation with content",
- wantErr: false,
- onlyURL: false,
- username: "username",
- password: "password",
- clientID: "clientId",
- clientSecret: "clientSecret",
- tags: tags,
- entryURL: entryURL,
- entryTitle: entryTitle,
- entryContent: entryContent,
- serverResponse: func(w http.ResponseWriter, r *http.Request) {
- if strings.Contains(r.URL.Path, "/oauth/v2/token") {
- // Return success response
- w.WriteHeader(http.StatusOK)
- json.NewEncoder(w).Encode(map[string]any{
- "access_token": "test-token",
- "expires_in": 3600,
- "refresh_token": "token",
- "scope": "scope",
- "token_type": "token_type",
- })
- return
- }
- // Verify authorization header
- auth := r.Header.Get("Authorization")
- if auth != "Bearer test-token" {
- t.Errorf("Expected Authorization header 'Bearer test-token', got %s", auth)
- }
- // Verify content type
- contentType := r.Header.Get("Content-Type")
- if contentType != "application/json" {
- t.Errorf("Expected Content-Type 'application/json', got %s", contentType)
- }
- // Parse and verify request
- body, _ := io.ReadAll(r.Body)
- var req map[string]any
- if err := json.Unmarshal(body, &req); err != nil {
- t.Errorf("Failed to parse request body: %v", err)
- }
- if requstEntryURL := req["url"]; requstEntryURL != entryURL {
- t.Errorf("Expected entryURL %s, got %s", entryURL, requstEntryURL)
- }
- if requestEntryTitle := req["title"]; requestEntryTitle != entryTitle {
- t.Errorf("Expected entryTitle %s, got %s", entryTitle, requestEntryTitle)
- }
- if requestEntryContent := req["content"]; requestEntryContent != entryContent {
- t.Errorf("Expected entryContent %s, got %s", entryContent, requestEntryContent)
- }
- if requestTags := req["tags"]; requestTags != tags {
- t.Errorf("Expected tags %s, got %s", tags, requestTags)
- } // Return success response
- w.WriteHeader(http.StatusOK)
- },
- errContains: "",
- },
- {
- name: "failed when unable to decode accessToken response",
- wantErr: true,
- onlyURL: true,
- username: "username",
- password: "password",
- clientID: "clientId",
- clientSecret: "clientSecret",
- tags: tags,
- entryURL: entryURL,
- entryTitle: entryTitle,
- entryContent: entryContent,
- serverResponse: func(w http.ResponseWriter, r *http.Request) {
- if strings.Contains(r.URL.Path, "/oauth/v2/token") {
- // Return success response
- w.WriteHeader(http.StatusOK)
- w.Write([]byte("invalid json"))
- return
- }
- t.Error("Server should not be called when failed to get accessToken")
- },
- errContains: "unable to decode token response",
- },
- {
- name: "failed when saving entry",
- wantErr: true,
- onlyURL: true,
- username: "username",
- password: "password",
- clientID: "clientId",
- clientSecret: "clientSecret",
- tags: tags,
- entryURL: entryURL,
- entryTitle: entryTitle,
- entryContent: entryContent,
- serverResponse: func(w http.ResponseWriter, r *http.Request) {
- if strings.Contains(r.URL.Path, "/oauth/v2/token") {
- // Return success response
- w.WriteHeader(http.StatusOK)
- json.NewEncoder(w).Encode(map[string]any{
- "access_token": "test-token",
- "expires_in": 3600,
- "refresh_token": "token",
- "scope": "scope",
- "token_type": "token_type",
- })
- return
- }
- w.WriteHeader(http.StatusUnauthorized)
- },
- errContains: "unable to get save entry",
- },
- {
- name: "failure due to no accessToken",
- wantErr: true,
- onlyURL: false,
- username: "username",
- password: "password",
- clientID: "clientId",
- clientSecret: "clientSecret",
- tags: tags,
- entryURL: entryURL,
- entryTitle: entryTitle,
- entryContent: entryContent,
- serverResponse: func(w http.ResponseWriter, r *http.Request) {
- if strings.Contains(r.URL.Path, "/oauth/v2/token") {
- // Return error response
- w.WriteHeader(http.StatusUnauthorized)
- return
- }
- t.Error("Server should not be called when failed to get accessToken")
- },
- errContains: "unable to get access token",
- },
- {
- name: "failure due to missing client parameters",
- wantErr: true,
- onlyURL: false,
- tags: tags,
- entryURL: entryURL,
- entryTitle: entryTitle,
- entryContent: entryContent,
- serverResponse: func(w http.ResponseWriter, r *http.Request) {
- t.Error("Server should not be called when failed to get accessToken")
- },
- errContains: "wallabag: missing base URL, client ID, client secret, username or password",
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- // Create test server if we have a server response function
- var serverURL string
- if tt.serverResponse != nil {
- server := httptest.NewServer(http.HandlerFunc(tt.serverResponse))
- defer server.Close()
- serverURL = server.URL
- }
- // Create client with test server URL
- client := NewClient(serverURL, tt.clientID, tt.clientSecret, tt.username, tt.password, tt.tags, tt.onlyURL)
- // Call CreateBookmark
- err := client.CreateEntry(tt.entryURL, tt.entryTitle, tt.entryContent)
- // Check error expectations
- if tt.wantErr {
- if err == nil {
- t.Errorf("Expected error but got none")
- } else if tt.errContains != "" && !strings.Contains(err.Error(), tt.errContains) {
- t.Errorf("Expected error containing '%s', got '%s'", tt.errContains, err.Error())
- }
- } else {
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- }
- })
- }
- }
- func TestNewClient(t *testing.T) {
- tests := []struct {
- name string
- baseURL string
- clientID string
- clientSecret string
- username string
- password string
- tags string
- onlyURL bool
- }{
- {
- name: "with all parameters",
- baseURL: "https://wallabag.example.com",
- clientID: "clientID",
- clientSecret: "clientSecret",
- username: "wallabag",
- password: "wallabag",
- tags: "",
- onlyURL: true,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- client := NewClient(tt.baseURL, tt.clientID, tt.clientSecret, tt.username, tt.password, tt.tags, tt.onlyURL)
- if client.baseURL != tt.baseURL {
- t.Errorf("Expected.baseURL %s, got %s", tt.baseURL, client.baseURL)
- }
- if client.username != tt.username {
- t.Errorf("Expected username %s, got %s", tt.username, client.username)
- }
- if client.password != tt.password {
- t.Errorf("Expected password %s, got %s", tt.password, client.password)
- }
- if client.clientID != tt.clientID {
- t.Errorf("Expected clientID %s, got %s", tt.clientID, client.clientID)
- }
- if client.clientSecret != tt.clientSecret {
- t.Errorf("Expected clientSecret %s, got %s", tt.clientSecret, client.clientSecret)
- }
- if client.tags != tt.tags {
- t.Errorf("Expected tags %s, got %s", tt.tags, client.tags)
- }
- if client.onlyURL != tt.onlyURL {
- t.Errorf("Expected onlyURL %v, got %v", tt.onlyURL, client.onlyURL)
- }
- })
- }
- }
|