Skip to content

Commit

Permalink
Serialize array of controls (#612)
Browse files Browse the repository at this point in the history
Co-authored-by: Andrew Petrochuk (from Dev Box) <[email protected]>
  • Loading branch information
petrochuk and anpetroc authored Mar 31, 2024
1 parent 9d0e570 commit b93c8e8
Show file tree
Hide file tree
Showing 17 changed files with 281 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ internal static class YamlDeserializerExtensions
{
internal static object? DeserializeControl(this IYamlDeserializer deserializer, TextReader yamlReader, Type controlType)
{
var deserializeMethod = typeof(IYamlDeserializer).GetMethod(nameof(IYamlDeserializer.DeserializeControl), types: new[] { typeof(TextReader) })!.MakeGenericMethod(controlType);
var deserializeMethod = typeof(IYamlDeserializer).GetMethod(nameof(IYamlDeserializer.Deserialize), types: new[] { typeof(TextReader) })!.MakeGenericMethod(controlType);
return deserializeMethod.Invoke(deserializer, new object[] { yamlReader });
}
}
6 changes: 3 additions & 3 deletions src/Persistence.Tests/Yaml/DeserializerInvalidTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void Deserialize_ShouldFailWhenYamlIsInvalid()
// Act
try
{
var result = deserializer.DeserializeControl<Control>(yamlReader);
var result = deserializer.Deserialize<Control>(yamlReader);
if (result is not Control)
throw new InvalidOperationException("Expected a control");
Expand Down Expand Up @@ -57,7 +57,7 @@ public void Deserialize_ShouldFailWhenExpectingDifferentType()

// Act
// Explicitly using the wrong type BuiltInControl
Action act = () => { deserializer.DeserializeControl<BuiltInControl>(yamlReader); }; // Explicitly using the wrong type BuiltInControl
Action act = () => { deserializer.Deserialize<BuiltInControl>(yamlReader); }; // Explicitly using the wrong type BuiltInControl

// Assert
act.Should().Throw<YamlException>()
Expand All @@ -72,7 +72,7 @@ public void Deserialize_EmptyString()
var deserializer = TestBase.ServiceProvider.GetRequiredService<IYamlSerializationFactory>().CreateDeserializer();

// Act
Action act = () => deserializer.DeserializeControl<Control>(string.Empty);
Action act = () => deserializer.Deserialize<Control>(string.Empty);

// Assert
act.Should().Throw<ArgumentNullException>().WithMessage("Value cannot be null. (Parameter 'yaml')");
Expand Down
28 changes: 14 additions & 14 deletions src/Persistence.Tests/Yaml/DeserializerValidTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void Deserialize_ShouldParseSimpleStructure(bool isTextFirst,

var deserializer = ServiceProvider.GetRequiredService<IYamlSerializationFactory>().CreateDeserializer(isTextFirst);

var sut = deserializer.DeserializeControl<Control>(yaml);
var sut = deserializer.Deserialize<Control>(yaml);
sut.Should().NotBeNull().And.BeOfType<Screen>();
sut.Name.Should().Be("Screen1");
sut.TemplateId.Should().Be("http://microsoft.com/appmagic/screen");
Expand Down Expand Up @@ -76,11 +76,11 @@ public void Deserialize_ShouldParseYamlWithChildNodes()
);

var serializer = ServiceProvider.GetRequiredService<IYamlSerializationFactory>().CreateSerializer();
var yaml = serializer.SerializeControl(graph.BeforeSerialize());
var yaml = serializer.SerializeControl(graph);

var deserializer = ServiceProvider.GetRequiredService<IYamlSerializationFactory>().CreateDeserializer();

var sut = deserializer.DeserializeControl<Control>(yaml).AfterDeserialize(ControlFactory);
var sut = deserializer.Deserialize<Control>(yaml);
sut.Should().NotBeNull().And.BeOfType<Screen>();
sut.Name.Should().Be("Screen1");
sut.TemplateId.Should().Be("http://microsoft.com/appmagic/screen");
Expand Down Expand Up @@ -124,7 +124,7 @@ public void Deserialize_ShouldParseYamlForCustomControl()

var deserializer = ServiceProvider.GetRequiredService<IYamlSerializationFactory>().CreateDeserializer();

var sut = deserializer.DeserializeControl<Control>(yaml);
var sut = deserializer.Deserialize<Control>(yaml);
sut.Should().NotBeNull().And.BeOfType<CustomControl>();
sut.Name.Should().Be("CustomControl1");
sut.TemplateId.Should().Be("http://localhost/#customcontrol");
Expand All @@ -147,7 +147,7 @@ public void Deserialize_ShouldParseBuiltInControlFromYamlCustomControl(string te

var deserializer = ServiceProvider.GetRequiredService<IYamlSerializationFactory>().CreateDeserializer();

var sut = deserializer.DeserializeControl<Control>(yaml);
var sut = deserializer.Deserialize<Control>(yaml);
sut.Should().NotBeNull().And.BeOfType<BuiltInControl>();
}

Expand Down Expand Up @@ -192,7 +192,7 @@ public void Deserialize_App_ShouldSucceed(string path, string expectedName, int
using var yamlReader = new StreamReader(yamlStream);

// Act
var app = deserializer.DeserializeControl<App>(yamlReader);
var app = deserializer.Deserialize<App>(yamlReader);

app!.Name.Should().NotBeNull().And.Be(expectedName);
app.Children.Should().NotBeNull().And.HaveCount(controlCount);
Expand All @@ -210,7 +210,7 @@ public void Deserialize_App_WithSettings_ShouldSucceed(string path, string expec
using var yamlReader = new StreamReader(yamlStream);

// Act
var app = deserializer.DeserializeControl<App>(yamlReader);
var app = deserializer.Deserialize<App>(yamlReader);

app.Settings.Should().NotBeNull();
app.Settings!.Name.Should().NotBeNull().And.Be(expectedName);
Expand All @@ -228,7 +228,7 @@ public void Deserialize_ShouldIgnoreUnmatchedProperties(string path)
using var yamlReader = new StreamReader(yamlStream);

// Act
var controlObj = deserializer.DeserializeControl<Screen>(yamlReader);
var controlObj = deserializer.Deserialize<Screen>(yamlReader);

// Assert
controlObj.Should().NotBeNull();
Expand All @@ -243,7 +243,7 @@ public void Deserialize_Strings()
using var yamlReader = new StreamReader(yamlStream);

// Act
var controlObj = deserializer.DeserializeControl<BuiltInControl>(yamlReader);
var controlObj = deserializer.Deserialize<BuiltInControl>(yamlReader);

// Assert
controlObj.Should().NotBeNull();
Expand Down Expand Up @@ -278,7 +278,7 @@ public void Deserialize_Component_ShouldSucceed(
using var yamlReader = new StreamReader(yamlStream);

// Act
var component = deserializer.DeserializeControl<Component>(yamlReader);
var component = deserializer.Deserialize<Component>(yamlReader);

// Assert
component.Name.Should().Be(expectedName);
Expand All @@ -302,7 +302,7 @@ public void Variant_ShouldSucceed(
using var yamlReader = new StreamReader(yamlStream);

// Act
var control = deserializer.DeserializeControl<BuiltInControl>(yamlReader);
var control = deserializer.Deserialize<BuiltInControl>(yamlReader);

// Assert
control.Name.Should().Be(expectedName);
Expand All @@ -321,7 +321,7 @@ public void Deserialize_Should_AddGalleryTemplate(string path)
using var yamlReader = new StreamReader(yamlStream);

// Act
var screen = deserializer.DeserializeControl<Screen>(yamlReader).AfterDeserialize(ControlFactory);
var screen = deserializer.Deserialize<Screen>(yamlReader);

// Assert
screen.Should().NotBeNull();
Expand Down Expand Up @@ -385,7 +385,7 @@ public void Deserialize_ShouldParseYamlForComponentCustomProperties(CustomProper

var sut = ServiceProvider.GetRequiredService<IYamlSerializationFactory>().CreateDeserializer();

var component = sut.DeserializeControl<Component>(expectedYaml);
var component = sut.Deserialize<Component>(expectedYaml);
component.Should().NotBeNull();
component!.CustomProperties.Should().NotBeNull().And.HaveCount(1);

Expand All @@ -403,7 +403,7 @@ public void Deserialize_ShouldParseYamlForGroupWithChildren(string path, int exp
using var yamlReader = new StreamReader(yamlStream);

// Act
var group = deserializer.DeserializeControl<GroupControl>(yamlReader);
var group = deserializer.Deserialize<GroupControl>(yamlReader);

// Assert
group.Should().NotBeNull();
Expand Down
30 changes: 29 additions & 1 deletion src/Persistence.Tests/Yaml/ValidSerializerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public void Serialize_Should_FlattenGalleryTemplate(string expectedPath)

var serializer = ServiceProvider.GetRequiredService<IYamlSerializationFactory>().CreateSerializer();

var sut = serializer.SerializeControl(graph.BeforeSerialize()).NormalizeNewlines();
var sut = serializer.SerializeControl(graph).NormalizeNewlines();
var expectedYaml = File.ReadAllText(expectedPath).NormalizeNewlines();
sut.Should().Be(expectedYaml);
}
Expand Down Expand Up @@ -228,6 +228,34 @@ public void Should_SortBy_Category(string expectedPath, string templateName, str
sut.Should().Be(expectedYaml);
}


[TestMethod]
[DataRow(@"_TestData/ValidYaml/With-list-of-controls.pa.yaml", "SuperButton")]
public void Should_Serialize_List_Of_Controls(string expectedPath, string templateName)
{
var graph = new List<Control>()
{
ControlFactory.Create("BuiltIn Control1", template: templateName,
properties: new()
{
{ "Text", "Just text" },
}
),
ControlFactory.Create("BuiltIn Label", template: "Label",
properties: new()
{
{ "Text", "Just label text" },
}
),
};
var serializer = ServiceProvider.GetRequiredService<IYamlSerializationFactory>().CreateSerializer();

var sut = serializer.Serialize(graph).NormalizeNewlines();
var expectedYaml = File.ReadAllText(expectedPath).NormalizeNewlines();
sut.Should().Be(expectedYaml);
}


public static IEnumerable<object[]> Serialize_ShouldCreateValidYamlForComponentCustomProperties_Data => new List<object[]>()
{
new object[]
Expand Down
65 changes: 63 additions & 2 deletions src/Persistence.Tests/Yaml/ZIndexOrderingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void SerializedChildrenInZOrder()

var serializer = ServiceProvider.GetRequiredService<IYamlSerializationFactory>().CreateSerializer();

var sut = serializer.SerializeControl(graph.BeforeSerialize());
var sut = serializer.SerializeControl(graph);
var expected = File.ReadAllText(@"_TestData/ValidYaml/ZIndexOrdering/Screen-with-sorted-children.pa.yaml");
sut.Should().BeEquivalentTo(expected);
}
Expand All @@ -39,7 +39,7 @@ public void DeserializeChildrenShouldHaveMatchingZIndexProperty()
using var yamlStream = File.OpenRead(@"_TestData/ValidYaml/ZIndexOrdering/Screen-with-sorted-children.pa.yaml");
using var yamlReader = new StreamReader(yamlStream);

var sut = deserializer.DeserializeControl<Screen>(yamlReader).AfterDeserialize(ControlFactory);
var sut = deserializer.Deserialize<Screen>(yamlReader);

sut.Children.Should()
.HaveCount(5)
Expand All @@ -53,6 +53,67 @@ public void DeserializeChildrenShouldHaveMatchingZIndexProperty()
});
}

[TestMethod]
public void Deserialize_List_Should_Be_With_ZIndex()
{
var deserializer = ServiceProvider.GetRequiredService<IYamlSerializationFactory>().CreateDeserializer();

using var yamlStream = File.OpenRead(@"_TestData/ValidYaml/ZIndexOrdering/With-list-of-controls-with-children.pa.yaml");
using var yamlReader = new StreamReader(yamlStream);

var result = deserializer.Deserialize<List<Control>>(yamlReader);

result.Should().HaveCount(3);
for (var i = 0; i < result.Count; i++)
{
result[i].Name.Should().Be($"Group{i + 1}");
result[i].Children.Should().NotBeNull();
for (var j = 0; j < result[i].Children!.Count; j++)
{
result[i].Children![j].Name.Should().Be($"Label{j + 1}");
result[i].Children![j].ZIndex.Should().Be(result[i].Children!.Count - j);
}
}
}

[TestMethod]
public void Seralizes_List_Should_Be_Without_ZIndex()
{
var graph = new List<Control>
{
MakeLabelWithZIndex(1),
MakeLabelWithZIndex(3),
MakeLabelWithZIndex(2),
MakeLabelWithZIndex(5),
MakeLabelWithZIndex(4),
};

var serializer = ServiceProvider.GetRequiredService<IYamlSerializationFactory>().CreateSerializer();

var sut = serializer.Serialize(graph);
var expected = File.ReadAllText(@"_TestData/ValidYaml/ZIndexOrdering/With-list-of-controls.pa.yaml");
sut.Should().BeEquivalentTo(expected);
}

[TestMethod]
public void Seralizes_SortedList_Should_Be_Without_ZIndex()
{
var graph = new SortedList<int, Control>
{
{1, MakeLabelWithZIndex(1) },
{3, MakeLabelWithZIndex(3) },
{2, MakeLabelWithZIndex(2) },
{5, MakeLabelWithZIndex(5) },
{4, MakeLabelWithZIndex(4) },
};

var serializer = ServiceProvider.GetRequiredService<IYamlSerializationFactory>().CreateSerializer();

var sut = serializer.Serialize(graph.Values);
var expected = File.ReadAllText(@"_TestData/ValidYaml/ZIndexOrdering/With-sortedlist-of-controls.pa.yaml");
sut.Should().BeEquivalentTo(expected);
}

private Control MakeLabelWithZIndex(int i)
{
return ControlFactory.Create($"Label{i}", template: "text",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
- Control: SuperButton
Name: BuiltIn Control1
Properties:
Text: =Just text
- Label:
Name: BuiltIn Label
Properties:
Text: =Just label text
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
- Group:
Name: Group1
Children:
- Text:
Name: Label1
- Text:
Name: Label2
- Group:
Name: Group2
Children:
- Text:
Name: Label1
- Text:
Name: Label2
- Group:
Name: Group3
Children:
- Text:
Name: Label1
- Text:
Name: Label2

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
- Text:
Name: Label1
- Text:
Name: Label3
- Text:
Name: Label2
- Text:
Name: Label5
- Text:
Name: Label4
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
- Text:
Name: Label1
- Text:
Name: Label2
- Text:
Name: Label3
- Text:
Name: Label4
- Text:
Name: Label5
5 changes: 5 additions & 0 deletions src/Persistence/Collections/ControlPropertiesCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ public void Add(Tuple<string, string> keyValue)
_properties.Add(keyValue.Item1, new ControlProperty(keyValue.Item1, keyValue.Item2));
}

public void Remove(string key)
{
_properties.Remove(key);
}

public IEnumerator<KeyValuePair<string, ControlProperty>> GetEnumerator()
{
return _properties.GetEnumerator();
Expand Down
Loading

0 comments on commit b93c8e8

Please sign in to comment.