Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 49 additions & 8 deletions Ical.Net.Tests/CalendarPropertiesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,68 @@ public void AddPropertyShouldNotIncludePropertyNameInValue()
}

[Test]
[Ignore("Calendar properties aren't being properly serialized")]
public void PropertySerialization_Tests()
public void PropertySerialization()
{
const string formatted =
@"FMTTYPE=text/html:<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 3.2//EN"">\n<HTML>\n<HEAD>\n<META NAME=""Generator"" CONTENT=""MS Exchange Server version rmj.rmm.rup.rpr"">\n<TITLE></TITLE>\n</HEAD>\n<BODY>\n<!-- Converted from text/rtf format -->\n\n<P DIR=LTR><SPAN LANG=""en-us""><FONT FACE=""Calibri"">This is some</FONT></SPAN><SPAN LANG=""en-us""><B> <FONT FACE=""Calibri"">HTML</FONT></B></SPAN><SPAN LANG=""en-us""><FONT FACE=""Calibri""></FONT></SPAN><SPAN LANG=""en-us""><U> <FONT FACE=""Calibri"">formatted</FONT></U></SPAN><SPAN LANG=""en-us""><FONT FACE=""Calibri""></FONT></SPAN><SPAN LANG=""en-us""><I> <FONT FACE=""Calibri"">text</FONT></I></SPAN><SPAN LANG=""en-us""><FONT FACE=""Calibri"">.</FONT></SPAN><SPAN LANG=""en-us""></SPAN></P>\n\n</BODY>\n</HTML>";

var start = DateTime.Now;
const string propValue =
"""<html><body>BodyText</body></html>""";
var start = DateTime.UtcNow;
var end = start.AddHours(1);
var @event = new CalendarEvent
{
Start = new CalDateTime(start),
End = new CalDateTime(end),
Description = "This is a description",
};
var property = new CalendarProperty("X-ALT-DESC", formatted);
var property = new CalendarProperty("X-ALT-DESC", propValue);
// Parameters most not be part of the value
property.Parameters.Add("FMTTYPE", "text/html");
var property2 = new CalendarProperty("ATTENDEE", "mailto:[email protected]");
property2.Parameters.Add("MEMBER", "mailto:[email protected],mailto:[email protected]");
@event.Properties.Add(property2);
@event.AddProperty(property);
var calendar = new Calendar();
calendar.Events.Add(@event);

var serialized = new CalendarSerializer().SerializeToString(calendar);
Assert.That(serialized, Does.Contain("X-ALT-DESC;"));
Assert.That(serialized, Does.Contain($"X-ALT-DESC;FMTTYPE=text/html:{propValue}"),
"Parameter and value should get serialized standard compliant");
}

[Test]
public void PropertyDeserialization()
{
var ics = """
BEGIN:VCALENDAR
PRODID:-//github.com/ical-org/ical.net//NONSGML ical.net 5.0.0.0//EN
VERSION:2.0
BEGIN:VEVENT
DESCRIPTION:This is a description
DTEND:20250518T145922Z
DTSTAMP:20250518T135922Z
DTSTART:20250518T135922Z
SEQUENCE:0
UID:8f7aa9fc-e9d7-4276-8bf6-915dfe168f0d
X-ALT-DESC;FMTTYPE=text/html:<html><body>BodyText</body></html>
X-PROJECTS;PROP=name;PRIO=high:ProjectA,ProjectB
END:VEVENT
END:VCALENDAR
""";
var calendar = Calendar.Load(ics)!;
var calEvent = calendar.Events.First();
var propDescription = calEvent.Properties.FirstOrDefault(x => x.Name == "X-ALT-DESC")!;
var propProjects = calEvent.Properties.FirstOrDefault(x => x.Name == "X-PROJECTS")!;

Assert.Multiple(() =>
{
Assert.That(propDescription.Parameters, Has.Count.EqualTo(1));
Assert.That(propDescription.Value, Is.EqualTo("<html><body>BodyText</body></html>"));
Assert.That(propDescription.Parameters.FirstOrDefault(p => p.Name == "FMTTYPE")!.Value, Is.EqualTo("text/html"));

Assert.That(propProjects.Parameters, Has.Count.EqualTo(2), "Parameter list should have 2 elements");
Assert.That(propProjects.Value, Is.EqualTo("ProjectA,ProjectB"));
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should propProject.Values be a list containing ProjectA and ProjectB as elements?

Assert.That(propProjects.Parameters.FirstOrDefault(p => p.Name == "PROP")!.Value!.ToString(), Is.EqualTo("name"));
Assert.That(propProjects.Parameters.FirstOrDefault(p => p.Name == "PRIO")!.Value!.ToString(), Is.EqualTo("high"));
});
}

