diff --git a/ical.NET.Collections/ical.NET.Collections/GroupedList.cs b/ical.NET.Collections/ical.NET.Collections/GroupedList.cs index d571f89d3..799e76e8f 100644 --- a/ical.NET.Collections/ical.NET.Collections/GroupedList.cs +++ b/ical.NET.Collections/ical.NET.Collections/GroupedList.cs @@ -25,7 +25,9 @@ public class GroupedList : protected virtual TGroup GroupModifier(TGroup group) { if (group == null) + { throw new ArgumentNullException(nameof(group), "The item's group cannot be null."); + } return group; } diff --git a/ical.NET.UnitTests/AttendeeTest.cs b/ical.NET.UnitTests/AttendeeTest.cs index 0f87f2156..c3843d779 100644 --- a/ical.NET.UnitTests/AttendeeTest.cs +++ b/ical.NET.UnitTests/AttendeeTest.cs @@ -11,7 +11,7 @@ namespace ical.NET.UnitTests [TestFixture] public class AttendeeTest { - internal static Event EvtFactory() + internal static Event VEventFactory() { return new Event { @@ -21,61 +21,53 @@ internal static Event EvtFactory() }; } - const string req = "REQ-PARTICIPANT"; //this string may be added to the api in the future - internal static IList AttendeesFactory() + private const string _requiredParticipant = "REQ-PARTICIPANT"; //this string may be added to the api in the future + private static readonly IList _attendees = new List { - - return new[] { - new Attendee("MAILTO:james@test.com") - { - CommonName = "James James", - Role = req, - Rsvp = true, - ParticipationStatus = ParticipationStatus.Tentative - }, - new Attendee("MAILTO:mary@test.com") - { - CommonName = "Mary Mary", - Role = req, - Rsvp = true, - ParticipationStatus = ParticipationStatus.Accepted - } - }; - } + new Attendee("MAILTO:james@example.com") + { + CommonName = "James James", + Role = _requiredParticipant, + Rsvp = true, + ParticipationStatus = ParticipationStatus.Tentative + }, + new Attendee("MAILTO:mary@example.com") + { + CommonName = "Mary Mary", + Role = _requiredParticipant, + Rsvp = true, + ParticipationStatus = ParticipationStatus.Accepted + } + }.AsReadOnly(); + + /// /// Ensures that attendees can be properly added to an event. /// [Test, Category("Attendee")] public void Add1Attendee() { - var evt = EvtFactory(); + var evt = VEventFactory(); Assert.AreEqual(0, evt.Attendees.Count); - var at = AttendeesFactory(); - - evt.Attendees.Add(at[0]); + evt.Attendees.Add(_attendees[0]); Assert.AreEqual(1, evt.Attendees.Count); - Assert.AreSame(at[0], evt.Attendees[0]); //the properties below had been set to null during the Attendees.Add operation in NuGet version 2.1.4 - Assert.AreEqual(req, evt.Attendees[0].Role); + Assert.AreEqual(_requiredParticipant, evt.Attendees[0].Role); Assert.AreEqual(ParticipationStatus.Tentative, evt.Attendees[0].ParticipationStatus); } [Test, Category("Attendee")] public void Add2Attendees() { - var evt = EvtFactory(); + var evt = VEventFactory(); Assert.AreEqual(0, evt.Attendees.Count); - var at = AttendeesFactory(); - - evt.Attendees.Add(at[0]); - evt.Attendees.Add(at[1]); + evt.Attendees.Add(_attendees[0]); + evt.Attendees.Add(_attendees[1]); Assert.AreEqual(2, evt.Attendees.Count); - Assert.AreSame(at[1], evt.Attendees[1]); - - Assert.AreEqual(req, evt.Attendees[1].Role); + Assert.AreEqual(_requiredParticipant, evt.Attendees[1].Role); var cal = new Calendar(); cal.Events.Add(evt); @@ -89,17 +81,15 @@ public void Add2Attendees() [Test, Category("Attendee")] public void Remove1Attendee() { - var evt = EvtFactory(); - + var evt = VEventFactory(); Assert.AreEqual(0, evt.Attendees.Count); - var at = AttendeesFactory()[0]; - evt.Attendees.Add(at); + + var attendee = _attendees[0]; + evt.Attendees.Add(attendee); Assert.AreEqual(1, evt.Attendees.Count); - Assert.AreSame(at, evt.Attendees[0]); - evt.Attendees.Remove(at); + evt.Attendees.Remove(attendee); Assert.AreEqual(0, evt.Attendees.Count); } - } } diff --git a/ical.NET.UnitTests/CopyTest.cs b/ical.NET.UnitTests/CopyTest.cs index be3acf5a8..ff11c5047 100644 --- a/ical.NET.UnitTests/CopyTest.cs +++ b/ical.NET.UnitTests/CopyTest.cs @@ -16,7 +16,7 @@ public void CopyCalendarTest(string calendarString) { var iCal1 = Calendar.LoadFromStream(new StringReader(calendarString))[0]; var iCal2 = iCal1.Copy(); - SerializationTest.CompareCalendars(iCal1, iCal2); + SerializationTests.CompareCalendars(iCal1, iCal2); } public static IEnumerable CopyCalendarTest_TestCases() diff --git a/ical.NET.UnitTests/DeserializationTest.cs b/ical.NET.UnitTests/DeserializationTests.cs similarity index 99% rename from ical.NET.UnitTests/DeserializationTest.cs rename to ical.NET.UnitTests/DeserializationTests.cs index 56ecf7420..4c240a859 100644 --- a/ical.NET.UnitTests/DeserializationTest.cs +++ b/ical.NET.UnitTests/DeserializationTests.cs @@ -19,7 +19,7 @@ namespace ical.NET.UnitTests { [TestFixture] - public class DeSerializationTest + public class DeserializationTests { [Test, Category("Deserialization")] diff --git a/ical.NET.UnitTests/SerializationTest.cs b/ical.NET.UnitTests/SerializationTest.cs deleted file mode 100644 index 7b757cfc6..000000000 --- a/ical.NET.UnitTests/SerializationTest.cs +++ /dev/null @@ -1,318 +0,0 @@ -using System; -using System.Collections; -using Ical.Net; -using Ical.Net.DataTypes; -using Ical.Net.Interfaces; -using Ical.Net.Interfaces.Components; -using Ical.Net.Serialization; -using Ical.Net.Serialization.iCalendar.Serializers; -using NUnit.Framework; -using Ical.Net.Interfaces.DataTypes; -using System.IO; -using System.Collections.Generic; -using Ical.Net.ExtensionMethods; -using System.Text.RegularExpressions; -using System.Linq; - -namespace ical.NET.UnitTests -{ - [TestFixture] - public class SerializationTest - { - #region helperMethods - public static void CompareCalendars(ICalendar cal1, ICalendar cal2) - { - CompareComponents(cal1, cal2); - - Assert.AreEqual(cal1.Children.Count, cal2.Children.Count, "Children count is different between calendars."); - - for (var i = 0; i < cal1.Children.Count; i++) - { - var component1 = cal1.Children[i] as ICalendarComponent; - var component2 = cal2.Children[i] as ICalendarComponent; - if (component1 != null && component2 != null) - { - CompareComponents(component1, component2); - } - } - } - - public static void CompareComponents(ICalendarComponent cb1, ICalendarComponent cb2) - { - foreach (var p1 in cb1.Properties) - { - var isMatch = false; - foreach (var p2 in cb2.Properties.AllOf(p1.Name)) - { - try - { - Assert.AreEqual(p1, p2, "The properties '" + p1.Name + "' are not equal."); - if (p1.Value is IComparable) - Assert.AreEqual(0, ((IComparable)p1.Value).CompareTo(p2.Value), "The '" + p1.Name + "' property values do not match."); - else if (p1.Value is IEnumerable) - CompareEnumerables((IEnumerable)p1.Value, (IEnumerable)p2.Value, p1.Name); - else - Assert.AreEqual(p1.Value, p2.Value, "The '" + p1.Name + "' property values are not equal."); - - isMatch = true; - break; - } - catch { } - } - - Assert.IsTrue(isMatch, "Could not find a matching property - " + p1.Name + ":" + (p1.Value?.ToString() ?? string.Empty)); - } - - Assert.AreEqual(cb1.Children.Count, cb2.Children.Count, "The number of children are not equal."); - for (var i = 0; i < cb1.Children.Count; i++) - { - var child1 = cb1.Children[i] as ICalendarComponent; - var child2 = cb2.Children[i] as ICalendarComponent; - if (child1 != null && child2 != null) - CompareComponents(child1, child2); - else - Assert.AreEqual(child1, child2, "The child objects are not equal."); - } - } - - public static void CompareEnumerables(IEnumerable a1, IEnumerable a2, string value) - { - if (a1 == null && a2 == null) - return; - - Assert.IsFalse((a1 == null && a2 != null) || (a1 != null && a2 == null), value + " do not match - one item is null"); - - var enum1 = a1.GetEnumerator(); - var enum2 = a2.GetEnumerator(); - - while (enum1.MoveNext() && enum2.MoveNext()) - Assert.AreEqual(enum1.Current, enum2.Current, value + " do not match"); - } - - const string NewLine = "\r\n"; // I suspect the spec actually specifies this, and so Environment.NewLine would not be appropriate - public static string InspectSerializedSection(string serialized, string sectionName, IEnumerable elements) - { - const string notFound = "expected '{0}' not found"; - string searchFor = "BEGIN:" + sectionName; - int begin = serialized.IndexOf(searchFor); - Assert.AreNotEqual(-1, begin, notFound, searchFor); - searchFor = "END:" + sectionName; - int end = serialized.IndexOf(searchFor, begin); - Assert.AreNotEqual(-1, end, notFound, searchFor); - - string searchRegion = serialized.Substring(begin, end - begin + 1); - - foreach (var e in elements) - { - Assert.IsTrue(searchRegion.Contains(NewLine + e + NewLine), notFound, e); - } - - return searchRegion; - } - - //3 formats - UTC, local time as defined in vTimeZone, and floating, - //at some point it would be great to independently unit test string serialization of an IDateTime object, into its 3 forms - //http://www.kanzaki.com/docs/ical/dateTime.html - static string CalDateString(IDateTime cdt) - { - string returnVar = cdt.Year.ToString() + cdt.Month + cdt.Day + 'T' + cdt.Hour + cdt.Minute + cdt.Second; - if (cdt.IsUniversalTime) - { - return returnVar + 'Z'; - } - if(!string.IsNullOrEmpty(cdt.TzId)){ - return string.Format("TZID={0}:{1}",cdt.TzId,returnVar); - } - return returnVar; - } - - //This method needs renaming - static Dictionary GetValues(string serialized, string name, string value) - { - string lengthened = serialized.Replace(NewLine + ' ', string.Empty); - //using a regex for now - for the sake of speed, it may be worth creating a C# text search later - var match = Regex.Match(lengthened, '^' + Regex.Escape(name) + ";(.*):" + Regex.Escape(value) + NewLine, RegexOptions.Multiline); - Assert.IsTrue(match.Success, "could not find a(n) '{0}' with value '{1}'", name, value); - return match.Groups[1].Value.Split(';').Select(v=>v.Split('=')).ToDictionary(v=>v[0], v=>v.Length>1 ? v[1] : null); - } - #endregion //helperMethods - - #region tests - [Test, Category("Serialization")] - public void TimeZoneSerialize() - { - - using (var cal = new Calendar() { Method = "PUBLISH", Version = "2.0" }) - { - const string exampleTZ = "New Zealand Standard Time"; // can change this but should SupportDaylightTime - var tzi = TimeZoneInfo.FindSystemTimeZoneById(exampleTZ); - var timezone = VTimeZone.FromSystemTimeZone(tzi); - cal.AddTimeZone(timezone); - var evt = new Event - { - Summary = "Testing", - Start = new CalDateTime(2016, 7, 14, timezone.Id), - End = new CalDateTime(2016, 7, 15, timezone.Id) - }; - cal.Events.Add(evt); - - var serializer = new CalendarSerializer(new SerializationContext()); - var serializedCalendar = serializer.SerializeToString(cal); - - Console.Write(serializedCalendar); - - string vTimezone = InspectSerializedSection(serializedCalendar, "VTIMEZONE", new[] { - "TZID:" + timezone.Id - }); - - string o = tzi.BaseUtcOffset.ToString("hhmm", System.Globalization.CultureInfo.InvariantCulture); - InspectSerializedSection(vTimezone, "STANDARD", new[] { - "TZNAME:" + tzi.StandardName, - "TZOFFSETTO:" + o - //todo - standard time, for NZ standard time (current example) - //"DTSTART:20150402T030000", - //"RRULE:FREQ=YEARLY;BYDAY=1SU;BYHOUR=3;BYMINUTE=0;BYMONTH=4", - //"TZOFFSETFROM:+1300" - }); - - - InspectSerializedSection(vTimezone, "DAYLIGHT", new[] { - "TZNAME:" + tzi.DaylightName, - "TZOFFSETFROM:" + o - }); - } - } - [Test, Category("Serialization")] - public void SerializeDeserialize() - { - using (var cal1 = new Calendar() { Method = "PUBLISH", Version = "2.0" }) - { - var evt = new Event - { - Class = "PRIVATE", - Created = new CalDateTime(2010, 3, 25, 12, 53, 35), - DtStamp = new CalDateTime(2010, 3, 25, 12, 53, 35), - LastModified = new CalDateTime(2010, 3, 27, 13, 53, 35), - Sequence = 0, - Uid = "42f58d4f-847e-46f8-9f4a-ce52697682cf", - Priority = 5, - Location = "here", - Summary = "test", - DtStart = new CalDateTime(2012, 3, 25, 12, 50, 00), - DtEnd = new CalDateTime(2012, 3, 25, 13, 10, 00) - }; - cal1.Events.Add(evt); - - var serializer = new CalendarSerializer(new SerializationContext()); - var serializedCalendar = serializer.SerializeToString(cal1); - using (var sr = new StringReader(serializedCalendar)) - { - var cal2 = Calendar.LoadFromStream(sr)[0]; - CompareCalendars(cal1, cal2); - } - - } - } - [Test, Category("Serialization")] - public void EventPropertiesSerialized() - { - using (var cal = new Calendar() { Method = "PUBLISH", Version = "2.0" }) - { - var evt = new Event - { - Class = "PRIVATE", - Created = new CalDateTime(2010, 3, 25, 12, 53, 35), - DtStamp = new CalDateTime(2010, 3, 25, 12, 53, 35), - LastModified = new CalDateTime(2010, 3, 27, 13, 53, 35), - Sequence = 0, - Uid = "42f58d4f-847e-46f8-9f4a-ce52697682cf", - Priority = 5, - Location = "here", - Summary = "test", - DtStart = new CalDateTime(2012, 3, 25, 12, 50, 00), - DtEnd = new CalDateTime(2012, 3, 25, 13, 10, 00), - //not yet testing property below as serialized output currently does not comply with RTFC 2445 - //Transparency = TransparencyType.Opaque, - //Status = EventStatus.Confirmed - }; - cal.Events.Add(evt); - - var serializer = new CalendarSerializer(new SerializationContext()); - var serializedCalendar = serializer.SerializeToString(cal); - - Console.Write(serializedCalendar); - Assert.IsTrue(serializedCalendar.StartsWith("BEGIN:VCALENDAR")); - Assert.IsTrue(serializedCalendar.EndsWith("END:VCALENDAR\r\n")); - - var expectProperties = new[] - { - "METHOD:PUBLISH", - "VERSION:2.0", - }; - - foreach (var p in expectProperties) - { - Assert.IsTrue(serializedCalendar.Contains(NewLine + p + NewLine), "expected '" + p + "' not found"); - } - - InspectSerializedSection(serializedCalendar, "VEVENT", new[] - { - "CLASS:" + evt.Class, - "CREATED:" + CalDateString(evt.Created), - "DTSTAMP:" + CalDateString(evt.DtStamp), - "LASTMODIFIED:" + CalDateString(evt.LastModified), - "SEQUENCE:" + evt.Sequence, - "UID:" + evt.Uid, - "PRIORITY:" + evt.Priority, - "LOCATION:" + evt.Location, - "SUMMARY:" + evt.Summary, - "DTSTART:" + CalDateString(evt.DtStart), - "DTEND:" + CalDateString(evt.DtEnd), - //"TRANSPARENCY:" + TransparencyType.Opaque.ToString().ToUpperInvariant(), - //"STATUS:" + EventStatus.Confirmed.ToString().ToUpperInvariant() - }); - } - } - [Test, Category("Serialization")] - public void AttendeesSerialized() - { - using (var cal = new Calendar() { Method = "REQUEST", Version = "2.0" }) - { - var evt = AttendeeTest.EvtFactory(); - cal.Events.Add(evt); - const string org = "MAILTO:james@test.com"; - evt.Organizer = new Organizer(org); - - evt.Attendees.AddRange(AttendeeTest.AttendeesFactory()); - - var serializer = new CalendarSerializer(new SerializationContext()); - var serializedCalendar = serializer.SerializeToString(cal); - - Console.Write(serializedCalendar); - - var vEvt = InspectSerializedSection(serializedCalendar, "VEVENT", new string[] { - "ORGANIZER:" + org - }); - - foreach (var a in evt.Attendees) - { - var vals = GetValues(vEvt, "ATTENDEE", a.Value.OriginalString); - foreach (var v in new Dictionary { - ["CN"] = a.CommonName, - ["ROLE"] = a.Role, - ["RSVP"] = a.Rsvp.ToString().ToUpperInvariant(), - ["PARTSTAT"] = a.ParticipationStatus - }) { - Assert.IsTrue(vals.ContainsKey(v.Key), "could not find key '{0}'", v.Key); - Assert.AreEqual(v.Value, vals[v.Key], "ATENDEE prop '{0}' differ", v.Key); - } - } - } - } - - //todo test event: - //-GeographicLocation - //-Alarm - #endregion - } -} diff --git a/ical.NET.UnitTests/SerializationTests.cs b/ical.NET.UnitTests/SerializationTests.cs new file mode 100644 index 000000000..e504068a1 --- /dev/null +++ b/ical.NET.UnitTests/SerializationTests.cs @@ -0,0 +1,347 @@ +using System; +using System.Collections; +using Ical.Net; +using Ical.Net.DataTypes; +using Ical.Net.Interfaces; +using Ical.Net.Interfaces.Components; +using Ical.Net.Serialization; +using Ical.Net.Serialization.iCalendar.Serializers; +using NUnit.Framework; +using Ical.Net.Interfaces.DataTypes; +using System.IO; +using System.Collections.Generic; +using Ical.Net.ExtensionMethods; +using System.Text.RegularExpressions; +using System.Linq; + +namespace ical.NET.UnitTests +{ + [TestFixture] + public class SerializationTests + { + #region helperMethods + public static void CompareCalendars(ICalendar cal1, ICalendar cal2) + { + CompareComponents(cal1, cal2); + + Assert.AreEqual(cal1.Children.Count, cal2.Children.Count, "Children count is different between calendars."); + + for (var i = 0; i < cal1.Children.Count; i++) + { + var component1 = cal1.Children[i] as ICalendarComponent; + var component2 = cal2.Children[i] as ICalendarComponent; + if (component1 != null && component2 != null) + { + CompareComponents(component1, component2); + } + } + } + + public static void CompareComponents(ICalendarComponent cb1, ICalendarComponent cb2) + { + foreach (var p1 in cb1.Properties) + { + var isMatch = false; + foreach (var p2 in cb2.Properties.AllOf(p1.Name)) + { + try + { + Assert.AreEqual(p1, p2, "The properties '" + p1.Name + "' are not equal."); + if (p1.Value is IComparable) + { + Assert.AreEqual(0, ((IComparable) p1.Value).CompareTo(p2.Value), "The '" + p1.Name + "' property values do not match."); + } + else if (p1.Value is IEnumerable) + { + CompareEnumerables((IEnumerable) p1.Value, (IEnumerable) p2.Value, p1.Name); + } + else + { + Assert.AreEqual(p1.Value, p2.Value, "The '" + p1.Name + "' property values are not equal."); + } + + isMatch = true; + break; + } + catch { } + } + + Assert.IsTrue(isMatch, "Could not find a matching property - " + p1.Name + ":" + (p1.Value?.ToString() ?? string.Empty)); + } + + Assert.AreEqual(cb1.Children.Count, cb2.Children.Count, "The number of children are not equal."); + for (var i = 0; i < cb1.Children.Count; i++) + { + var child1 = cb1.Children[i] as ICalendarComponent; + var child2 = cb2.Children[i] as ICalendarComponent; + if (child1 != null && child2 != null) + { + CompareComponents(child1, child2); + } + else + { + Assert.AreEqual(child1, child2, "The child objects are not equal."); + } + } + } + + public static void CompareEnumerables(IEnumerable a1, IEnumerable a2, string value) + { + if (a1 == null && a2 == null) + { + return; + } + + Assert.IsFalse((a1 == null && a2 != null) || (a1 != null && a2 == null), value + " do not match - one item is null"); + + var enum1 = a1.GetEnumerator(); + var enum2 = a2.GetEnumerator(); + + while (enum1.MoveNext() && enum2.MoveNext()) + { + Assert.AreEqual(enum1.Current, enum2.Current, value + " do not match"); + } + } + + private const string _newLine = "\r\n"; // I suspect the spec actually specifies this, and so Environment.NewLine would not be appropriate + public static string InspectSerializedSection(string serialized, string sectionName, IEnumerable elements) + { + const string notFound = "expected '{0}' not found"; + var searchFor = "BEGIN:" + sectionName; + var begin = serialized.IndexOf(searchFor); + Assert.AreNotEqual(-1, begin, notFound, searchFor); + + searchFor = "END:" + sectionName; + var end = serialized.IndexOf(searchFor, begin); + Assert.AreNotEqual(-1, end, notFound, searchFor); + + var searchRegion = serialized.Substring(begin, end - begin + 1); + + foreach (var e in elements) + { + Assert.IsTrue(searchRegion.Contains(_newLine + e + _newLine), notFound, e); + } + + return searchRegion; + } + + //3 formats - UTC, local time as defined in vTimeZone, and floating, + //at some point it would be great to independently unit test string serialization of an IDateTime object, into its 3 forms + //http://www.kanzaki.com/docs/ical/dateTime.html + static string CalDateString(IDateTime cdt) + { + var returnVar = cdt.Year.ToString() + cdt.Month + cdt.Day + 'T' + cdt.Hour + cdt.Minute + cdt.Second; + if (cdt.IsUniversalTime) + { + return returnVar + 'Z'; + } + + return string.IsNullOrEmpty(cdt.TzId) + ? returnVar + : $"TZID={cdt.TzId}:{returnVar}"; + } + + //This method needs renaming + static Dictionary GetValues(string serialized, string name, string value) + { + var lengthened = serialized.Replace(_newLine + ' ', string.Empty); + //using a regex for now - for the sake of speed, it may be worth creating a C# text search later + var match = Regex.Match(lengthened, '^' + Regex.Escape(name) + ";(.*):" + Regex.Escape(value) + _newLine, RegexOptions.Multiline); + Assert.IsTrue(match.Success, $"could not find a(n) '{name}' with value '{value}'"); + return match.Groups[1].Value.Split(';').Select(v=>v.Split('=')).ToDictionary(v=>v[0], v=>v.Length>1 ? v[1] : null); + } + #endregion //helperMethods + + #region tests + [Test, Category("Serialization")] + public void TimeZoneSerialize() + { + var cal = new Calendar() + { + Method = "PUBLISH", + Version = "2.0" + }; + + const string exampleTz = "New Zealand Standard Time"; // can change this but should SupportDaylightTime + var tzi = TimeZoneInfo.FindSystemTimeZoneById(exampleTz); + var timezone = VTimeZone.FromSystemTimeZone(tzi); + cal.AddTimeZone(timezone); + var evt = new Event + { + Summary = "Testing", + Start = new CalDateTime(2016, 7, 14, timezone.Id), + End = new CalDateTime(2016, 7, 15, timezone.Id) + }; + cal.Events.Add(evt); + + var serializer = new CalendarSerializer(new SerializationContext()); + var serializedCalendar = serializer.SerializeToString(cal); + + Console.Write(serializedCalendar); + + var vTimezone = InspectSerializedSection(serializedCalendar, "VTIMEZONE", new[] {"TZID:" + timezone.Id}); + var o = tzi.BaseUtcOffset.ToString("hhmm", System.Globalization.CultureInfo.InvariantCulture); + + InspectSerializedSection(vTimezone, "STANDARD", new[] {"TZNAME:" + tzi.StandardName, "TZOFFSETTO:" + o + //todo - standard time, for NZ standard time (current example) + //"DTSTART:20150402T030000", + //"RRULE:FREQ=YEARLY;BYDAY=1SU;BYHOUR=3;BYMINUTE=0;BYMONTH=4", + //"TZOFFSETFROM:+1300" + }); + + + InspectSerializedSection(vTimezone, "DAYLIGHT", new[] {"TZNAME:" + tzi.DaylightName, "TZOFFSETFROM:" + o}); + } + [Test, Category("Serialization")] + public void SerializeDeserialize() + { + var cal1 = new Calendar() + { + Method = "PUBLISH", + Version = "2.0" + }; + + var evt = new Event + { + Class = "PRIVATE", + Created = new CalDateTime(2010, 3, 25, 12, 53, 35), + DtStamp = new CalDateTime(2010, 3, 25, 12, 53, 35), + LastModified = new CalDateTime(2010, 3, 27, 13, 53, 35), + Sequence = 0, + Uid = "42f58d4f-847e-46f8-9f4a-ce52697682cf", + Priority = 5, + Location = "here", + Summary = "test", + DtStart = new CalDateTime(2012, 3, 25, 12, 50, 00), + DtEnd = new CalDateTime(2012, 3, 25, 13, 10, 00) + }; + cal1.Events.Add(evt); + + var serializer = new CalendarSerializer(new SerializationContext()); + var serializedCalendar = serializer.SerializeToString(cal1); + using (var sr = new StringReader(serializedCalendar)) + { + var cal2 = Calendar.LoadFromStream(sr)[0]; + CompareCalendars(cal1, cal2); + } + } + + [Test, Category("Serialization")] + public void EventPropertiesSerialized() + { + var cal = new Calendar() + { + Method = "PUBLISH", + Version = "2.0" + }; + + var evt = new Event + { + Class = "PRIVATE", + Created = new CalDateTime(2010, 3, 25, 12, 53, 35), + DtStamp = new CalDateTime(2010, 3, 25, 12, 53, 35), + LastModified = new CalDateTime(2010, 3, 27, 13, 53, 35), + Sequence = 0, + Uid = "42f58d4f-847e-46f8-9f4a-ce52697682cf", + Priority = 5, + Location = "here", + Summary = "test", + DtStart = new CalDateTime(2012, 3, 25, 12, 50, 00), + DtEnd = new CalDateTime(2012, 3, 25, 13, 10, 00), + //not yet testing property below as serialized output currently does not comply with RTFC 2445 + //Transparency = TransparencyType.Opaque, + //Status = EventStatus.Confirmed + }; + cal.Events.Add(evt); + + var serializer = new CalendarSerializer(new SerializationContext()); + var serializedCalendar = serializer.SerializeToString(cal); + + Console.Write(serializedCalendar); + Assert.IsTrue(serializedCalendar.StartsWith("BEGIN:VCALENDAR")); + Assert.IsTrue(serializedCalendar.EndsWith("END:VCALENDAR\r\n")); + + var expectProperties = new[] {"METHOD:PUBLISH", "VERSION:2.0",}; + + foreach (var p in expectProperties) + { + Assert.IsTrue(serializedCalendar.Contains(_newLine + p + _newLine), "expected '" + p + "' not found"); + } + + InspectSerializedSection(serializedCalendar, "VEVENT", + new[] + { + "CLASS:" + evt.Class, "CREATED:" + CalDateString(evt.Created), "DTSTAMP:" + CalDateString(evt.DtStamp), + "LASTMODIFIED:" + CalDateString(evt.LastModified), "SEQUENCE:" + evt.Sequence, "UID:" + evt.Uid, "PRIORITY:" + evt.Priority, + "LOCATION:" + evt.Location, "SUMMARY:" + evt.Summary, "DTSTART:" + CalDateString(evt.DtStart), "DTEND:" + CalDateString(evt.DtEnd), + //"TRANSPARENCY:" + TransparencyType.Opaque.ToString().ToUpperInvariant(), + //"STATUS:" + EventStatus.Confirmed.ToString().ToUpperInvariant() + }); + } + + private const string _requiredParticipant = "REQ-PARTICIPANT"; //this string may be added to the api in the future + private static readonly IList _attendees = new List + { + new Attendee("MAILTO:james@example.com") + { + CommonName = "James James", + Role = _requiredParticipant, + Rsvp = true, + ParticipationStatus = ParticipationStatus.Tentative + }, + new Attendee("MAILTO:mary@example.com") + { + CommonName = "Mary Mary", + Role = _requiredParticipant, + Rsvp = true, + ParticipationStatus = ParticipationStatus.Accepted + } + }.AsReadOnly(); + + [Test, Category("Serialization")] + public void AttendeesSerialized() + { + var cal = new Calendar() + { + Method = "REQUEST", + Version = "2.0" + }; + + var evt = AttendeeTest.VEventFactory(); + cal.Events.Add(evt); + const string org = "MAILTO:james@example.com"; + evt.Organizer = new Organizer(org); + + evt.Attendees.AddRange(_attendees); + + var serializer = new CalendarSerializer(new SerializationContext()); + var serializedCalendar = serializer.SerializeToString(cal); + + Console.Write(serializedCalendar); + + var vEvt = InspectSerializedSection(serializedCalendar, "VEVENT", new string[] {"ORGANIZER:" + org}); + + foreach (var a in evt.Attendees) + { + var vals = GetValues(vEvt, "ATTENDEE", a.Value.OriginalString); + foreach (var v in new Dictionary + { + ["CN"] = a.CommonName, + ["ROLE"] = a.Role, + ["RSVP"] = a.Rsvp.ToString() + .ToUpperInvariant(), + ["PARTSTAT"] = a.ParticipationStatus + }) + { + Assert.IsTrue(vals.ContainsKey(v.Key), $"could not find key '{v.Key}'"); + Assert.AreEqual(v.Value, vals[v.Key], $"ATENDEE prop '{v.Key}' differ"); + } + } + } + + //todo test event: + //-GeographicLocation + //-Alarm + #endregion + } +} diff --git a/ical.NET.UnitTests/ical.NET.UnitTests.csproj b/ical.NET.UnitTests/ical.NET.UnitTests.csproj index 710cc6aa2..dd7857379 100644 --- a/ical.NET.UnitTests/ical.NET.UnitTests.csproj +++ b/ical.NET.UnitTests/ical.NET.UnitTests.csproj @@ -72,7 +72,9 @@ + + @@ -82,7 +84,7 @@ - +