Skip to content

Commit 025f233

Browse files
committed
Added additional classes for Android and APNS FCM options. Added check for analytics label. Added tests.
1 parent a047dde commit 025f233

File tree

8 files changed

+184
-4
lines changed

8 files changed

+184
-4
lines changed

FirebaseAdmin/FirebaseAdmin.Tests/Messaging/MessageTest.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ public void Notification()
7575
Title = "title",
7676
Body = "body",
7777
},
78+
FcmOptions = new FcmOptions()
79+
{
80+
AnalyticsLabel = "label",
81+
},
7882
};
7983
var expected = new JObject()
8084
{
@@ -86,6 +90,12 @@ public void Notification()
8690
{ "body", "body" },
8791
}
8892
},
93+
{
94+
"fcm_options", new JObject()
95+
{
96+
{ "analytics_label", "label" },
97+
}
98+
},
8999
};
90100
this.AssertJsonEquals(expected, message);
91101
}
@@ -117,6 +127,10 @@ public void MessageDeserialization()
117127
{
118128
Data = new Dictionary<string, string>() { { "key", "value" } },
119129
},
130+
FcmOptions = new FcmOptions()
131+
{
132+
AnalyticsLabel = "label",
133+
},
120134
};
121135
var json = NewtonsoftJsonSerializer.Instance.Serialize(original);
122136
var copy = NewtonsoftJsonSerializer.Instance.Deserialize<Message>(json);
@@ -128,6 +142,7 @@ public void MessageDeserialization()
128142
original.Android.RestrictedPackageName, copy.Android.RestrictedPackageName);
129143
Assert.Equal(original.Apns.Aps.AlertString, copy.Apns.Aps.AlertString);
130144
Assert.Equal(original.Webpush.Data, copy.Webpush.Data);
145+
Assert.Equal(original.FcmOptions.AnalyticsLabel, copy.FcmOptions.AnalyticsLabel);
131146
}
132147

133148
[Fact]
@@ -236,6 +251,10 @@ public void AndroidConfig()
236251
BodyLocArgs = new List<string>() { "arg3", "arg4" },
237252
ChannelId = "channel-id",
238253
},
254+
FcmOptions = new AndroidFcmOptions()
255+
{
256+
AnalyticsLabel = "label",
257+
},
239258
},
240259
};
241260
var expected = new JObject()
@@ -266,6 +285,12 @@ public void AndroidConfig()
266285
{ "channel_id", "channel-id" },
267286
}
268287
},
288+
{
289+
"fcm_options", new JObject()
290+
{
291+
{ "analytics_label", "label" },
292+
}
293+
},
269294
}
270295
},
271296
};
@@ -843,6 +868,10 @@ public void ApnsConfig()
843868
{ "custom-key3", "custom-data" },
844869
{ "custom-key4", true },
845870
},
871+
FcmOptions = new ApnsFcmOptions()
872+
{
873+
AnalyticsLabel = "label",
874+
},
846875
},
847876
};
848877
var expected = new JObject()
@@ -879,6 +908,12 @@ public void ApnsConfig()
879908
{ "custom-key4", true },
880909
}
881910
},
911+
{
912+
"fcm_options", new JObject()
913+
{
914+
{ "analytics_label", "label" },
915+
}
916+
},
882917
}
883918
},
884919
};
@@ -1650,6 +1685,42 @@ public void WebpushNotificationWithInvalidHttpsLinkUrl()
16501685
Assert.Throws<ArgumentException>(() => message.CopyAndValidate());
16511686
}
16521687

1688+
[Fact]
1689+
public void AnalyticsLabelInvalid()
1690+
{
1691+
var message = new Message()
1692+
{
1693+
Topic = "test-topic",
1694+
Notification = new Notification()
1695+
{
1696+
Title = "title",
1697+
Body = "body",
1698+
},
1699+
FcmOptions = new FcmOptions()
1700+
{
1701+
AnalyticsLabel = "label!",
1702+
},
1703+
};
1704+
var expected = new JObject()
1705+
{
1706+
{ "topic", "test-topic" },
1707+
{
1708+
"notification", new JObject()
1709+
{
1710+
{ "title", "title" },
1711+
{ "body", "body" },
1712+
}
1713+
},
1714+
{
1715+
"fcm_options", new JObject()
1716+
{
1717+
{ "analytics_label", "label" },
1718+
}
1719+
},
1720+
};
1721+
Assert.Throws<ArgumentException>(() => this.AssertJsonEquals(expected, message));
1722+
}
1723+
16531724
private void AssertJsonEquals(JObject expected, Message actual)
16541725
{
16551726
var json = NewtonsoftJsonSerializer.Instance.Serialize(actual.CopyAndValidate());

FirebaseAdmin/FirebaseAdmin/Messaging/AndroidConfig.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public sealed class AndroidConfig
7070
/// Gets or sets the FCM options to be included in the message.
7171
/// </summary>
7272
[JsonProperty("fcm_options")]
73-
public FcmOptions FcmOptions { get; set; }
73+
public AndroidFcmOptions FcmOptions { get; set; }
7474

7575
/// <summary>
7676
/// Gets or sets the string representation of <see cref="Priority"/> as accepted by the FCM
@@ -165,6 +165,7 @@ internal AndroidConfig CopyAndValidate()
165165
TimeToLive = this.TimeToLive,
166166
RestrictedPackageName = this.RestrictedPackageName,
167167
Data = this.Data?.Copy(),
168+
FcmOptions = this.FcmOptions?.CopyAndValidate(),
168169
};
169170
var totalSeconds = copy.TimeToLive?.TotalSeconds ?? 0;
170171
if (totalSeconds < 0)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using FirebaseAdmin.Messaging.Util;
2+
using Newtonsoft.Json;
3+
4+
namespace FirebaseAdmin.Messaging
5+
{
6+
/// <summary>
7+
/// Represents Android FCM options.
8+
/// </summary>
9+
public sealed class AndroidFcmOptions
10+
{
11+
/// <summary>
12+
/// Gets or sets analytics label.
13+
/// </summary>
14+
[JsonProperty("analytics_label")]
15+
public string AnalyticsLabel { get; set; }
16+
17+
/// <summary>
18+
/// Copies this FCM options, and validates the content of it to ensure that it can
19+
/// be serialized into the JSON format expected by the FCM service.
20+
/// </summary>
21+
internal AndroidFcmOptions CopyAndValidate()
22+
{
23+
var copy = new AndroidFcmOptions()
24+
{
25+
AnalyticsLabel = this.AnalyticsLabel,
26+
};
27+
AnalyticsLabelChecker.CheckAnalyticsLabelOrThrow(this.AnalyticsLabel);
28+
29+
return copy;
30+
}
31+
}
32+
}

