diff --git a/Vonage.Test/WebhookStructsTest.cs b/Vonage.Test/WebhookStructsTest.cs
index 06d81330d..94f141217 100644
--- a/Vonage.Test/WebhookStructsTest.cs
+++ b/Vonage.Test/WebhookStructsTest.cs
@@ -28,7 +28,7 @@ public void TestAnswer()
Assert.Equal("aaaaaaaa-bbbb-cccc-dddd-0123456789ab", answerWebhook.Uuid);
Assert.Equal("CON-aaaaaaaa-bbbb-cccc-dddd-0123456789ab", answerWebhook.ConversationUuid);
}
-
+
[Fact]
public void TestAnswered()
{
@@ -61,7 +61,7 @@ public void TestAnswered()
Assert.Equal("1234", answeredWebhook.Network);
Assert.Equal("0.02", answeredWebhook.Rate);
}
-
+
[Fact]
public void TestCallbackStatusEventWithUnenumeratedDetail()
{
@@ -89,7 +89,7 @@ public void TestCallbackStatusEventWithUnenumeratedDetail()
CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal |
DateTimeStyles.AdjustToUniversal), callStatusWebhook.TimeStamp);
}
-
+
[Theory]
[InlineData("disconnected")]
[InlineData("cancelled")]
@@ -125,7 +125,7 @@ public void TestCallStatusEvent(string type)
CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal |
DateTimeStyles.AdjustToUniversal), callStatusWebhook.TimeStamp);
}
-
+
[Fact]
public void TestCallStatusEventWithDetail()
{
@@ -152,7 +152,7 @@ public void TestCallStatusEventWithDetail()
CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal |
DateTimeStyles.AdjustToUniversal), callStatusWebhook.TimeStamp);
}
-
+
[Fact]
public void TestCompleted()
{
@@ -193,7 +193,53 @@ public void TestCompleted()
Assert.Equal("0.03", completedWebhook.Price);
Assert.Equal("2", completedWebhook.Duration);
}
-
+
+ [Fact]
+ public void TestCompleted_WithNullStartTime()
+ {
+ var json = @"
+ {
+ ""from"":""442079460000"",
+ ""to"":""447700900000"",
+ ""uuid"":""aaaaaaaa-bbbb-cccc-dddd-0123456789ab"",
+ ""conversation_uuid"":""CON-aaaaaaaa-bbbb-cccc-dddd-0123456789ab"",
+ ""status"":""completed"",
+ ""direction"":""outbound"",
+ ""timestamp"":""2020-01-01T12:00:00.000Z"",
+ ""start_time"":null,
+ ""end_time"":""2020-01-01T12:00:01.000Z"",
+ ""rate"":""0.02"",
+ ""price"":""0.03"",
+ ""network"":""1234"",
+ ""duration"":""2""
+ }";
+ var completedWebhook = (Completed) EventBase.ParseEvent(json);
+ completedWebhook.StartTime.Should().BeNull();
+ }
+
+ [Fact]
+ public void TestCompleted_WithNullEndTime()
+ {
+ var json = @"
+ {
+ ""from"":""442079460000"",
+ ""to"":""447700900000"",
+ ""uuid"":""aaaaaaaa-bbbb-cccc-dddd-0123456789ab"",
+ ""conversation_uuid"":""CON-aaaaaaaa-bbbb-cccc-dddd-0123456789ab"",
+ ""status"":""completed"",
+ ""direction"":""outbound"",
+ ""timestamp"":""2020-01-01T12:00:00.000Z"",
+ ""start_time"":""2020-01-01T12:00:00.000Z"",
+ ""end_time"":null,
+ ""rate"":""0.02"",
+ ""price"":""0.03"",
+ ""network"":""1234"",
+ ""duration"":""2""
+ }";
+ var completedWebhook = (Completed) EventBase.ParseEvent(json);
+ completedWebhook.EndTime.Should().BeNull();
+ }
+
[Fact]
public void TestDtmfMultiInputStruct()
{
@@ -218,13 +264,13 @@ public void TestDtmfMultiInputStruct()
CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal |
DateTimeStyles.AdjustToUniversal), inputWebhook.TimeStamp);
}
-
+
[Fact]
public void TestEmpty()
{
Assert.Null(EventBase.ParseEvent("{}"));
}
-
+
[Fact]
public void TestError()
{
@@ -241,7 +287,7 @@ public void TestError()
CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal |
DateTimeStyles.AdjustToUniversal), errorWebhook.TimeStamp);
}
-
+
[Theory]
[InlineData("human")]
[InlineData("machine")]
@@ -268,7 +314,7 @@ public void TestHumanMachine(string type)
CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal |
DateTimeStyles.AdjustToUniversal), humanMachineWebhook.TimeStamp);
}
-
+
[Fact]
public void TestNotifications()
{
@@ -285,7 +331,7 @@ public void TestNotifications()
CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal |
DateTimeStyles.AdjustToUniversal), notification.TimeStamp);
}
-
+
[Fact]
public void TestRecord()
{
@@ -315,7 +361,7 @@ public void TestRecord()
Assert.Equal("aaaaaaaa-bbbb-cccc-dddd-0123456789ab", recordWebhook.Uuid);
Assert.Equal("CON-aaaaaaaa-bbbb-cccc-dddd-0123456789ab", recordWebhook.ConversationUuid);
}
-
+
[Fact]
public void TestSpeechMultiInputStruct()
{
@@ -342,7 +388,7 @@ public void TestSpeechMultiInputStruct()
CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal |
DateTimeStyles.AdjustToUniversal), inputWebhook.TimeStamp);
}
-
+
[Fact]
public void TestTransfer()
{
@@ -361,7 +407,7 @@ public void TestTransfer()
DateTimeStyles.AdjustToUniversal), transferWebhook.TimeStamp);
Assert.Equal("aaaaaaaa-bbbb-cccc-dddd-0123456789ab", transferWebhook.Uuid);
}
-
+
[Fact]
public void ShouldDeserializedAnswered_GivenStartTimeIsNull()
{
@@ -370,7 +416,7 @@ public void ShouldDeserializedAnswered_GivenStartTimeIsNull()
File.ReadAllText("Data/Webhooks/ShouldDeserializedAnswered_GivenStartTimeIsNull.json"));
deserializedEvent.StartTime.Should().BeNull();
}
-
+
public class Foo
{
public string bar { get; set; }
diff --git a/Vonage/Voice/EventWebhooks/Completed.cs b/Vonage/Voice/EventWebhooks/Completed.cs
index d6a426adc..a82d2b7f3 100644
--- a/Vonage/Voice/EventWebhooks/Completed.cs
+++ b/Vonage/Voice/EventWebhooks/Completed.cs
@@ -10,34 +10,34 @@ public class Completed : CallStatusEvent
///
[JsonProperty("duration")]
public string Duration { get; set; }
-
+
///
/// Timestamp (ISO 8601 format) of the end time of the call
///
[JsonProperty("end_time")]
- public DateTime EndTime { get; set; }
-
+ public DateTime? EndTime { get; set; }
+
///
/// The type of network that was used in the call
///
[JsonProperty("network")]
public string Network { get; set; }
-
+
///
/// Total cost of the call (EUR)
///
[JsonProperty("price")]
public string Price { get; set; }
-
+
///
/// Cost per minute of the call (EUR)
///
[JsonProperty("rate")]
public string Rate { get; set; }
-
+
///
/// Timestamp (ISO 8601 format)
///
[JsonProperty("start_time")]
- public DateTime StartTime { get; set; }
+ public DateTime? StartTime { get; set; }
}
\ No newline at end of file