mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Update node fields fix (#16428)
* Modifies accessibility bridge to populate new node fields in semantics API. * Adds additional UTs and fixes logic for breaking up updates for nodes with large values. * Chaged tests to set node flags using bitwise-or instead of addition. * Address bug in update size arithmetic. * Fixes issue in TruncatesLargeValue unit test causing unexpected deletes. * Fixes expected number of updates in BatchesLargeMessages unit test to reflect expected values now that node states are populated.
This commit is contained in:
parent
9d713968f7
commit
537eb77379
@ -80,11 +80,38 @@ AccessibilityBridge::GetNodeAttributes(const flutter::SemanticsNode& node,
|
||||
}
|
||||
|
||||
fuchsia::accessibility::semantics::States AccessibilityBridge::GetNodeStates(
|
||||
const flutter::SemanticsNode& node) const {
|
||||
const flutter::SemanticsNode& node,
|
||||
size_t* additional_size) const {
|
||||
fuchsia::accessibility::semantics::States states;
|
||||
if (node.HasFlag(flutter::SemanticsFlags::kHasCheckedState)) {
|
||||
states.set_checked(node.HasFlag(flutter::SemanticsFlags::kIsChecked));
|
||||
(*additional_size) += sizeof(fuchsia::accessibility::semantics::States);
|
||||
|
||||
// Set checked state.
|
||||
if (!node.HasFlag(flutter::SemanticsFlags::kHasCheckedState)) {
|
||||
states.set_checked_state(
|
||||
fuchsia::accessibility::semantics::CheckedState::NONE);
|
||||
} else {
|
||||
states.set_checked_state(
|
||||
node.HasFlag(flutter::SemanticsFlags::kIsChecked)
|
||||
? fuchsia::accessibility::semantics::CheckedState::CHECKED
|
||||
: fuchsia::accessibility::semantics::CheckedState::UNCHECKED);
|
||||
}
|
||||
|
||||
// Set selected state.
|
||||
states.set_selected(node.HasFlag(flutter::SemanticsFlags::kIsSelected));
|
||||
|
||||
// Set hidden state.
|
||||
states.set_hidden(node.HasFlag(flutter::SemanticsFlags::kIsHidden));
|
||||
|
||||
// Set value.
|
||||
if (node.value.size() > fuchsia::accessibility::semantics::MAX_VALUE_SIZE) {
|
||||
states.set_value(node.value.substr(
|
||||
0, fuchsia::accessibility::semantics::MAX_VALUE_SIZE));
|
||||
(*additional_size) += fuchsia::accessibility::semantics::MAX_VALUE_SIZE;
|
||||
} else {
|
||||
states.set_value(node.value);
|
||||
(*additional_size) += node.value.size();
|
||||
}
|
||||
|
||||
return states;
|
||||
}
|
||||
|
||||
@ -199,7 +226,7 @@ void AccessibilityBridge::AddSemanticsNodeUpdate(
|
||||
.set_location(GetNodeLocation(flutter_node))
|
||||
.set_transform(GetNodeTransform(flutter_node))
|
||||
.set_attributes(GetNodeAttributes(flutter_node, &this_node_size))
|
||||
.set_states(GetNodeStates(flutter_node))
|
||||
.set_states(GetNodeStates(flutter_node, &this_node_size))
|
||||
.set_child_ids(child_ids);
|
||||
this_node_size +=
|
||||
kNodeIdSize * flutter_node.childrenInTraversalOrder.size();
|
||||
|
||||
@ -142,7 +142,8 @@ class AccessibilityBridge
|
||||
// Derives the states for a Fuchsia semantics node from a Flutter semantics
|
||||
// node.
|
||||
fuchsia::accessibility::semantics::States GetNodeStates(
|
||||
const flutter::SemanticsNode& node) const;
|
||||
const flutter::SemanticsNode& node,
|
||||
size_t* additional_size) const;
|
||||
|
||||
// Gets the set of reachable descendants from the given node id.
|
||||
std::unordered_set<int32_t> GetDescendants(int32_t node_id) const;
|
||||
|
||||
@ -137,6 +137,106 @@ TEST_F(AccessibilityBridgeTest, DeletesChildrenTransitively) {
|
||||
EXPECT_FALSE(semantics_manager_.UpdateOverflowed());
|
||||
}
|
||||
|
||||
TEST_F(AccessibilityBridgeTest, PopulatesCheckedState) {
|
||||
flutter::SemanticsNode node0;
|
||||
node0.id = 0;
|
||||
// HasCheckedState = true
|
||||
// IsChecked = true
|
||||
// IsSelected = false
|
||||
// IsHidden = false
|
||||
node0.flags |= static_cast<int>(flutter::SemanticsFlags::kHasCheckedState);
|
||||
node0.flags |= static_cast<int>(flutter::SemanticsFlags::kIsChecked);
|
||||
node0.value = "value";
|
||||
|
||||
accessibility_bridge_->AddSemanticsNodeUpdate({{0, node0}});
|
||||
RunLoopUntilIdle();
|
||||
|
||||
EXPECT_EQ(0, semantics_manager_.DeleteCount());
|
||||
EXPECT_EQ(1, semantics_manager_.UpdateCount());
|
||||
EXPECT_EQ(1, semantics_manager_.CommitCount());
|
||||
EXPECT_EQ(1U, semantics_manager_.LastUpdatedNodes().size());
|
||||
const auto& fuchsia_node = semantics_manager_.LastUpdatedNodes().at(0u);
|
||||
EXPECT_EQ(fuchsia_node.node_id(), static_cast<unsigned int>(node0.id));
|
||||
EXPECT_TRUE(fuchsia_node.has_states());
|
||||
const auto& states = fuchsia_node.states();
|
||||
EXPECT_TRUE(states.has_checked_state());
|
||||
EXPECT_EQ(states.checked_state(),
|
||||
fuchsia::accessibility::semantics::CheckedState::CHECKED);
|
||||
EXPECT_TRUE(states.has_selected());
|
||||
EXPECT_FALSE(states.selected());
|
||||
EXPECT_TRUE(states.has_hidden());
|
||||
EXPECT_FALSE(states.hidden());
|
||||
EXPECT_TRUE(states.has_value());
|
||||
EXPECT_EQ(states.value(), node0.value);
|
||||
|
||||
EXPECT_FALSE(semantics_manager_.DeleteOverflowed());
|
||||
EXPECT_FALSE(semantics_manager_.UpdateOverflowed());
|
||||
}
|
||||
|
||||
TEST_F(AccessibilityBridgeTest, PopulatesSelectedState) {
|
||||
flutter::SemanticsNode node0;
|
||||
node0.id = 0;
|
||||
// HasCheckedState = false
|
||||
// IsChecked = false
|
||||
// IsSelected = true
|
||||
// IsHidden = false
|
||||
node0.flags = static_cast<int>(flutter::SemanticsFlags::kIsSelected);
|
||||
|
||||
accessibility_bridge_->AddSemanticsNodeUpdate({{0, node0}});
|
||||
RunLoopUntilIdle();
|
||||
|
||||
EXPECT_EQ(0, semantics_manager_.DeleteCount());
|
||||
EXPECT_EQ(1, semantics_manager_.UpdateCount());
|
||||
EXPECT_EQ(1, semantics_manager_.CommitCount());
|
||||
EXPECT_EQ(1U, semantics_manager_.LastUpdatedNodes().size());
|
||||
const auto& fuchsia_node = semantics_manager_.LastUpdatedNodes().at(0u);
|
||||
EXPECT_EQ(fuchsia_node.node_id(), static_cast<unsigned int>(node0.id));
|
||||
EXPECT_TRUE(fuchsia_node.has_states());
|
||||
const auto& states = fuchsia_node.states();
|
||||
EXPECT_TRUE(states.has_checked_state());
|
||||
EXPECT_EQ(states.checked_state(),
|
||||
fuchsia::accessibility::semantics::CheckedState::NONE);
|
||||
EXPECT_TRUE(states.has_selected());
|
||||
EXPECT_TRUE(states.selected());
|
||||
EXPECT_TRUE(states.has_hidden());
|
||||
EXPECT_FALSE(states.hidden());
|
||||
|
||||
EXPECT_FALSE(semantics_manager_.DeleteOverflowed());
|
||||
EXPECT_FALSE(semantics_manager_.UpdateOverflowed());
|
||||
}
|
||||
|
||||
TEST_F(AccessibilityBridgeTest, PopulatesHiddenState) {
|
||||
flutter::SemanticsNode node0;
|
||||
node0.id = 0;
|
||||
// HasCheckedState = false
|
||||
// IsChecked = false
|
||||
// IsSelected = false
|
||||
// IsHidden = true
|
||||
node0.flags = static_cast<int>(flutter::SemanticsFlags::kIsHidden);
|
||||
|
||||
accessibility_bridge_->AddSemanticsNodeUpdate({{0, node0}});
|
||||
RunLoopUntilIdle();
|
||||
|
||||
EXPECT_EQ(0, semantics_manager_.DeleteCount());
|
||||
EXPECT_EQ(1, semantics_manager_.UpdateCount());
|
||||
EXPECT_EQ(1, semantics_manager_.CommitCount());
|
||||
EXPECT_EQ(1u, semantics_manager_.LastUpdatedNodes().size());
|
||||
const auto& fuchsia_node = semantics_manager_.LastUpdatedNodes().at(0u);
|
||||
EXPECT_EQ(fuchsia_node.node_id(), static_cast<unsigned int>(node0.id));
|
||||
EXPECT_TRUE(fuchsia_node.has_states());
|
||||
const auto& states = fuchsia_node.states();
|
||||
EXPECT_TRUE(states.has_checked_state());
|
||||
EXPECT_EQ(states.checked_state(),
|
||||
fuchsia::accessibility::semantics::CheckedState::NONE);
|
||||
EXPECT_TRUE(states.has_selected());
|
||||
EXPECT_FALSE(states.selected());
|
||||
EXPECT_TRUE(states.has_hidden());
|
||||
EXPECT_TRUE(states.hidden());
|
||||
|
||||
EXPECT_FALSE(semantics_manager_.DeleteOverflowed());
|
||||
EXPECT_FALSE(semantics_manager_.UpdateOverflowed());
|
||||
}
|
||||
|
||||
TEST_F(AccessibilityBridgeTest, TruncatesLargeLabel) {
|
||||
// Test that labels which are too long are truncated.
|
||||
flutter::SemanticsNode node0;
|
||||
@ -181,6 +281,49 @@ TEST_F(AccessibilityBridgeTest, TruncatesLargeLabel) {
|
||||
EXPECT_FALSE(semantics_manager_.UpdateOverflowed());
|
||||
}
|
||||
|
||||
TEST_F(AccessibilityBridgeTest, TruncatesLargeValue) {
|
||||
// Test that values which are too long are truncated.
|
||||
flutter::SemanticsNode node0;
|
||||
node0.id = 0;
|
||||
|
||||
flutter::SemanticsNode node1;
|
||||
node1.id = 1;
|
||||
|
||||
flutter::SemanticsNode bad_node;
|
||||
bad_node.id = 2;
|
||||
bad_node.value =
|
||||
std::string(fuchsia::accessibility::semantics::MAX_VALUE_SIZE + 1, '2');
|
||||
|
||||
node0.childrenInTraversalOrder = {1, 2};
|
||||
node0.childrenInHitTestOrder = {1, 2};
|
||||
|
||||
accessibility_bridge_->AddSemanticsNodeUpdate({
|
||||
{0, node0},
|
||||
{1, node1},
|
||||
{2, bad_node},
|
||||
});
|
||||
RunLoopUntilIdle();
|
||||
|
||||
EXPECT_EQ(0, semantics_manager_.DeleteCount());
|
||||
EXPECT_EQ(1, semantics_manager_.UpdateCount());
|
||||
EXPECT_EQ(1, semantics_manager_.CommitCount());
|
||||
EXPECT_EQ(3U, semantics_manager_.LastUpdatedNodes().size());
|
||||
auto trimmed_node =
|
||||
std::find_if(semantics_manager_.LastUpdatedNodes().begin(),
|
||||
semantics_manager_.LastUpdatedNodes().end(),
|
||||
[id = static_cast<uint32_t>(bad_node.id)](
|
||||
fuchsia::accessibility::semantics::Node const& node) {
|
||||
return node.node_id() == id;
|
||||
});
|
||||
ASSERT_NE(trimmed_node, semantics_manager_.LastUpdatedNodes().end());
|
||||
ASSERT_TRUE(trimmed_node->has_states());
|
||||
EXPECT_EQ(
|
||||
trimmed_node->states().value(),
|
||||
std::string(fuchsia::accessibility::semantics::MAX_VALUE_SIZE, '2'));
|
||||
EXPECT_FALSE(semantics_manager_.DeleteOverflowed());
|
||||
EXPECT_FALSE(semantics_manager_.UpdateOverflowed());
|
||||
}
|
||||
|
||||
TEST_F(AccessibilityBridgeTest, SplitsLargeUpdates) {
|
||||
// Test that labels which are too long are truncated.
|
||||
flutter::SemanticsNode node0;
|
||||
@ -201,8 +344,8 @@ TEST_F(AccessibilityBridgeTest, SplitsLargeUpdates) {
|
||||
|
||||
flutter::SemanticsNode node4;
|
||||
node4.id = 4;
|
||||
node4.label =
|
||||
std::string(fuchsia::accessibility::semantics::MAX_LABEL_SIZE, '4');
|
||||
node4.value =
|
||||
std::string(fuchsia::accessibility::semantics::MAX_VALUE_SIZE, '4');
|
||||
|
||||
node0.childrenInTraversalOrder = {1, 2};
|
||||
node0.childrenInHitTestOrder = {1, 2};
|
||||
@ -294,7 +437,7 @@ TEST_F(AccessibilityBridgeTest, BatchesLargeMessages) {
|
||||
RunLoopUntilIdle();
|
||||
|
||||
EXPECT_EQ(0, semantics_manager_.DeleteCount());
|
||||
EXPECT_EQ(4, semantics_manager_.UpdateCount());
|
||||
EXPECT_EQ(5, semantics_manager_.UpdateCount());
|
||||
EXPECT_EQ(1, semantics_manager_.CommitCount());
|
||||
EXPECT_FALSE(semantics_manager_.DeleteOverflowed());
|
||||
EXPECT_FALSE(semantics_manager_.UpdateOverflowed());
|
||||
@ -308,7 +451,7 @@ TEST_F(AccessibilityBridgeTest, BatchesLargeMessages) {
|
||||
RunLoopUntilIdle();
|
||||
|
||||
EXPECT_EQ(1, semantics_manager_.DeleteCount());
|
||||
EXPECT_EQ(5, semantics_manager_.UpdateCount());
|
||||
EXPECT_EQ(6, semantics_manager_.UpdateCount());
|
||||
EXPECT_EQ(2, semantics_manager_.CommitCount());
|
||||
EXPECT_FALSE(semantics_manager_.DeleteOverflowed());
|
||||
EXPECT_FALSE(semantics_manager_.UpdateOverflowed());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user