From 92b759438dcc83846535216c923792594a41453a Mon Sep 17 00:00:00 2001 From: Gani Georgiev Date: Tue, 8 Oct 2024 12:46:42 +0300 Subject: [PATCH] updated realtime form validator with more human friendly message and added more tests --- apis/realtime.go | 1 + apis/realtime_test.go | 75 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/apis/realtime.go b/apis/realtime.go index 99a714d5..9262ba6b 100644 --- a/apis/realtime.go +++ b/apis/realtime.go @@ -161,6 +161,7 @@ type realtimeSubscribeForm struct { func (form *realtimeSubscribeForm) validate() error { return validation.ValidateStruct(form, validation.Field(&form.ClientId, validation.Required, validation.Length(1, 255)), + validation.Field(&form.Subscriptions, validation.Length(0, 1000)), ) } diff --git a/apis/realtime_test.go b/apis/realtime_test.go index de854b8d..414e1579 100644 --- a/apis/realtime_test.go +++ b/apis/realtime_test.go @@ -3,6 +3,7 @@ package apis_test import ( "context" "errors" + "fmt" "net/http" "strings" "testing" @@ -100,6 +101,15 @@ func TestRealtimeSubscribe(t *testing.T) { client.Set(apis.RealtimeClientAuthKey, nil) } + validSubscriptionsLimit := make([]string, 1000) + for i := 0; i < len(validSubscriptionsLimit); i++ { + validSubscriptionsLimit[i] = fmt.Sprintf(`"%d"`, i) + } + invalidSubscriptionsLimit := make([]string, 1001) + for i := 0; i < len(invalidSubscriptionsLimit); i++ { + invalidSubscriptionsLimit[i] = fmt.Sprintf(`"%d"`, i) + } + scenarios := []tests.ApiScenario{ { Name: "missing client", @@ -110,6 +120,69 @@ func TestRealtimeSubscribe(t *testing.T) { ExpectedContent: []string{`"data":{}`}, ExpectedEvents: map[string]int{"*": 0}, }, + { + Name: "empty data", + Method: http.MethodPost, + URL: "/api/realtime", + Body: strings.NewReader(`{}`), + ExpectedStatus: 400, + ExpectedContent: []string{ + `"data":{`, + `"clientId":{"code":"validation_required`, + }, + NotExpectedContent: []string{ + `"subscriptions"`, + }, + ExpectedEvents: map[string]int{"*": 0}, + }, + { + Name: "existing client with invalid subscriptions limit", + Method: http.MethodPost, + URL: "/api/realtime", + Body: strings.NewReader(`{ + "clientId": "` + client.Id() + `", + "subscriptions": [` + strings.Join(invalidSubscriptionsLimit, ",") + `] + }`), + BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) { + app.SubscriptionsBroker().Register(client) + }, + AfterTestFunc: func(t testing.TB, app *tests.TestApp, res *http.Response) { + resetClient() + }, + ExpectedStatus: 400, + ExpectedContent: []string{ + `"data":{`, + `"subscriptions":{"code":"validation_length_too_long"`, + }, + ExpectedEvents: map[string]int{"*": 0}, + }, + { + Name: "existing client with valid subscriptions limit", + Method: http.MethodPost, + URL: "/api/realtime", + Body: strings.NewReader(`{ + "clientId": "` + client.Id() + `", + "subscriptions": [` + strings.Join(validSubscriptionsLimit, ",") + `] + }`), + ExpectedStatus: 204, + ExpectedEvents: map[string]int{ + "*": 0, + "OnRealtimeSubscribeRequest": 1, + }, + BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) { + client.Subscribe("test0") // should be replaced + app.SubscriptionsBroker().Register(client) + }, + AfterTestFunc: func(t testing.TB, app *tests.TestApp, res *http.Response) { + if len(client.Subscriptions()) != len(validSubscriptionsLimit) { + t.Errorf("Expected %d subscriptions, got %d", len(validSubscriptionsLimit), len(client.Subscriptions())) + } + if client.HasSubscription("test0") { + t.Errorf("Expected old subscriptions to be replaced") + } + resetClient() + }, + }, { Name: "existing client - empty subscriptions", Method: http.MethodPost, @@ -126,7 +199,7 @@ func TestRealtimeSubscribe(t *testing.T) { }, AfterTestFunc: func(t testing.TB, app *tests.TestApp, res *http.Response) { if len(client.Subscriptions()) != 0 { - t.Errorf("Expected no subscriptions, got %v", client.Subscriptions()) + t.Errorf("Expected no subscriptions, got %d", len(client.Subscriptions())) } resetClient() },