[Test]
Expand Down
20 changes: 10 additions & 10 deletions Ical.Net.Tests/Calendars/Serialization/Categories1.ics
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar//EN
BEGIN:VEVENT
CREATED:20060717T210517Z
LAST-MODIFIED:20060717T210718Z
DTSTAMP:20060717T210718Z
CREATED:20250717T210517Z
LAST-MODIFIED:20250717T210718Z
DTSTAMP:20250717T210718Z
UID:uuid1153170430406
SUMMARY:Test event
CATEGORIES:One,Two,Three
CATEGORIES:Four,Five,Six
CATEGORIES;ENCODING=BASE64:U2V2ZW4=
CATEGORIES:A string of text with nothing less than a comma\, semicolon\; and a newline\n.
DTSTART;TZID=US-Eastern:20060902T090000
RRULE:FREQ=WEEKLY;INTERVAL=2;UNTIL=20061224T000000Z;WKST=SU;BYDAY=MO,WE,FR
EXDATE:20060914T050000/PT2H
DTEND;TZID=US-Eastern:20060902T100000
CATEGORIES:A string of text with comma\, semicolon\; and a newline\n.
DTSTART;TZID=US-Eastern:20250902T090000
RRULE:FREQ=WEEKLY;INTERVAL=2;UNTIL=20251224T000000Z;WKST=SU;BYDAY=MO,WE,FR
EXDATE:20250914
DTEND;TZID=US-Eastern:20250902T100000
LOCATION:Daywest
END:VEVENT
BEGIN:VTIMEZONE
TZID:US-Eastern
LAST-MODIFIED:19870101T000000Z
LAST-MODIFIED:20250717T210517Z
TZURL:http://zones.stds_r_us.net/tz/US-Eastern
BEGIN:STANDARD
DTSTART:19671029T020000
Expand Down
12 changes: 6 additions & 6 deletions Ical.Net.Tests/DeserializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,25 +162,25 @@ public void CaseInsensitive4()
[Test]
public void Categories1_2()
{
var iCal = Calendar.Load(IcsFiles.Categories1);
var iCal = Calendar.Load(IcsFiles.Categories1)!;
ProgramTest.TestCal(iCal);
var evt = iCal.Events.First();

var items = new List<string>();
items.AddRange(new[]
{
items.AddRange([
"One", "Two", "Three",
"Four", "Five", "Six",
"Seven", "A string of text with nothing less than a comma, semicolon; and a newline\n."
});
"Seven", // Category has parameter ENCODING=BASE64:U2V2ZW4=
"A string of text with comma, semicolon; and a newline\n."
]);

var found = new Dictionary<string, bool>();
foreach (var s in evt.Categories.Where(s => items.Contains(s)))
{
found[s] = true;
}

foreach (string item in items)
foreach (var item in items)
{
Assert.That(found.ContainsKey(item), Is.True, "Event should contain CATEGORY '" + item + "', but it was not found.");
}
Expand Down
42 changes: 22 additions & 20 deletions Ical.Net.Tests/SerializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ public void SerializeDeserialize()
cal1.Events.Add(evt);

var serializer = new CalendarSerializer();
var serializedCalendar = serializer.SerializeToString(cal1);
var serializedCalendar = serializer.SerializeToString(cal1)!;
var cal2 = Calendar.Load(serializedCalendar);
CompareCalendars(cal1, cal2);
}
Expand All @@ -253,24 +253,23 @@ public void EventPropertiesSerialized()
var evt = new CalendarEvent
{
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),
Created = new CalDateTime(2025, 3, 25, 12, 53, 35),
DtStamp = new CalDateTime(2025, 3, 25, 12, 53, 35),
LastModified = new CalDateTime(2025, 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
DtStart = new CalDateTime(2025, 3, 25, 12, 50, 00),
DtEnd = new CalDateTime(2025, 3, 25, 13, 10, 00),
Transparency = TransparencyType.Opaque,
Status = EventStatus.Confirmed
};
cal.Events.Add(evt);

