Fix campaign/listmonk API shapes against confirmed source, not guesses
Read knadh/listmonk's actual Go source (cmd/campaigns.go, cmd/subscribers.go) instead of relying on incomplete public docs. Two corrections: the media attach field is "media" (plain IDs), not "media_ids" as originally guessed; and there's a single query-based bulk list action (PUT /api/subscribers/query/lists) that applies a segment_query server-side, so resolveSegment no longer fetches subscriber IDs client-side before bulk-adding them. Create-status-defaults-to-draft and the test-send "subscribers" field are now confirmed rather than flagged TODO(verify).
This commit is contained in:
@@ -98,28 +98,7 @@ func TestFindOrCreateListByName_CreatesWhenMissing(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestQuerySubscriberIDs_UsesPerPageAllAndParsesIDs(t *testing.T) {
|
||||
var gotPath string
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
gotPath = r.URL.RequestURI()
|
||||
w.Write([]byte(`{"data":{"results":[{"id":1},{"id":2}]}}`))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
c := New(srv.URL, "u", "t")
|
||||
ids, err := c.QuerySubscriberIDs("subscribers.attribs->>'source' = 'workshop'")
|
||||
if err != nil {
|
||||
t.Fatalf("QuerySubscriberIDs: %v", err)
|
||||
}
|
||||
if !strings.Contains(gotPath, "per_page=all") {
|
||||
t.Errorf("expected per_page=all, got %q", gotPath)
|
||||
}
|
||||
if len(ids) != 2 || ids[0] != 1 || ids[1] != 2 {
|
||||
t.Errorf("expected [1 2], got %v", ids)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBulkAddToList_SendsExpectedPayload(t *testing.T) {
|
||||
func TestQueryAddToList_SendsExpectedPayload(t *testing.T) {
|
||||
var gotMethod, gotPath string
|
||||
var gotBody map[string]any
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -132,34 +111,35 @@ func TestBulkAddToList_SendsExpectedPayload(t *testing.T) {
|
||||
defer srv.Close()
|
||||
|
||||
c := New(srv.URL, "u", "t")
|
||||
if err := c.BulkAddToList([]int{1, 2, 3}, 9); err != nil {
|
||||
t.Fatalf("BulkAddToList: %v", err)
|
||||
query := "subscribers.attribs->>'source' = 'workshop'"
|
||||
if err := c.QueryAddToList(query, 9); err != nil {
|
||||
t.Fatalf("QueryAddToList: %v", err)
|
||||
}
|
||||
if gotMethod != http.MethodPut {
|
||||
t.Errorf("expected PUT, got %s", gotMethod)
|
||||
}
|
||||
if gotPath != "/api/subscribers/lists" {
|
||||
t.Errorf("expected /api/subscribers/lists, got %q", gotPath)
|
||||
if gotPath != "/api/subscribers/query/lists" {
|
||||
t.Errorf("expected /api/subscribers/query/lists, got %q", gotPath)
|
||||
}
|
||||
if gotBody["query"] != query {
|
||||
t.Errorf("expected query sent verbatim, got %+v", gotBody)
|
||||
}
|
||||
if gotBody["action"] != "add" {
|
||||
t.Errorf("expected action=add, got %+v", gotBody)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBulkAddToList_NoopOnEmptyIDs(t *testing.T) {
|
||||
var calls int
|
||||
func TestQueryAddToList_SurfacesListmonkErrors(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
calls++
|
||||
w.Write([]byte(`{}`))
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(`{"message":"invalid SQL expression"}`))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
c := New(srv.URL, "u", "t")
|
||||
if err := c.BulkAddToList(nil, 9); err != nil {
|
||||
t.Fatalf("BulkAddToList: %v", err)
|
||||
}
|
||||
if calls != 0 {
|
||||
t.Errorf("expected no request for empty id list, got %d", calls)
|
||||
err := c.QueryAddToList("not valid sql", 9)
|
||||
if err == nil || !strings.Contains(err.Error(), "invalid SQL expression") {
|
||||
t.Fatalf("expected listmonk's error message to surface, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user