Skip to content

Commit

Permalink
serializing control properties in alphabetical order (#525)
Browse files Browse the repository at this point in the history
  • Loading branch information
mizrael authored Jan 26, 2024
1 parent 89b44d8 commit 28fcab4
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void Deserialize_ShouldParseYamlWithChildNodes()
},
Controls = new Control[]
{
new Label()
new Text()
{
Name = "Label1",
Properties = new Dictionary<string, ControlPropertyValue>()
Expand Down Expand Up @@ -89,9 +89,9 @@ public void Deserialize_ShouldParseYamlWithChildNodes()
sut.Properties["Text"].Value.Should().Be("I am a screen");

sut.Controls.Should().NotBeNull().And.HaveCount(2);
sut.Controls![0].Should().BeOfType<Label>();
sut.Controls![0].Should().BeOfType<Text>();
sut.Controls![0].Name.Should().Be("Label1");
sut.Controls![0].ControlUri.Should().Be(BuiltInTemplatesUris.Label);
sut.Controls![0].ControlUri.Should().Be(BuiltInTemplatesUris.Text);
sut.Controls![0].Properties.Should().NotBeNull()
.And.HaveCount(1)
.And.ContainKey("Text");
Expand Down Expand Up @@ -136,4 +136,22 @@ public void Deserialize_ShouldParseYamlForCustomControl()
.And.ContainKey("Text");
sut.Properties["Text"].Value.Should().Be("I am a custom control");
}

[TestMethod]
public void Deserialize_ShouldParseBuiltInControlFromYamlCustomControl()
{
var graph = new CustomControl()
{
ControlUri = BuiltInTemplatesUris.Button,
Name = "MyCustomButton",
};

var serializer = YamlSerializationFactory.CreateSerializer();
var yaml = serializer.Serialize(graph);

var deserializer = YamlSerializationFactory.CreateDeserializer();

var sut = deserializer.Deserialize<Control>(yaml);
sut.Should().NotBeNull().And.BeOfType<Button>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,26 @@ public void Serialize_ShouldCreateValidYamlForSimpleStructure()
sut.Should().Be($"Screen: {Environment.NewLine}Name: Screen1{Environment.NewLine}Properties:{Environment.NewLine} Text: I am a screen{Environment.NewLine}");
}

[TestMethod]
public void Serialize_ShouldSortControlPropertiesAlphabetically()
{
var graph = new Screen()
{
Name = "Screen1",
Properties = new Dictionary<string, ControlPropertyValue>()
{
{ "PropertyB", new() { Value = "B" } },
{ "PropertyC", new() { Value = "C" } },
{ "PropertyA", new() { Value = "A" } },
},
};

var serializer = YamlSerializationFactory.CreateSerializer();

var sut = serializer.Serialize(graph);
sut.Should().Be($"Screen: {Environment.NewLine}Name: Screen1{Environment.NewLine}Properties:{Environment.NewLine} PropertyA: A{Environment.NewLine} PropertyB: B{Environment.NewLine} PropertyC: C{Environment.NewLine}");
}

[TestMethod]
public void Serialize_ShouldCreateValidYamlWithChildNodes()
{
Expand All @@ -39,7 +59,7 @@ public void Serialize_ShouldCreateValidYamlWithChildNodes()
},
Controls = new Control[]
{
new Label()
new Text()
{
Name = "Label1",
Properties = new Dictionary<string, ControlPropertyValue>()
Expand All @@ -63,7 +83,7 @@ public void Serialize_ShouldCreateValidYamlWithChildNodes()
var serializer = YamlSerializationFactory.CreateSerializer();

var sut = serializer.Serialize(graph);
sut.Should().Be($"Screen: {Environment.NewLine}Name: Screen1{Environment.NewLine}Properties:{Environment.NewLine} Text: I am a screen{Environment.NewLine}Controls:{Environment.NewLine}- Label: {Environment.NewLine} Name: Label1{Environment.NewLine} Properties:{Environment.NewLine} Text: lorem ipsum{Environment.NewLine}- Button: {Environment.NewLine} Name: Button1{Environment.NewLine} Properties:{Environment.NewLine} Text: click me{Environment.NewLine} X: 100{Environment.NewLine} Y: 200{Environment.NewLine}");
sut.Should().Be($"Screen: {Environment.NewLine}Name: Screen1{Environment.NewLine}Properties:{Environment.NewLine} Text: I am a screen{Environment.NewLine}Controls:{Environment.NewLine}- Text: {Environment.NewLine} Name: Label1{Environment.NewLine} Properties:{Environment.NewLine} Text: lorem ipsum{Environment.NewLine}- Button: {Environment.NewLine} Name: Button1{Environment.NewLine} Properties:{Environment.NewLine} Text: click me{Environment.NewLine} X: 100{Environment.NewLine} Y: 200{Environment.NewLine}");
}

[TestMethod]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Microsoft.PowerPlatform.PowerApps.Persistence.Models;

public static class BuiltInTemplatesUris
{
public const string Screen = "http://microsoft.com/appmagic/screen#screen";
public const string Button = "http://microsoft.com/appmagic/button#button";
public const string Label = "http://microsoft.com/appmagic/label#label";
public const string Screen = "http://microsoft.com/appmagic/screen";
public const string Button = "http://microsoft.com/appmagic/powercontrol/PowerApps_CoreControls_ButtonCanvas";
public const string Text = "http://microsoft.com/appmagic/powercontrol/PowerApps_CoreControls_TextCanvas";
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

namespace Microsoft.PowerPlatform.PowerApps.Persistence.Models;

[FirstClass(nameof(Label))]
public record Label : Control
[FirstClass(nameof(Text))]
public record Text : Control
{
public Label()
public Text()
{
ControlUri = BuiltInTemplatesUris.Label;
ControlUri = BuiltInTemplatesUris.Text;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,15 @@ public void WriteYaml(IEmitter emitter, object? value, Type type)

emitter.Emit(new MappingStart());

foreach (var kv in collection)
var sortedKeys = collection.Keys.OrderBy(x => x, StringComparer.Ordinal);

foreach (var key in sortedKeys)
{
emitter.Emit(new Scalar(kv.Key));
emitter.Emit(new Scalar(key));

#pragma warning disable CS8604 // Possible null reference argument, but valid in YAML.
emitter.Emit(new Scalar(kv.Value.Value));
var property = collection[key];
emitter.Emit(new Scalar(property.Value));
#pragma warning restore CS8604 // Possible null reference argument.
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ namespace Microsoft.PowerPlatform.PowerApps.Persistence.Yaml;

internal static class SerializerBuilderExtensions
{
private const string ControlPropertyName = "Control";

public static SerializerBuilder WithFirstClassModels(this SerializerBuilder builder)
{
builder = AddAttributeOverrides(builder)
Expand Down Expand Up @@ -38,10 +40,10 @@ public static DeserializerBuilder WithFirstClassModels(this DeserializerBuilder
{ nameof(Button), typeof(Button) },
{ BuiltInTemplatesUris.Button, typeof(Button) },

{ nameof(Label), typeof(Label) },
{ BuiltInTemplatesUris.Label, typeof(Label) },
{ nameof(Text), typeof(Text) },
{ BuiltInTemplatesUris.Text, typeof(Text) },
};
options.AddKeyValueTypeDiscriminator<Control>(nameof(Control.ControlUri), map);
options.AddKeyValueTypeDiscriminator<Control>(ControlPropertyName, map);
options.AddUniqueKeyTypeDiscriminator<Control>(map);
})
.WithTypeConverter(new ControlPropertiesCollectionConverter());
Expand All @@ -61,7 +63,7 @@ private static TBuilder AddAttributeOverrides<TBuilder>(TBuilder builder)
else
newAttrib = new YamlMemberAttribute(typeof(string))
{
Alias = "Control",
Alias = ControlPropertyName,
Order = 0,
};

Expand Down

0 comments on commit 28fcab4

Please sign in to comment.