FirebaseAdmin/FirebaseAdmin/Messaging/ApnsConfig.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public sealed class ApnsConfig
3939
/// Gets or sets the FCM options to be included in the message.
4040
/// </summary>
4141
[JsonProperty("fcm_options")]
42-
public FcmOptions FcmOptions { get; set; }
42+
public ApnsFcmOptions FcmOptions { get; set; }
4343

4444
/// <summary>
4545
/// Gets or sets the <c>aps</c> dictionary to be included in the APNs payload.
@@ -108,6 +108,7 @@ internal ApnsConfig CopyAndValidate()
108108
{
109109
Headers = this.Headers?.Copy(),
110110
Payload = this.Payload.CopyAndValidate(),
111+
FcmOptions = this.FcmOptions?.CopyAndValidate(),
111112
};
112113
return copy;
113114
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using FirebaseAdmin.Messaging.Util;
2+
using Newtonsoft.Json;
3+
4+
namespace FirebaseAdmin.Messaging
5+
{
6+
/// <summary>
7+
/// Represents Apple Push Notification Service FCM options.
8+
/// </summary>
9+
public sealed class ApnsFcmOptions
10+
{
11+
/// <summary>
12+
/// Gets or sets analytics label.
13+
/// </summary>
14+
[JsonProperty("analytics_label")]
15+
public string AnalyticsLabel { get; set; }
16+
17+
/// <summary>
18+
/// Copies this FCM options, and validates the content of it to ensure that it can
19+
/// be serialized into the JSON format expected by the FCM service.
20+
/// </summary>
21+
internal ApnsFcmOptions CopyAndValidate()
22+
{
23+
var copy = new ApnsFcmOptions()
24+
{
25+
AnalyticsLabel = this.AnalyticsLabel,
26+
};
27+
AnalyticsLabelChecker.CheckAnalyticsLabelOrThrow(this.AnalyticsLabel);
28+
29+
return copy;
30+
}
31+
}
32+
}
Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,32 @@
1+
using FirebaseAdmin.Messaging.Util;
12
using Newtonsoft.Json;
23

34
namespace FirebaseAdmin.Messaging
45
{
56
/// <summary>
67
/// Represents FCM options.
78
/// </summary>
8-
public class FcmOptions
9+
public sealed class FcmOptions
910
{
1011
/// <summary>
1112
/// Gets or sets analytics label.
1213
/// </summary>
1314
[JsonProperty("analytics_label")]
1415
public string AnalyticsLabel { get; set; }
16+
17+
/// <summary>
18+
/// Copies this FCM options, and validates the content of it to ensure that it can
19+
/// be serialized into the JSON format expected by the FCM service.
20+
/// </summary>
21+
internal FcmOptions CopyAndValidate()
22+
{
23+
var copy = new FcmOptions()
24+
{
25+
AnalyticsLabel = this.AnalyticsLabel,
26+
};
27+
AnalyticsLabelChecker.CheckAnalyticsLabelOrThrow(this.AnalyticsLabel);
28+
29+
return copy;
30+
}
1531
}
16-
}
32+
}

FirebaseAdmin/FirebaseAdmin/Messaging/Message.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ internal Message CopyAndValidate()
125125
Topic = this.Topic,
126126
Condition = this.Condition,
127127
Data = this.Data?.Copy(),
128+
FcmOptions = this.FcmOptions?.CopyAndValidate(),
128129
};
129130
var list = new List<string>()
130131
{
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Text.RegularExpressions;
3+
4+
namespace FirebaseAdmin.Messaging.Util
5+
{
6+
/// <summary>
7+
/// Checker for analytics label.
8+
/// </summary>
9+
public static class AnalyticsLabelChecker
10+
{
11+
private static string pattern = "^[a-zA-Z0-9-_.~%]{0,50}$";
12+
13+
/// <summary>
14+
/// Checks anytytics labels an throw if not valid.
15+
/// </summary>
16+
/// <exception cref="ArgumentException">If analytics label does not match pattern.</exception>
17+
/// <param name="analyticsLabel">Analytics label.</param>
18+
public static void CheckAnalyticsLabelOrThrow(string analyticsLabel)
19+
{
20+
if (!Regex.IsMatch(analyticsLabel, pattern))
21+
{
22+
throw new ArgumentException("Analytics label must have format matching'^[a-zA-Z0-9-_.~%]{1,50}$");
23+
}
24+
}
25+
}
26+
}

0 commit comments

Comments
 (0)