Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ namespace AdaptiveCardsSharedModelUnitTest
ENUM_TEST_WITH_REVERSE_MAP(ImageStyle, ImageStyle::Person, "person"s, );
ENUM_TEST(SeparatorThickness, SeparatorThickness::Thick, "thick"s);
ENUM_TEST(Spacing, Spacing::None, "none"s);
ENUM_TEST(TextInputStyle, TextInputStyle::Tel, "Tel"s);
ENUM_TEST(TextInputStyle, TextInputStyle::Password, "Password"s);
ENUM_TEST_WITH_REVERSE_MAP(TextSize, TextSize::Large, "Large"s, {{"Normal", TextSize::Default}});
ENUM_TEST_WITH_REVERSE_MAP(TextWeight, TextWeight::Bolder, "Bolder"s, {{"Normal", TextWeight::Default}});
ENUM_TEST(VerticalContentAlignment, VerticalContentAlignment::Center, "Center"s);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ namespace AdaptiveCardsSharedModelUnitTest

Assert::IsTrue(parseResult->GetWarnings().size() == 0);
Assert::IsTrue(body.size() == 1);
Assert::IsTrue(body.at(0)->GetElementType() == CardElementType::ChoiceSetInput);
Assert::IsTrue(body.at(0)->GetElementType() == CardElementType::ChoiceSetInput);
auto choiceSetElement = std::dynamic_pointer_cast<ChoiceSetInput>(body.at(0));
Assert::IsTrue(choiceSetElement->GetChoices().size() == 0);

Expand Down Expand Up @@ -660,8 +660,84 @@ namespace AdaptiveCardsSharedModelUnitTest
auto i = 0;
for (const auto& elem : body) {
std::shared_ptr<TextBlock> textBlock = std::dynamic_pointer_cast<TextBlock>(elem);
Assert::IsTrue(textBlock->GetStyle() == expectedStyles[i++]);
Assert::IsTrue(textBlock->GetStyle() == expectedStyles[i++]);
}
}

TEST_METHOD(PasswordStyleParseTest)
{
const std::string testjson{ R"(
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.5",
"body": [
{
"type": "Input.Text",
"id": "plain",
"label" : "Plaintext"
},
{
"type": "Input.Text",
"id": "password",
"style": "passWORD",
"label" : "Password"
}
]
}
)"};

auto parseResult = AdaptiveCard::DeserializeFromString(testjson, "1.5");
auto card = parseResult->GetAdaptiveCard();
auto body = card->GetBody();
Assert::AreEqual(body.size(), 2ui64);

auto plainInput = std::dynamic_pointer_cast<TextInput>(body.at(0));
Assert::IsTrue(TextInputStyle::Text == plainInput->GetTextInputStyle());

auto passwordInput = std::dynamic_pointer_cast<TextInput>(body.at(1));
Assert::IsTrue(TextInputStyle::Password == passwordInput->GetTextInputStyle());
}

TEST_METHOD(PasswordWithMultilineParseTest)
{
const std::string testjson{ R"(
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.5",
"body": [
{
"type": "Input.Text",
"id": "theId",
"label" : "Password",
"style": "password",
"isMultiline": true
}
]
}
)"};

const auto parseResult = AdaptiveCard::DeserializeFromString(testjson, "1.5");

// verify we emitted a warning and it's correct
const auto warnings = parseResult->GetWarnings();
Assert::IsTrue(warnings.size() == 1ui64);
const auto warning = warnings.at(0);
Assert::IsTrue(WarningStatusCode::InvalidValue == warning->GetStatusCode());
Assert::AreEqual("Input.Text ignores isMultiline when using password style"s, warning->GetReason());

// verify the generated element doesn't report itself as supporting multiline
const auto card = parseResult->GetAdaptiveCard();
const auto body = card->GetBody();
Assert::AreEqual(body.size(), 1ui64);
const auto theInput = std::dynamic_pointer_cast<TextInput>(body.at(0));
Assert::IsTrue(TextInputStyle::Password == theInput->GetTextInputStyle());
Assert::IsFalse(theInput->GetIsMultiline());

// verify that we still serialize isMultiline == true
const auto serializedCard = card->SerializeToJsonValue();
Assert::IsTrue(serializedCard["body"][0]["isMultiline"].asBool());
}
};
}
3 changes: 2 additions & 1 deletion source/shared/cpp/ObjectModel/Enums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,8 @@ namespace AdaptiveCards
{TextInputStyle::Email, "Email"},
{TextInputStyle::Tel, "Tel"},
{TextInputStyle::Text, "Text"},
{TextInputStyle::Url, "Url"}});
{TextInputStyle::Url, "Url"},
{TextInputStyle::Password, "Password"}});

DEFINE_ADAPTIVECARD_ENUM(ContainerStyle, {
{ContainerStyle::Default, "Default"},
Expand Down
1 change: 1 addition & 0 deletions source/shared/cpp/ObjectModel/Enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ namespace AdaptiveCards
Tel,
Url,
Email,
Password,
};
DECLARE_ADAPTIVECARD_ENUM(TextInputStyle);

Expand Down
23 changes: 19 additions & 4 deletions source/shared/cpp/ObjectModel/TextInput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ void TextInput::SetValue(const std::string& value)

bool TextInput::GetIsMultiline() const
{
return m_isMultiline;
// isMultiline is ignored if the TextInputStyle is password
return m_isMultiline && m_style != TextInputStyle::Password;
}

void TextInput::SetIsMultiline(const bool value)
Expand Down Expand Up @@ -133,10 +134,24 @@ std::shared_ptr<BaseCardElement> TextInputParser::Deserialize(ParseContext& cont
std::shared_ptr<TextInput> textInput = BaseInputElement::Deserialize<TextInput>(context, json);
textInput->SetPlaceholder(ParseUtil::GetString(json, AdaptiveCardSchemaKey::Placeholder));
textInput->SetValue(ParseUtil::GetString(json, AdaptiveCardSchemaKey::Value));
textInput->SetIsMultiline(ParseUtil::GetBool(json, AdaptiveCardSchemaKey::IsMultiline, false));
textInput->SetMaxLength(ParseUtil::GetUInt(json, AdaptiveCardSchemaKey::MaxLength, 0));
textInput->SetTextInputStyle(
ParseUtil::GetEnumValue<TextInputStyle>(json, AdaptiveCardSchemaKey::Style, TextInputStyle::Text, TextInputStyleFromString));

const auto isMultiline = ParseUtil::GetBool(json, AdaptiveCardSchemaKey::IsMultiline, false);
textInput->SetIsMultiline(isMultiline);

const auto textInputStyle =
ParseUtil::GetEnumValue<TextInputStyle>(json, AdaptiveCardSchemaKey::Style, TextInputStyle::Text, TextInputStyleFromString);
textInput->SetTextInputStyle(textInputStyle);

// emit warning in the case where style is `password` but multiline is specified (this is an invalid combination...
// we will ignore multiline, though we'll allow it to serialize (see TextInput::GetIsMultiline()).
if (isMultiline && textInputStyle == TextInputStyle::Password)
{
context.warnings.emplace_back(
std::make_shared<AdaptiveCardParseWarning>(WarningStatusCode::InvalidValue,
"Input.Text ignores isMultiline when using password style"));
}

textInput->SetInlineAction(ParseUtil::GetAction(context, json, AdaptiveCardSchemaKey::InlineAction, false));
textInput->SetRegex(ParseUtil::GetString(json, AdaptiveCardSchemaKey::Regex));

Expand Down