(t *testing.T)
| 153 | } |
| 154 | |
| 155 | func TestSendSMS_RateLimit(t *testing.T) { |
| 156 | ctx := context.Background() |
| 157 | phone := setupPhone(ctx, t, 10) |
| 158 | |
| 159 | signingKey, webhookPath := setupWebhook(ctx, t, phone.PhoneNumber, []string{ |
| 160 | "message.phone.sent", |
| 161 | "message.phone.delivered", |
| 162 | }) |
| 163 | |
| 164 | client := newAPIClient() |
| 165 | contactNumber := randomPhoneNumber() |
| 166 | |
| 167 | sendResp1, resp1, err := client.Messages.Send(ctx, &httpsms.MessageSendParams{ |
| 168 | From: phone.PhoneNumber, |
| 169 | To: contactNumber, |
| 170 | Content: "Rate limit test message 1", |
| 171 | }) |
| 172 | require.NoError(t, err) |
| 173 | require.Equal(t, http.StatusOK, resp1.HTTPResponse.StatusCode) |
| 174 | msgID1 := sendResp1.Data.ID.String() |
| 175 | |
| 176 | sendResp2, resp2, err := client.Messages.Send(ctx, &httpsms.MessageSendParams{ |
| 177 | From: phone.PhoneNumber, |
| 178 | To: contactNumber, |
| 179 | Content: "Rate limit test message 2", |
| 180 | }) |
| 181 | require.NoError(t, err) |
| 182 | require.Equal(t, http.StatusOK, resp2.HTTPResponse.StatusCode) |
| 183 | msgID2 := sendResp2.Data.ID.String() |
| 184 | |
| 185 | t.Logf("sent messages: %s, %s", msgID1, msgID2) |
| 186 | |
| 187 | fcm1 := waitForFCMPush(t, msgID1, 30*time.Second) |
| 188 | require.Len(t, fcm1, 1) |
| 189 | |
| 190 | fcm2 := waitForFCMPush(t, msgID2, 30*time.Second) |
| 191 | require.Len(t, fcm2, 1) |
| 192 | |
| 193 | time1 := fcm1[0].Request.LoggedDate |
| 194 | time2 := fcm2[0].Request.LoggedDate |
| 195 | gapMs := time2 - time1 |
| 196 | if gapMs < 0 { |
| 197 | gapMs = time1 - time2 |
| 198 | } |
| 199 | t.Logf("FCM push gap: %dms", gapMs) |
| 200 | assert.GreaterOrEqual(t, gapMs, int64(5500), "rate limit gap should be >= 5500ms (6s minus timing tolerance), got %dms", gapMs) |
| 201 | |
| 202 | fireEvent(ctx, t, phone.PhoneAPIKey, msgID1, "SENT") |
| 203 | fireEvent(ctx, t, phone.PhoneAPIKey, msgID1, "DELIVERED") |
| 204 | fireEvent(ctx, t, phone.PhoneAPIKey, msgID2, "SENT") |
| 205 | fireEvent(ctx, t, phone.PhoneAPIKey, msgID2, "DELIVERED") |
| 206 | |
| 207 | msg1 := pollMessageStatus(ctx, t, msgID1, "delivered", 15*time.Second) |
| 208 | msg2 := pollMessageStatus(ctx, t, msgID2, "delivered", 15*time.Second) |
| 209 | assert.Equal(t, "delivered", msg1.Status) |
| 210 | assert.Equal(t, "delivered", msg2.Status) |
| 211 | |
| 212 | webhookReqs := waitForWebhookEvents(t, webhookPath, 4, 30*time.Second) |
nothing calls this directly
no test coverage detected