kleinTodo/tests/sharing_test.go

135 lines
4.2 KiB
Go

package tests
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"
"gitea.kleinsense.nl/DariusKlein/kleinTodo/common"
"gitea.kleinsense.nl/DariusKlein/kleinTodo/server/handler"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestSharedTodoSync(t *testing.T) {
// 1. Setup Environment
tempDir, err := os.MkdirTemp("", "todo-test-*")
require.NoError(t, err)
defer os.RemoveAll(tempDir)
os.Setenv("XDG_CONFIG_HOME", tempDir)
os.Setenv("JWT_SECRET", "test-secret-123")
// 2. Initialize Server
mux := http.NewServeMux()
mux.HandleFunc("POST /register", handler.RegisterHandler)
mux.HandleFunc("POST /login", handler.LoginHandler)
mux.HandleFunc("POST /sync", handler.SyncHandler)
mux.HandleFunc("POST /store", handler.StoreHandler)
ts := httptest.NewServer(mux)
defer ts.Close()
client := ts.Client()
// 3. Register two users
users := []struct {
username, password string
token string
}{
{"owner", "pass1", ""},
{"shared", "pass2", ""},
}
for i, u := range users {
regPayload, _ := json.Marshal(common.Credentials{Username: u.username, Password: u.password})
resp, err := client.Post(ts.URL+"/register", "application/json", bytes.NewBuffer(regPayload))
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
resp, err = client.Post(ts.URL+"/login", "application/json", bytes.NewBuffer(regPayload))
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
users[i].token = resp.Header.Get(common.AuthHeader)
}
// 4. Owner creates a shared todo
sharedTodo := common.Todo{
Id: uuid.New().String(),
Name: "Shared Task",
Description: "This is shared",
Status: common.NotStarted,
Owner: "owner",
SharedWith: []string{"shared"},
LastModified: time.Now().UTC(),
}
syncReq := common.TodoList{Todos: []common.Todo{sharedTodo}}
syncPayload, _ := json.Marshal(syncReq)
req, _ := http.NewRequest("POST", ts.URL+"/sync", bytes.NewBuffer(syncPayload))
req.Header.Set("Content-Type", "application/json")
req.Header.Set(common.AuthHeader, "Bearer "+users[0].token)
resp, err := client.Do(req)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
// 5. Shared user pulls todos
emptySyncReq := common.TodoList{Todos: []common.Todo{}}
emptySyncPayload, _ := json.Marshal(emptySyncReq)
req, _ = http.NewRequest("POST", ts.URL+"/sync", bytes.NewBuffer(emptySyncPayload))
req.Header.Set("Content-Type", "application/json")
req.Header.Set(common.AuthHeader, "Bearer "+users[1].token)
resp, err = client.Do(req)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
var syncResp common.SyncResponse
err = json.NewDecoder(resp.Body).Decode(&syncResp)
require.NoError(t, err)
resp.Body.Close()
// Shared user should see the todo
assert.Len(t, syncResp.SyncedTodos, 1)
assert.Equal(t, "Shared Task", syncResp.SyncedTodos[0].Name)
assert.Equal(t, "owner", syncResp.SyncedTodos[0].Owner)
assert.Contains(t, syncResp.SyncedTodos[0].SharedWith, "shared")
// 6. Shared user updates the todo status
updatedTodo := syncResp.SyncedTodos[0]
updatedTodo.Status = common.Done
updatedTodo.LastModified = time.Now().UTC()
updateSyncReq := common.TodoList{Todos: []common.Todo{updatedTodo}}
updateSyncPayload, _ := json.Marshal(updateSyncReq)
req, _ = http.NewRequest("POST", ts.URL+"/sync", bytes.NewBuffer(updateSyncPayload))
req.Header.Set("Content-Type", "application/json")
req.Header.Set(common.AuthHeader, "Bearer "+users[1].token)
resp, err = client.Do(req)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
// 7. Owner pulls todos and checks status
req, _ = http.NewRequest("POST", ts.URL+"/sync", bytes.NewBuffer(emptySyncPayload))
req.Header.Set("Content-Type", "application/json")
req.Header.Set(common.AuthHeader, "Bearer "+users[0].token)
resp, err = client.Do(req)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
err = json.NewDecoder(resp.Body).Decode(&syncResp)
require.NoError(t, err)
resp.Body.Close()
assert.Len(t, syncResp.SyncedTodos, 1)
assert.Equal(t, common.Done, syncResp.SyncedTodos[0].Status, "Owner should see status update from shared user")
}