From 273776e907df32fdbebc8d68ba7f7e713910fe8b Mon Sep 17 00:00:00 2001 From: Yvonne Pan <103622026+yvonnep165@users.noreply.github.com> Date: Wed, 27 May 2026 16:35:47 -0400 Subject: [PATCH 1/7] Add fid and deprecate token for the Message struct --- integration/messaging/messaging_test.go | 7 +++++++ messaging/messaging.go | 6 ++++-- messaging/messaging_test.go | 17 +++++++++++++++-- messaging/messaging_utils.go | 4 ++-- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/integration/messaging/messaging_test.go b/integration/messaging/messaging_test.go index 4552988a..6deedbf1 100644 --- a/integration/messaging/messaging_test.go +++ b/integration/messaging/messaging_test.go @@ -105,6 +105,13 @@ func TestSendInvalidToken(t *testing.T) { } } +func TestSendInvalidFid(t *testing.T) { + msg := &messaging.Message{Fid: "INVALID_FID"} + if _, err := client.Send(context.Background(), msg); err == nil || !messaging.IsUnregistered(err) { + t.Errorf("Send() = %v; want UnregisteredError", err) + } +} + func TestSendEach(t *testing.T) { messages := []*messaging.Message{ { diff --git a/messaging/messaging.go b/messaging/messaging.go index 67b94f66..ca49d8be 100644 --- a/messaging/messaging.go +++ b/messaging/messaging.go @@ -58,7 +58,7 @@ var ( // Message to be sent via Firebase Cloud Messaging. // // Message contains payload data, recipient information and platform-specific configuration -// options. A Message must specify exactly one of Token, Topic or Condition fields. Apart from +// options. A Message must specify exactly one of Fid, Token, Topic or Condition fields. Apart from // that a Message may specify any combination of Data, Notification, Android, Webpush and APNS // fields. See https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages for more // details on how the backend FCM servers handle different message parameters. @@ -69,9 +69,11 @@ type Message struct { Webpush *WebpushConfig `json:"webpush,omitempty"` APNS *APNSConfig `json:"apns,omitempty"` FCMOptions *FCMOptions `json:"fcm_options,omitempty"` + // Deprecated: use `Fid` instead Token string `json:"token,omitempty"` Topic string `json:"-"` Condition string `json:"condition,omitempty"` + Fid string `json:"fid,omitempty"` } // MarshalJSON marshals a Message into JSON (for internal use only). @@ -958,7 +960,7 @@ func newFCMClient(hc *http.Client, conf *internal.MessagingConfig, messagingEndp // Send sends a Message to Firebase Cloud Messaging. // -// The Message must specify exactly one of Token, Topic and Condition fields. FCM will +// The Message must specify exactly one of Fid, Token, Topic or Condition fields. FCM will // customize the message for each target platform based on the arguments specified in the // Message. func (c *fcmClient) Send(ctx context.Context, message *Message) (string, error) { diff --git a/messaging/messaging_test.go b/messaging/messaging_test.go index 5ba548af..00d4fee9 100644 --- a/messaging/messaging_test.go +++ b/messaging/messaging_test.go @@ -60,6 +60,11 @@ var validMessages = []struct { req: &Message{Token: "test-token"}, want: map[string]interface{}{"token": "test-token"}, }, + { + name: "FidOnly", + req: &Message{Fid: "test-fid"}, + want: map[string]interface{}{"fid": "test-fid"}, + }, { name: "TopicOnly", req: &Message{Topic: "test-topic"}, @@ -774,7 +779,7 @@ var invalidMessages = []struct { { name: "NoTargets", req: &Message{}, - want: "exactly one of token, topic or condition must be specified", + want: "exactly one of fid, token, topic or condition must be specified", }, { name: "MultipleTargets", @@ -782,7 +787,15 @@ var invalidMessages = []struct { Token: "token", Topic: "topic", }, - want: "exactly one of token, topic or condition must be specified", + want: "exactly one of fid, token, topic or condition must be specified", + }, + { + name: "MultipleTargetsWithFid", + req: &Message{ + Fid: "fid", + Topic: "topic", + }, + want: "exactly one of fid, token, topic or condition must be specified", }, { name: "InvalidPrefixedTopicName", diff --git a/messaging/messaging_utils.go b/messaging/messaging_utils.go index 5716b328..49fec654 100644 --- a/messaging/messaging_utils.go +++ b/messaging/messaging_utils.go @@ -33,9 +33,9 @@ func validateMessage(message *Message) error { return fmt.Errorf("message must not be nil") } - targets := countNonEmpty(message.Token, message.Condition, message.Topic) + targets := countNonEmpty(message.Token, message.Condition, message.Topic, message.Fid) if targets != 1 { - return fmt.Errorf("exactly one of token, topic or condition must be specified") + return fmt.Errorf("exactly one of fid, token, topic or condition must be specified") } // validate topic From 8fe938ab59be08179ffdda7237831f3184ffd9c8 Mon Sep 17 00:00:00 2001 From: Yvonne Pan <103622026+yvonnep165@users.noreply.github.com> Date: Thu, 28 May 2026 21:31:34 -0400 Subject: [PATCH 2/7] Add fids and deprecate tokens for MulticastMessage --- integration/messaging/messaging_test.go | 38 +++++++ messaging/messaging.go | 4 +- messaging/messaging_batch.go | 30 +++-- messaging/messaging_batch_test.go | 143 +++++++++++++++++++++++- 4 files changed, 202 insertions(+), 13 deletions(-) diff --git a/integration/messaging/messaging_test.go b/integration/messaging/messaging_test.go index 6deedbf1..7c123b7f 100644 --- a/integration/messaging/messaging_test.go +++ b/integration/messaging/messaging_test.go @@ -236,6 +236,44 @@ func TestSendEachForMulticast(t *testing.T) { } } +func TestSendEachForMulticastFids(t *testing.T) { + message := &messaging.MulticastMessage{ + Notification: &messaging.Notification{ + Title: "title", + Body: "body", + }, + Fids: []string{"INVALID_FID", "ANOTHER_INVALID_FID"}, + } + + br, err := client.SendEachForMulticastDryRun(context.Background(), message) + if err != nil { + t.Fatal(err) + } + + if len(br.Responses) != 2 { + t.Errorf("len(Responses) = %d; want = 2", len(br.Responses)) + } + if br.SuccessCount != 0 { + t.Errorf("SuccessCount = %d; want = 0", br.SuccessCount) + } + if br.FailureCount != 2 { + t.Errorf("FailureCount = %d; want = 2", br.FailureCount) + } + + for i := 0; i < 2; i++ { + sr := br.Responses[i] + if sr.Success { + t.Errorf("Responses[%d]: Success = true; want = false", i) + } + if sr.MessageID != "" { + t.Errorf("Responses[%d]: MessageID = %q; want = %q", i, sr.MessageID, "") + } + if sr.Error == nil || !messaging.IsUnregistered(sr.Error) { + t.Errorf("Responses[%d]: Error = %v; want = UnregisteredError", i, sr.Error) + } + } +} + func TestSendAll(t *testing.T) { t.Skip("Skipping integration tests for deprecated sendAll() API") messages := []*messaging.Message{ diff --git a/messaging/messaging.go b/messaging/messaging.go index ca49d8be..dcf4a05d 100644 --- a/messaging/messaging.go +++ b/messaging/messaging.go @@ -1056,8 +1056,8 @@ func IsRegistrationTokenNotRegistered(err error) bool { return IsUnregistered(err) } -// IsUnregistered checks if the given error was due to a registration token that -// became invalid. +// IsUnregistered checks if the given error was due to a registration token or +// installation ID (FID) that was unregistered or became invalid. func IsUnregistered(err error) bool { return hasMessagingErrorCode(err, unregistered) } diff --git a/messaging/messaging_batch.go b/messaging/messaging_batch.go index 03129587..ea323604 100644 --- a/messaging/messaging_batch.go +++ b/messaging/messaging_batch.go @@ -37,9 +37,11 @@ const multipartBoundary = "__END_OF_PART__" // MulticastMessage represents a message that can be sent to multiple devices via Firebase Cloud // Messaging (FCM). // -// It contains payload information as well as the list of device registration tokens to which the -// message should be sent. A single MulticastMessage may contain up to 500 registration tokens. +// It contains payload information as well as the list of device registration tokens and/or +// Firebase Installation IDs (FIDs) to which the message should be sent. A single +// MulticastMessage may contain up to 500 registration tokens and FIDs combined. type MulticastMessage struct { + // Deprecated: use `Fids` instead. Tokens []string Data map[string]string Notification *Notification @@ -47,17 +49,19 @@ type MulticastMessage struct { Webpush *WebpushConfig APNS *APNSConfig FCMOptions *FCMOptions + Fids []string } func (mm *MulticastMessage) toMessages() ([]*Message, error) { - if len(mm.Tokens) == 0 { - return nil, errors.New("tokens must not be nil or empty") + if len(mm.Tokens) == 0 && len(mm.Fids) == 0 { + return nil, errors.New("either tokens or fids must be specified") } - if len(mm.Tokens) > maxMessages { - return nil, fmt.Errorf("tokens must not contain more than %d elements", maxMessages) + total := len(mm.Tokens) + len(mm.Fids) + if total > maxMessages { + return nil, fmt.Errorf("total tokens and fids must not exceed %d elements", maxMessages) } - var messages []*Message + messages := make([]*Message, 0, total) for _, token := range mm.Tokens { temp := &Message{ Token: token, @@ -70,6 +74,18 @@ func (mm *MulticastMessage) toMessages() ([]*Message, error) { } messages = append(messages, temp) } + for _, fid := range mm.Fids { + temp := &Message{ + Fid: fid, + Data: mm.Data, + Notification: mm.Notification, + Android: mm.Android, + Webpush: mm.Webpush, + APNS: mm.APNS, + FCMOptions: mm.FCMOptions, + } + messages = append(messages, temp) + } return messages, nil } diff --git a/messaging/messaging_batch_test.go b/messaging/messaging_batch_test.go index ed9a1a42..771ae8f5 100644 --- a/messaging/messaging_batch_test.go +++ b/messaging/messaging_batch_test.go @@ -37,6 +37,13 @@ var testMessages = []*Message{{Topic: "topic1"}, {Topic: "topic2"}} var testMulticastMessage = &MulticastMessage{ Tokens: []string{"token1", "token2"}, } +var testFidMulticastMessage = &MulticastMessage{ + Fids: []string{"fid1", "fid2"}, +} +var testMixedMulticastMessage = &MulticastMessage{ + Tokens: []string{"token1"}, + Fids: []string{"fid2"}, +} var testSuccessResponse = []fcmResponse{ {Name: "projects/test-project/messages/1"}, {Name: "projects/test-project/messages/2"}, @@ -642,7 +649,7 @@ func TestSendEachForMulticastEmptyArray(t *testing.T) { t.Fatal(err) } - want := "tokens must not be nil or empty" + want := "either tokens or fids must be specified" mm := &MulticastMessage{} br, err := client.SendEachForMulticast(ctx, mm) if err == nil || err.Error() != want { @@ -657,6 +664,15 @@ func TestSendEachForMulticastEmptyArray(t *testing.T) { if err == nil || err.Error() != want { t.Errorf("SendEachForMulticast(Tokens: []) = (%v, %v); want = (nil, %q)", br, err, want) } + + var fids []string + mm = &MulticastMessage{ + Fids: fids, + } + br, err = client.SendEachForMulticast(ctx, mm) + if err == nil || err.Error() != want { + t.Errorf("SendEachForMulticast(Fids: []) = (%v, %v); want = (nil, %q)", br, err, want) + } } func TestSendEachForMulticastTooManyTokens(t *testing.T) { @@ -671,12 +687,36 @@ func TestSendEachForMulticastTooManyTokens(t *testing.T) { tokens = append(tokens, fmt.Sprintf("token%d", i)) } - want := "tokens must not contain more than 500 elements" + want := "total tokens and fids must not exceed 500 elements" mm := &MulticastMessage{Tokens: tokens} br, err := client.SendEachForMulticast(ctx, mm) if err == nil || err.Error() != want { t.Errorf("SendEachForMulticast() = (%v, %v); want = (nil, %q)", br, err, want) } + + var fids []string + for i := 0; i < 501; i++ { + fids = append(fids, fmt.Sprintf("fid%d", i)) + } + mm = &MulticastMessage{Fids: fids} + br, err = client.SendEachForMulticast(ctx, mm) + if err == nil || err.Error() != want { + t.Errorf("SendEachForMulticast() = (%v, %v); want = (nil, %q)", br, err, want) + } + + mixedTokens := []string{} + mixedFids := []string{} + for i := 0; i < 250; i++ { + mixedTokens = append(mixedTokens, fmt.Sprintf("token%d", i)) + } + for i := 0; i < 251; i++ { + mixedFids = append(mixedFids, fmt.Sprintf("fid%d", i)) + } + mm = &MulticastMessage{Tokens: mixedTokens, Fids: mixedFids} + br, err = client.SendEachForMulticast(ctx, mm) + if err == nil || err.Error() != want { + t.Errorf("SendEachForMulticast() = (%v, %v); want = (nil, %q)", br, err, want) + } } func TestSendEachForMulticastInvalidMessage(t *testing.T) { @@ -725,6 +765,67 @@ func TestSendEachForMulticast(t *testing.T) { } } +func TestSendEachForMulticastFids(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + req, _ := ioutil.ReadAll(r.Body) + w.Header().Set("Content-Type", "application/json") + for idx, fid := range testFidMulticastMessage.Fids { + if strings.Contains(string(req), fid) { + w.Write([]byte("{ \"name\":\"" + testSuccessResponse[idx].Name + "\" }")) + } + } + })) + defer ts.Close() + ctx := context.Background() + client, err := NewClient(ctx, testMessagingConfig) + if err != nil { + t.Fatal(err) + } + client.fcmEndpoint = ts.URL + + br, err := client.SendEachForMulticast(ctx, testFidMulticastMessage) + if err != nil { + t.Fatal(err) + } + + if err := checkSuccessfulBatchResponseForSendEach(br, false); err != nil { + t.Errorf("SendEachForMulticast() = %v", err) + } +} + +func TestSendEachForMulticastMixed(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + req, _ := ioutil.ReadAll(r.Body) + w.Header().Set("Content-Type", "application/json") + for idx, token := range testMixedMulticastMessage.Tokens { + if strings.Contains(string(req), token) { + w.Write([]byte("{ \"name\":\"" + testSuccessResponse[idx].Name + "\" }")) + } + } + for idx, fid := range testMixedMulticastMessage.Fids { + if strings.Contains(string(req), fid) { + w.Write([]byte("{ \"name\":\"" + testSuccessResponse[idx+1].Name + "\" }")) + } + } + })) + defer ts.Close() + ctx := context.Background() + client, err := NewClient(ctx, testMessagingConfig) + if err != nil { + t.Fatal(err) + } + client.fcmEndpoint = ts.URL + + br, err := client.SendEachForMulticast(ctx, testMixedMulticastMessage) + if err != nil { + t.Fatal(err) + } + + if br.SuccessCount != 2 { + t.Errorf("SuccessCount = %d; want = 2", br.SuccessCount) + } +} + func TestSendEachForMulticastWithCustomEndpoint(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { req, _ := ioutil.ReadAll(r.Body) @@ -1099,7 +1200,7 @@ func TestSendMulticastEmptyArray(t *testing.T) { t.Fatal(err) } - want := "tokens must not be nil or empty" + want := "either tokens or fids must be specified" mm := &MulticastMessage{} br, err := client.SendMulticast(ctx, mm) if err == nil || err.Error() != want { @@ -1114,6 +1215,15 @@ func TestSendMulticastEmptyArray(t *testing.T) { if err == nil || err.Error() != want { t.Errorf("SendMulticast(Tokens: []) = (%v, %v); want = (nil, %q)", br, err, want) } + + var fids []string + mm = &MulticastMessage{ + Fids: fids, + } + br, err = client.SendMulticast(ctx, mm) + if err == nil || err.Error() != want { + t.Errorf("SendMulticast(Fids: []) = (%v, %v); want = (nil, %q)", br, err, want) + } } func TestSendMulticastTooManyTokens(t *testing.T) { @@ -1128,12 +1238,37 @@ func TestSendMulticastTooManyTokens(t *testing.T) { tokens = append(tokens, fmt.Sprintf("token%d", i)) } - want := "tokens must not contain more than 500 elements" + want := "total tokens and fids must not exceed 500 elements" mm := &MulticastMessage{Tokens: tokens} br, err := client.SendMulticast(ctx, mm) if err == nil || err.Error() != want { t.Errorf("SendMulticast() = (%v, %v); want = (nil, %q)", br, err, want) } + + var fids []string + for i := 0; i < 501; i++ { + fids = append(fids, fmt.Sprintf("fid%d", i)) + } + mm = &MulticastMessage{Fids: fids} + br, err = client.SendMulticast(ctx, mm) + if err == nil || err.Error() != want { + t.Errorf("SendMulticast() = (%v, %v); want = (nil, %q)", br, err, want) + } + + // Mixed limit over 500 + mixedTokens := []string{} + mixedFids := []string{} + for i := 0; i < 250; i++ { + mixedTokens = append(mixedTokens, fmt.Sprintf("token%d", i)) + } + for i := 0; i < 251; i++ { + mixedFids = append(mixedFids, fmt.Sprintf("fid%d", i)) + } + mm = &MulticastMessage{Tokens: mixedTokens, Fids: mixedFids} + br, err = client.SendMulticast(ctx, mm) + if err == nil || err.Error() != want { + t.Errorf("SendMulticast() = (%v, %v); want = (nil, %q)", br, err, want) + } } func TestSendMulticastInvalidMessage(t *testing.T) { From 716224a28e141977a555bdf2218ed50b665ca832 Mon Sep 17 00:00:00 2001 From: Yvonne Pan <103622026+yvonnep165@users.noreply.github.com> Date: Thu, 28 May 2026 21:48:17 -0400 Subject: [PATCH 3/7] Update docstring in messaging batch --- messaging/messaging_batch.go | 53 ++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/messaging/messaging_batch.go b/messaging/messaging_batch.go index ea323604..7c4c8a05 100644 --- a/messaging/messaging_batch.go +++ b/messaging/messaging_batch.go @@ -133,12 +133,14 @@ func (c *fcmClient) SendEachDryRun(ctx context.Context, messages []*Message) (*B return c.sendEachInBatch(ctx, messages, true) } -// SendEachForMulticast sends the given multicast message to all the FCM registration tokens specified. +// SendEachForMulticast sends the given multicast message to all the specified FCM registration +// tokens and/or Firebase Installation IDs (FIDs). // -// The tokens array in MulticastMessage may contain up to 500 tokens. SendMulticast uses the -// SendEach() function to send the given message to all the target recipients. The -// responses list obtained from the return value corresponds to the order of the input tokens. An error -// from SendEachForMulticast or a BatchResponse with all failures indicates a total failure, meaning +// The tokens and FIDs in MulticastMessage may contain up to 500 elements in total. +// SendEachForMulticast uses the SendEach() function to send the given message. The responses list +// obtained from the return value corresponds to the order of the input targets. If both tokens +// and FIDs are provided, tokens are processed first, followed by FIDs. An error from +// SendEachForMulticast or a BatchResponse with all failures indicates a total failure, meaning // that none of the messages in the list could be sent. Partial failures or no failures are only // indicated by a BatchResponse return value. func (c *fcmClient) SendEachForMulticast(ctx context.Context, message *MulticastMessage) (*BatchResponse, error) { @@ -151,16 +153,17 @@ func (c *fcmClient) SendEachForMulticast(ctx context.Context, message *Multicast } // SendEachForMulticastDryRun sends the given multicast message to all the specified FCM registration -// tokens in the dry run (validation only) mode. +// tokens and/or Firebase Installation IDs (FIDs) in the dry run (validation only) mode. // // This function does not actually deliver any messages to target devices. Instead, it performs all // the SDK-level and backend validations on the messages, and emulates the send operation. // -// The tokens array in MulticastMessage may contain up to 500 tokens. SendEachForMulticastDryRunn uses the -// SendEachDryRun() function to send the given message. The responses list obtained from -// the return value corresponds to the order of the input tokens. An error from SendEachForMulticastDryRun -// or a BatchResponse with all failures indicates a total failure, meaning that of the messages in the -// list could be sent. Partial failures or no failures are only +// The tokens and FIDs in MulticastMessage may contain up to 500 elements in total. +// SendEachForMulticastDryRun uses the SendEachDryRun() function to send the given message. +// The responses list obtained from the return value corresponds to the order of the input targets. +// If both tokens and FIDs are provided, tokens are processed first, followed by FIDs. An error from +// SendEachForMulticastDryRun or a BatchResponse with all failures indicates a total failure, meaning +// that none of the messages in the list could be sent. Partial failures or no failures are only // indicated by a BatchResponse return value. func (c *fcmClient) SendEachForMulticastDryRun(ctx context.Context, message *MulticastMessage) (*BatchResponse, error) { messages, err := toMessages(message) @@ -291,13 +294,16 @@ func (c *fcmClient) SendAllDryRun(ctx context.Context, messages []*Message) (*Ba return c.sendBatch(ctx, messages, true) } -// SendMulticast sends the given multicast message to all the FCM registration tokens specified. +// SendMulticast sends the given multicast message to all the specified FCM registration +// tokens and/or Firebase Installation IDs (FIDs). // -// The tokens array in MulticastMessage may contain up to 500 tokens. SendMulticast uses the -// SendAll() function to send the given message to all the target recipients. The -// responses list obtained from the return value corresponds to the order of the input tokens. An -// error from SendMulticast indicates a total failure, meaning that the message could not be sent -// to any of the recipients. Partial failures are indicated by a BatchResponse return value. +// The tokens and FIDs in MulticastMessage may contain up to 500 elements in total. +// SendMulticast uses the SendAll() function to send the given message to all the target +// recipients. The responses list obtained from the return value corresponds to the order of +// the input targets. If both tokens and FIDs are provided, tokens are processed first, +// followed by FIDs. An error from SendMulticast indicates a total failure, meaning that the +// message could not be sent to any of the recipients. Partial failures are indicated by a +// BatchResponse return value. // // Deprecated: Use SendEachForMulticast instead. func (c *fcmClient) SendMulticast(ctx context.Context, message *MulticastMessage) (*BatchResponse, error) { @@ -310,16 +316,17 @@ func (c *fcmClient) SendMulticast(ctx context.Context, message *MulticastMessage } // SendMulticastDryRun sends the given multicast message to all the specified FCM registration -// tokens in the dry run (validation only) mode. +// tokens and/or Firebase Installation IDs (FIDs) in the dry run (validation only) mode. // // This function does not actually deliver any messages to target devices. Instead, it performs all // the SDK-level and backend validations on the messages, and emulates the send operation. // -// The tokens array in MulticastMessage may contain up to 500 tokens. SendMulticastDryRun uses the -// SendAllDryRun() function to send the given message. The responses list obtained from -// the return value corresponds to the order of the input tokens. An error from SendMulticastDryRun -// indicates a total failure, meaning that none of the messages were sent to FCM for validation. -// Partial failures are indicated by a BatchResponse return value. +// The tokens and FIDs in MulticastMessage may contain up to 500 elements in total. +// SendMulticastDryRun uses the SendAllDryRun() function to send the given message. +// The responses list obtained from the return value corresponds to the order of the input targets. +// If both tokens and FIDs are provided, tokens are processed first, followed by FIDs. An error +// from SendMulticastDryRun indicates a total failure, meaning that none of the messages +// were sent to FCM for validation. Partial failures are indicated by a BatchResponse return value. // // Deprecated: Use SendEachForMulticastDryRun instead. func (c *fcmClient) SendMulticastDryRun(ctx context.Context, message *MulticastMessage) (*BatchResponse, error) { From 4fd88ac164c9d072b574c2113dccfcd181613abb Mon Sep 17 00:00:00 2001 From: Yvonne Pan <103622026+yvonnep165@users.noreply.github.com> Date: Thu, 28 May 2026 21:59:05 -0400 Subject: [PATCH 4/7] Update unit test names to include fids as targets --- messaging/messaging_batch_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/messaging/messaging_batch_test.go b/messaging/messaging_batch_test.go index 771ae8f5..508a7ad1 100644 --- a/messaging/messaging_batch_test.go +++ b/messaging/messaging_batch_test.go @@ -675,7 +675,7 @@ func TestSendEachForMulticastEmptyArray(t *testing.T) { } } -func TestSendEachForMulticastTooManyTokens(t *testing.T) { +func TestSendEachForMulticastTooManyTargets(t *testing.T) { ctx := context.Background() client, err := NewClient(ctx, testMessagingConfig) if err != nil { @@ -1226,7 +1226,7 @@ func TestSendMulticastEmptyArray(t *testing.T) { } } -func TestSendMulticastTooManyTokens(t *testing.T) { +func TestSendMulticastTooManyTargets(t *testing.T) { ctx := context.Background() client, err := NewClient(ctx, testMessagingConfig) if err != nil { @@ -1255,7 +1255,6 @@ func TestSendMulticastTooManyTokens(t *testing.T) { t.Errorf("SendMulticast() = (%v, %v); want = (nil, %q)", br, err, want) } - // Mixed limit over 500 mixedTokens := []string{} mixedFids := []string{} for i := 0; i < 250; i++ { From 6b417d287c76b2301718d20a0225479ee6be9dc3 Mon Sep 17 00:00:00 2001 From: Yvonne Pan <103622026+yvonnep165@users.noreply.github.com> Date: Fri, 29 May 2026 11:19:05 -0400 Subject: [PATCH 5/7] Fix formatting --- messaging/messaging.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/messaging/messaging.go b/messaging/messaging.go index dcf4a05d..19631f2e 100644 --- a/messaging/messaging.go +++ b/messaging/messaging.go @@ -70,10 +70,10 @@ type Message struct { APNS *APNSConfig `json:"apns,omitempty"` FCMOptions *FCMOptions `json:"fcm_options,omitempty"` // Deprecated: use `Fid` instead - Token string `json:"token,omitempty"` - Topic string `json:"-"` - Condition string `json:"condition,omitempty"` - Fid string `json:"fid,omitempty"` + Token string `json:"token,omitempty"` + Topic string `json:"-"` + Condition string `json:"condition,omitempty"` + Fid string `json:"fid,omitempty"` } // MarshalJSON marshals a Message into JSON (for internal use only). From 70750cb358f8739878c7aacc7be9cc737930f14b Mon Sep 17 00:00:00 2001 From: Yvonne Pan <103622026+yvonnep165@users.noreply.github.com> Date: Fri, 29 May 2026 11:43:36 -0400 Subject: [PATCH 6/7] Use the helper function to check targets in order for TestSendEachForMulticastMixed and change deprecation comment format --- messaging/messaging.go | 2 +- messaging/messaging_batch.go | 2 +- messaging/messaging_batch_test.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/messaging/messaging.go b/messaging/messaging.go index 19631f2e..fb9ef34a 100644 --- a/messaging/messaging.go +++ b/messaging/messaging.go @@ -69,7 +69,7 @@ type Message struct { Webpush *WebpushConfig `json:"webpush,omitempty"` APNS *APNSConfig `json:"apns,omitempty"` FCMOptions *FCMOptions `json:"fcm_options,omitempty"` - // Deprecated: use `Fid` instead + // Deprecated: Use Fid instead. Token string `json:"token,omitempty"` Topic string `json:"-"` Condition string `json:"condition,omitempty"` diff --git a/messaging/messaging_batch.go b/messaging/messaging_batch.go index 7c4c8a05..d1e63288 100644 --- a/messaging/messaging_batch.go +++ b/messaging/messaging_batch.go @@ -41,7 +41,7 @@ const multipartBoundary = "__END_OF_PART__" // Firebase Installation IDs (FIDs) to which the message should be sent. A single // MulticastMessage may contain up to 500 registration tokens and FIDs combined. type MulticastMessage struct { - // Deprecated: use `Fids` instead. + // Deprecated: Use Fids instead. Tokens []string Data map[string]string Notification *Notification diff --git a/messaging/messaging_batch_test.go b/messaging/messaging_batch_test.go index 508a7ad1..25ac5a11 100644 --- a/messaging/messaging_batch_test.go +++ b/messaging/messaging_batch_test.go @@ -821,8 +821,8 @@ func TestSendEachForMulticastMixed(t *testing.T) { t.Fatal(err) } - if br.SuccessCount != 2 { - t.Errorf("SuccessCount = %d; want = 2", br.SuccessCount) + if err := checkSuccessfulBatchResponseForSendEach(br, false); err != nil { + t.Errorf("SendEachForMulticast() = %v", err) } } From af189bd0c96cfad3f82e3a89dd5ec26aa5d83eb5 Mon Sep 17 00:00:00 2001 From: Yvonne Pan <103622026+yvonnep165@users.noreply.github.com> Date: Fri, 5 Jun 2026 13:45:56 -0700 Subject: [PATCH 7/7] Trigger CI