var serializer = new CalendarSerializer();
var serializedCalendar = serializer.SerializeToString(cal);
var serializedCalendar = serializer.SerializeToString(cal)!;

Assert.Multiple(() =>
{
Expand All @@ -282,18 +281,21 @@ public void EventPropertiesSerialized()

foreach (var p in expectProperties)
{
Assert.That(serializedCalendar, Does.Contain(SerializationConstants.LineBreak + p + SerializationConstants.LineBreak), "expected '" + p + "' not found");
Assert.That(serializedCalendar,
Does.Contain(SerializationConstants.LineBreak + p + SerializationConstants.LineBreak),
"expected '" + p + "' not found");
}

InspectSerializedSection(serializedCalendar, "VEVENT",
new[]
{
"CLASS:" + evt.Class, "CREATED:" + CalDateString(evt.Created), "DTSTAMP:" + CalDateString(evt.DtStamp),
"LAST-MODIFIED:" + 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()
});
[
"CLASS:" + evt.Class, "CREATED:" + CalDateString(evt.Created), "DTSTAMP:" + CalDateString(evt.DtStamp),
"LAST-MODIFIED:" + 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),
"TRANSP:" + TransparencyType.Opaque.ToUpperInvariant(),
"STATUS:" + EventStatus.Confirmed.ToUpperInvariant()
]);
}

private static readonly IList<Attendee> _attendees = new List<Attendee>
Expand Down Expand Up @@ -365,7 +367,7 @@ public void AttendeesSerialized()
public void ZeroDuration_Test()
{
var result = new DurationSerializer().SerializeToString(Duration.Zero);
Assert.That("P0D".Equals(result, StringComparison.Ordinal), Is.True);
Assert.That(result, Is.EqualTo("P0D"));
}

[Test]
Expand Down
25 changes: 0 additions & 25 deletions Ical.Net.Tests/SimpleDeserializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,31 +163,6 @@ public void CaseInsensitive4()
Assert.That(iCal.Version, Is.EqualTo("2.5"));
}

[Test, Category("Deserialization")]
public void Categories1_2()
{
var iCal = SimpleDeserializer.Default.Deserialize(new StringReader(IcsFiles.Categories1)).Cast<Calendar>().Single();
ProgramTest.TestCal(iCal);
var evt = iCal.Events.First();

var items = new List<string>();
items.AddRange(new[]
{
"One", "Two", "Three",
"Four", "Five", "Six",
"Seven", "A string of text with nothing less than a comma, semicolon; and a newline\n."
});

var found = new Dictionary<string, bool>();
foreach (var s in evt.Categories.Where(s => items.Contains(s)))
{
found[s] = true;
}

foreach (string item in items)
Assert.That(found.ContainsKey(item), Is.True, "Event should contain CATEGORY '" + item + "', but it was not found.");
}

[Test, Category("Deserialization")]
public void EmptyLines1()
{
Expand Down
2 changes: 1 addition & 1 deletion Ical.Net/CalendarComponents/CalendarComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,6 @@ public virtual void AddProperty(string name, string value)
public virtual void AddProperty(ICalendarProperty p)
{
p.Parent = this;
Properties.Set(p.Name, p.Value);
Properties.Add(p);
}
}
Loading