Implement TaskUpdateParams builder
- TaskUpdateParams struct with fluent setter methods - NewTaskUpdate() constructor - Setters: SetTitle, SetDescription, SetColor, SetOwner, SetCategory, SetPriority, SetScore, SetDueDate, SetStartDate, SetReference, SetTags - Clear methods: ClearDueDate, ClearStartDate, ClearOwner, ClearCategory - Only set fields are included in update request (partial updates) - Client.UpdateTaskFromParams for fluent task updates - Comprehensive test coverage
This commit is contained in:
parent
28e517289a
commit
0c5b7fd6e9
4 changed files with 451 additions and 1 deletions
271
task_update_params_test.go
Normal file
271
task_update_params_test.go
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
package kanboard
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestNewTaskUpdate(t *testing.T) {
|
||||
params := NewTaskUpdate()
|
||||
|
||||
if params == nil {
|
||||
t.Fatal("expected non-nil TaskUpdateParams")
|
||||
}
|
||||
if params.title != nil {
|
||||
t.Error("expected title to be nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskUpdateParams_Chaining(t *testing.T) {
|
||||
dueDate := time.Date(2025, 12, 31, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
params := NewTaskUpdate().
|
||||
SetTitle("Updated Title").
|
||||
SetDescription("New description").
|
||||
SetColor("red").
|
||||
SetOwner(10).
|
||||
SetCategory(5).
|
||||
SetPriority(2).
|
||||
SetDueDate(dueDate).
|
||||
SetReference("JIRA-456").
|
||||
SetTags("urgent", "review")
|
||||
|
||||
if *params.title != "Updated Title" {
|
||||
t.Errorf("expected title='Updated Title', got %s", *params.title)
|
||||
}
|
||||
if *params.description != "New description" {
|
||||
t.Errorf("expected description='New description', got %s", *params.description)
|
||||
}
|
||||
if *params.colorID != "red" {
|
||||
t.Errorf("expected colorID='red', got %s", *params.colorID)
|
||||
}
|
||||
if *params.ownerID != 10 {
|
||||
t.Errorf("expected ownerID=10, got %d", *params.ownerID)
|
||||
}
|
||||
if *params.categoryID != 5 {
|
||||
t.Errorf("expected categoryID=5, got %d", *params.categoryID)
|
||||
}
|
||||
if *params.priority != 2 {
|
||||
t.Errorf("expected priority=2, got %d", *params.priority)
|
||||
}
|
||||
if *params.dueDate != dueDate.Unix() {
|
||||
t.Errorf("expected dueDate=%d, got %d", dueDate.Unix(), *params.dueDate)
|
||||
}
|
||||
if *params.reference != "JIRA-456" {
|
||||
t.Errorf("expected reference='JIRA-456', got %s", *params.reference)
|
||||
}
|
||||
if len(params.tags) != 2 || params.tags[0] != "urgent" {
|
||||
t.Errorf("expected tags=['urgent', 'review'], got %v", params.tags)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskUpdateParams_SetScore(t *testing.T) {
|
||||
params := NewTaskUpdate().SetScore(5)
|
||||
|
||||
if *params.score != 5 {
|
||||
t.Errorf("expected score=5, got %d", *params.score)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskUpdateParams_SetStartDate(t *testing.T) {
|
||||
startDate := time.Date(2025, 6, 15, 0, 0, 0, 0, time.UTC)
|
||||
params := NewTaskUpdate().SetStartDate(startDate)
|
||||
|
||||
if *params.startDate != startDate.Unix() {
|
||||
t.Errorf("expected startDate=%d, got %d", startDate.Unix(), *params.startDate)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskUpdateParams_ClearDueDate(t *testing.T) {
|
||||
params := NewTaskUpdate().ClearDueDate()
|
||||
|
||||
if params.dueDate == nil {
|
||||
t.Fatal("expected dueDate to be set")
|
||||
}
|
||||
if *params.dueDate != 0 {
|
||||
t.Errorf("expected dueDate=0, got %d", *params.dueDate)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskUpdateParams_ClearStartDate(t *testing.T) {
|
||||
params := NewTaskUpdate().ClearStartDate()
|
||||
|
||||
if *params.startDate != 0 {
|
||||
t.Errorf("expected startDate=0, got %d", *params.startDate)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskUpdateParams_ClearOwner(t *testing.T) {
|
||||
params := NewTaskUpdate().ClearOwner()
|
||||
|
||||
if *params.ownerID != 0 {
|
||||
t.Errorf("expected ownerID=0, got %d", *params.ownerID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskUpdateParams_ClearCategory(t *testing.T) {
|
||||
params := NewTaskUpdate().ClearCategory()
|
||||
|
||||
if *params.categoryID != 0 {
|
||||
t.Errorf("expected categoryID=0, got %d", *params.categoryID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskUpdateParams_toUpdateTaskRequest(t *testing.T) {
|
||||
dueDate := time.Date(2025, 12, 31, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
params := NewTaskUpdate().
|
||||
SetTitle("Updated Title").
|
||||
SetDescription("Details").
|
||||
SetPriority(2).
|
||||
SetDueDate(dueDate).
|
||||
SetTags("urgent")
|
||||
|
||||
req := params.toUpdateTaskRequest(42)
|
||||
|
||||
if req.ID != 42 {
|
||||
t.Errorf("expected ID=42, got %d", req.ID)
|
||||
}
|
||||
if *req.Title != "Updated Title" {
|
||||
t.Errorf("expected Title='Updated Title', got %s", *req.Title)
|
||||
}
|
||||
if *req.Description != "Details" {
|
||||
t.Errorf("expected Description='Details', got %s", *req.Description)
|
||||
}
|
||||
if *req.Priority != 2 {
|
||||
t.Errorf("expected Priority=2, got %d", *req.Priority)
|
||||
}
|
||||
if *req.DateDue != dueDate.Unix() {
|
||||
t.Errorf("expected DateDue=%d, got %d", dueDate.Unix(), *req.DateDue)
|
||||
}
|
||||
if len(req.Tags) != 1 || req.Tags[0] != "urgent" {
|
||||
t.Errorf("expected Tags=['urgent'], got %v", req.Tags)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskUpdateParams_toUpdateTaskRequest_PartialUpdate(t *testing.T) {
|
||||
// Only set title, nothing else
|
||||
params := NewTaskUpdate().SetTitle("New Title")
|
||||
|
||||
req := params.toUpdateTaskRequest(42)
|
||||
|
||||
if *req.Title != "New Title" {
|
||||
t.Errorf("expected Title='New Title', got %s", *req.Title)
|
||||
}
|
||||
// Unset fields should be nil
|
||||
if req.Description != nil {
|
||||
t.Error("expected Description to be nil")
|
||||
}
|
||||
if req.Priority != nil {
|
||||
t.Error("expected Priority to be nil")
|
||||
}
|
||||
if req.OwnerID != nil {
|
||||
t.Error("expected OwnerID to be nil")
|
||||
}
|
||||
if req.Tags != nil {
|
||||
t.Error("expected Tags to be nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskUpdateParams_SetTags_Empty(t *testing.T) {
|
||||
// Explicitly clearing tags
|
||||
params := NewTaskUpdate().SetTags()
|
||||
|
||||
if !params.tagsSet {
|
||||
t.Error("expected tagsSet to be true")
|
||||
}
|
||||
if len(params.tags) != 0 {
|
||||
t.Errorf("expected empty tags, got %v", params.tags)
|
||||
}
|
||||
|
||||
req := params.toUpdateTaskRequest(42)
|
||||
if req.Tags == nil {
|
||||
t.Error("expected Tags to be non-nil (empty slice)")
|
||||
}
|
||||
if len(req.Tags) != 0 {
|
||||
t.Errorf("expected 0 tags, got %d", len(req.Tags))
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_UpdateTaskFromParams(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var req JSONRPCRequest
|
||||
json.NewDecoder(r.Body).Decode(&req)
|
||||
|
||||
if req.Method != "updateTask" {
|
||||
t.Errorf("expected method=updateTask, got %s", req.Method)
|
||||
}
|
||||
|
||||
params := req.Params.(map[string]any)
|
||||
if params["id"].(float64) != 42 {
|
||||
t.Errorf("expected id=42, got %v", params["id"])
|
||||
}
|
||||
if params["title"] != "Updated via Params" {
|
||||
t.Errorf("expected title='Updated via Params', got %v", params["title"])
|
||||
}
|
||||
if params["priority"].(float64) != 3 {
|
||||
t.Errorf("expected priority=3, got %v", params["priority"])
|
||||
}
|
||||
|
||||
resp := JSONRPCResponse{
|
||||
JSONRPC: "2.0",
|
||||
ID: req.ID,
|
||||
Result: json.RawMessage(`true`),
|
||||
}
|
||||
json.NewEncoder(w).Encode(resp)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client := NewClient(server.URL).WithAPIToken("test-token")
|
||||
|
||||
params := NewTaskUpdate().
|
||||
SetTitle("Updated via Params").
|
||||
SetPriority(3)
|
||||
|
||||
err := client.UpdateTaskFromParams(context.Background(), 42, params)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_UpdateTaskFromParams_OnlySetFieldsSent(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var req JSONRPCRequest
|
||||
json.NewDecoder(r.Body).Decode(&req)
|
||||
|
||||
params := req.Params.(map[string]any)
|
||||
|
||||
// Only title should be present, not priority or other fields
|
||||
if _, hasTitle := params["title"]; !hasTitle {
|
||||
t.Error("expected title to be present")
|
||||
}
|
||||
if _, hasPriority := params["priority"]; hasPriority {
|
||||
t.Error("expected priority to NOT be present")
|
||||
}
|
||||
if _, hasOwner := params["owner_id"]; hasOwner {
|
||||
t.Error("expected owner_id to NOT be present")
|
||||
}
|
||||
|
||||
resp := JSONRPCResponse{
|
||||
JSONRPC: "2.0",
|
||||
ID: req.ID,
|
||||
Result: json.RawMessage(`true`),
|
||||
}
|
||||
json.NewEncoder(w).Encode(resp)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client := NewClient(server.URL).WithAPIToken("test-token")
|
||||
|
||||
// Only set title
|
||||
params := NewTaskUpdate().SetTitle("Only Title")
|
||||
|
||||
err := client.UpdateTaskFromParams(context.Background(), 42, params)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue