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
1 change: 1 addition & 0 deletions source/dotnet/Library/AdaptiveCards/AdaptiveImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public AdaptiveImage(Uri url)
#if !NETSTANDARD1_3
[XmlIgnore]
#endif
[JsonProperty(Required = Required.Default)]
public override string Type { get; set; } = TypeName;

/// <summary>
Expand Down
126 changes: 90 additions & 36 deletions source/dotnet/Test/AdaptiveCards.Test/AdaptiveCardApiTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -228,39 +228,39 @@ public void TestResourceInformation()
public void TestDefaultValueHandling()
{
var json = @"{
""$schema"": ""http://adaptivecards.io/schemas/adaptive-card.json"",
""type"": ""AdaptiveCard"",
""version"": ""1.0"",
""body"": [
{
""type"": ""Container"",
""style"": ""asdf"",
""spacing"": ""asdf"",
""items"": [
{
""type"": ""TextBlock"",
""text"": ""Sample text"",
""color"": ""asdf"",
""size"": ""asdf"",
""weight"": ""asdf""
},
{
""type"": ""Image"",
""url"": ""http://adaptivecards.io/content/cats/1.png"",
""style"": ""asdf"",
""size"": ""asdf""
}
]
}
]
""$schema"": ""http://adaptivecards.io/schemas/adaptive-card.json"",
""type"": ""AdaptiveCard"",
""version"": ""1.0"",
""body"": [
{
""type"": ""Container"",
""style"": ""asdf"",
""spacing"": ""asdf"",
""items"": [
{
""type"": ""TextBlock"",
""text"": ""Sample text"",
""color"": ""asdf"",
""size"": ""asdf"",
""weight"": ""asdf""
},
{
""type"": ""Image"",
""url"": ""http://adaptivecards.io/content/cats/1.png"",
""style"": ""asdf"",
""size"": ""asdf""
}
]
}
]
}";

var card = AdaptiveCard.FromJson(json).Card;

// Contents of card for easier access
AdaptiveContainer container = (AdaptiveContainer) card.Body[0];
AdaptiveTextBlock textblock = (AdaptiveTextBlock) container.Items[0];
AdaptiveImage image = (AdaptiveImage) container.Items[1];
AdaptiveContainer container = (AdaptiveContainer)card.Body[0];
AdaptiveTextBlock textblock = (AdaptiveTextBlock)container.Items[0];
AdaptiveImage image = (AdaptiveImage)container.Items[1];

// Container property tests
Assert.IsNull(container.Style);
Expand Down Expand Up @@ -299,7 +299,7 @@ public void TestExplicitImagePositiveTest()
Assert.AreEqual(card.Body.Count, 1);
var imageBlock = card.Body[0] as AdaptiveImage;
Assert.AreEqual(0, result.Warnings.Count);
Assert.AreEqual(20U,imageBlock.PixelWidth);
Assert.AreEqual(20U, imageBlock.PixelWidth);
Assert.AreEqual(50U, imageBlock.PixelHeight);
}

Expand Down Expand Up @@ -518,7 +518,7 @@ public void DefaultHeightIsAuto()
Assert.AreEqual(columnSet.Height, AdaptiveHeight.Auto);
Assert.AreEqual(columnSet.Columns.Count, 2);

foreach(var column in columnSet.Columns)
foreach (var column in columnSet.Columns)
{
Assert.AreEqual(column.Items.Count, 1);
var columnContent = column.Items[0];
Expand Down Expand Up @@ -934,11 +934,11 @@ public void TestObjectModelActionSetElement()

actionSet.Actions.Add(showCardAction);

AdaptiveToggleVisibilityAction toggleVisibilityAction = new AdaptiveToggleVisibilityAction
{
Title = "Toggle",
TargetElements = new List<AdaptiveTargetElement> { "test" }
};
AdaptiveToggleVisibilityAction toggleVisibilityAction = new AdaptiveToggleVisibilityAction
{
Title = "Toggle",
TargetElements = new List<AdaptiveTargetElement> { "test" }
};
actionSet.Actions.Add(toggleVisibilityAction);

// This lines are not indented so the comparisson doesn't fail due to extra spaces
Expand Down Expand Up @@ -1142,6 +1142,60 @@ public void TestObjectModelMinHeight()
}";
var outputJson = card.ToJson();
Assert.AreEqual(outputJson, expectedJson);
}
}

[TestMethod]
public void TestImplicitImageType()
{
// Images set to type "Image" or with type unset should parse correctly within an image set
var imageTypeSetOrEmpty =
@"{
""type"": ""AdaptiveCard"",
""version"": ""1.2"",
""body"": [
{
""type"": ""ImageSet"",
""images"": [
{
""type"": ""Image"",
""url"": ""http://adaptivecards.io/content/cats/1.png""
},
{
""url"": ""http://adaptivecards.io/content/cats/1.png""
}
]
}
]
}";

// Images set to a bogus type should not parse correctly
var imageTypeInvalid =
@"{
""type"": ""AdaptiveCard"",
""version"": ""1.2"",
""body"": [
{
""type"": ""ImageSet"",
""images"": [
{
""type"": ""Elephant"",
""url"": ""http://adaptivecards.io/content/cats/1.png""
}
]
}
]
}";

var result = AdaptiveCard.FromJson(imageTypeSetOrEmpty);
Assert.IsNotNull(result.Card);
Assert.AreEqual(2, (result.Card.Body[0] as AdaptiveImageSet).Images.Count);

var ex = Assert.ThrowsException<ArgumentException>(() =>
{
AdaptiveCard.FromJson(imageTypeInvalid);
});

StringAssert.Contains(ex.Message, "The value \"AdaptiveCards.AdaptiveUnknownElement\" is not of type \"AdaptiveCards.AdaptiveImage\" and cannot be used in this generic collection.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1201,5 +1201,62 @@ namespace AdaptiveCardsSharedModelUnitTest
Assert::AreEqual("Unable to parse element of type Elephant", e.GetReason().c_str(), L"GetReason incorrect");
}
}

TEST_METHOD(ImplicitImageTypeInImageSetTest)
{
// Images set to type "Image" or with type unset should parse correctly within an image set
std::string imageTypeSetOrEmpty =
"{\
\"$schema\":\"http://adaptivecards.io/schemas/adaptive-card.json\",\
\"type\": \"AdaptiveCard\",\
\"version\": \"1.0\",\
\"body\": [\
{\
\"type\":\"ImageSet\",\
\"images\": [\
{\
\"type\": \"Image\",\
\"url\": \"http://adaptivecards.io/content/cats/1.png\"\
},\
{\
\"url\": \"http://adaptivecards.io/content/cats/1.png\"\
}\
]\
}\
]\
}";

// Images set to a bogus type should not parse correctly
std::string imageTypeInvalid =
"{\
\"$schema\":\"http://adaptivecards.io/schemas/adaptive-card.json\",\
\"type\": \"AdaptiveCard\",\
\"version\": \"1.0\",\
\"body\": [\
{\
\"type\":\"ImageSet\",\
\"images\": [\
{\
\"type\": \"Elephant\",\
\"url\": \"http://adaptivecards.io/content/cats/1.png\"\
}\
]\
}\
]\
}";

std::shared_ptr<ParseResult> parseResult = AdaptiveCard::DeserializeFromString(imageTypeSetOrEmpty, "1.0");

try
{
parseResult = AdaptiveCard::DeserializeFromString(imageTypeInvalid, "1.0");
Assert::IsTrue(false, L"Deserializing should throw an exception");
}
catch (const AdaptiveCardParseException& e)
{
Assert::IsTrue(ErrorStatusCode::InvalidPropertyValue == e.GetStatusCode(), L"ErrorStatusCode incorrect");
Assert::AreEqual("Unable to parse element of type Elephant", e.GetReason().c_str(), L"GetReason incorrect");
}
}
};
}
2 changes: 1 addition & 1 deletion source/shared/cpp/ObjectModel/ColumnSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void ColumnSet::DeserializeChildren(ParseContext& context, const Json::Value& va
value,
AdaptiveCardSchemaKey::Columns,
false, // isRequired
"Column"); // impliedType
CardElementTypeToString(CardElementType::Column)); // impliedType
}

void ColumnSet::PopulateKnownPropertiesSet()
Expand Down
3 changes: 2 additions & 1 deletion source/shared/cpp/ObjectModel/ImageSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ std::shared_ptr<BaseCardElement> ImageSetParser::Deserialize(ParseContext& conte
ParseUtil::GetEnumValue<ImageSize>(value, AdaptiveCardSchemaKey::ImageSize, ImageSize::None, ImageSizeFromString);

// Parse Images
auto images = ParseUtil::GetElementCollection<Image>(true, context, value, AdaptiveCardSchemaKey::Images, true);
auto images = ParseUtil::GetElementCollection<Image>(
true, context, value, AdaptiveCardSchemaKey::Images, true, CardElementTypeToString(CardElementType::Image));

for (auto image : images)
{
Expand Down