Skip to content

Commit b7c0e49

Browse files
generatedunixname1563563004708334meta-codesync[bot]
authored andcommitted
xplat/js/react-native-github/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphEventEmitter.cpp (#58633)
Summary: Pull Request resolved: #58633 Reviewed By: javache Differential Revision: D121155236 fbshipit-source-id: d38c8495e6e2aa0d35a23f4b830a94a9fd4a5561
1 parent baee2f3 commit b7c0e49

1 file changed

Lines changed: 180 additions & 0 deletions

File tree

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include <react/renderer/components/text/ParagraphEventEmitter.h>
9+
10+
#include <gtest/gtest.h>
11+
#include <hermes/hermes.h>
12+
#include <react/renderer/core/EventBeat.h>
13+
#include <react/renderer/core/EventDispatcher.h>
14+
#include <react/renderer/core/EventListener.h>
15+
#include <react/renderer/runtimescheduler/RuntimeScheduler.h>
16+
17+
namespace facebook::react {
18+
19+
namespace {
20+
21+
struct CapturedEvent {
22+
std::string type;
23+
SharedEventPayload payload;
24+
};
25+
26+
class ParagraphEventEmitterTest : public ::testing::Test {
27+
protected:
28+
void SetUp() override {
29+
runtime_ = facebook::hermes::makeHermesRuntime(
30+
::hermes::vm::RuntimeConfig::Builder().build());
31+
32+
RuntimeExecutor runtimeExecutor =
33+
[this](std::function<void(jsi::Runtime&)>&& callback) {
34+
callback(*runtime_);
35+
};
36+
runtimeScheduler_ = std::make_unique<RuntimeScheduler>(runtimeExecutor);
37+
38+
auto eventBeat = std::make_unique<EventBeat>(
39+
std::make_shared<EventBeat::OwnerBox>(), *runtimeScheduler_);
40+
auto eventQueueProcessor = EventQueueProcessor(
41+
[](jsi::Runtime&,
42+
EventTarget*,
43+
const std::string&,
44+
ReactEventPriority,
45+
const EventPayload&,
46+
HighResTimeStamp) {},
47+
[](jsi::Runtime&) {},
48+
[](const StateUpdate&) {},
49+
{});
50+
eventDispatcher_ = std::make_shared<EventDispatcher>(
51+
eventQueueProcessor,
52+
std::move(eventBeat),
53+
[](const StateUpdate&) {},
54+
std::weak_ptr<EventLogger>{});
55+
56+
listener_ = std::make_shared<EventListener>(
57+
[this](const RawEvent& event) {
58+
events_.push_back({event.type, event.eventPayload});
59+
return true;
60+
});
61+
eventDispatcher_->addListener(listener_);
62+
}
63+
64+
void expectLine(
65+
const jsi::Array& lines,
66+
size_t index,
67+
const LineMeasurement& expected) {
68+
auto line = lines.getValueAtIndex(*runtime_, index).asObject(*runtime_);
69+
EXPECT_EQ(
70+
line.getProperty(*runtime_, "text")
71+
.asString(*runtime_)
72+
.utf8(*runtime_),
73+
expected.text);
74+
EXPECT_EQ(
75+
line.getProperty(*runtime_, "x").asNumber(), expected.frame.origin.x);
76+
EXPECT_EQ(
77+
line.getProperty(*runtime_, "y").asNumber(), expected.frame.origin.y);
78+
EXPECT_EQ(
79+
line.getProperty(*runtime_, "width").asNumber(),
80+
expected.frame.size.width);
81+
EXPECT_EQ(
82+
line.getProperty(*runtime_, "height").asNumber(),
83+
expected.frame.size.height);
84+
EXPECT_EQ(
85+
line.getProperty(*runtime_, "descender").asNumber(),
86+
expected.descender);
87+
EXPECT_EQ(
88+
line.getProperty(*runtime_, "capHeight").asNumber(),
89+
expected.capHeight);
90+
EXPECT_EQ(
91+
line.getProperty(*runtime_, "ascender").asNumber(),
92+
expected.ascender);
93+
EXPECT_EQ(
94+
line.getProperty(*runtime_, "xHeight").asNumber(), expected.xHeight);
95+
}
96+
97+
std::unique_ptr<facebook::hermes::HermesRuntime> runtime_;
98+
std::unique_ptr<RuntimeScheduler> runtimeScheduler_;
99+
std::shared_ptr<EventDispatcher> eventDispatcher_;
100+
std::shared_ptr<const EventListener> listener_;
101+
std::vector<CapturedEvent> events_;
102+
};
103+
104+
TEST_F(
105+
ParagraphEventEmitterTest,
106+
testOnTextLayoutSerializesEveryLineMeasurement) {
107+
const LinesMeasurements measurements{
108+
{"First line", {{1.25, 2.5}, {30.75, 10.5}}, -2.25, 7.5, 8.25, 4.5},
109+
{"Second line", {{3.5, 13.75}, {42.25, 11.5}}, -1.5, 8.0, 9.75, 5.25},
110+
};
111+
ParagraphEventEmitter eventEmitter(nullptr, eventDispatcher_);
112+
113+
eventEmitter.onTextLayout(measurements);
114+
115+
ASSERT_EQ(events_.size(), 1);
116+
EXPECT_EQ(events_[0].type, "topTextLayout");
117+
auto payload = events_[0].payload->asJSIValue(*runtime_).asObject(*runtime_);
118+
auto lines = payload.getProperty(*runtime_, "lines")
119+
.asObject(*runtime_)
120+
.asArray(*runtime_);
121+
ASSERT_EQ(lines.size(*runtime_), measurements.size());
122+
expectLine(lines, 0, measurements[0]);
123+
expectLine(lines, 1, measurements[1]);
124+
}
125+
126+
TEST_F(
127+
ParagraphEventEmitterTest,
128+
testOnTextLayoutSuppressesIdenticalMeasurementsButDispatchesChanges) {
129+
const LinesMeasurements measurements{
130+
{"Line", {{1, 2}, {30, 10}}, -2, 7, 8, 4},
131+
};
132+
auto changedMeasurements = measurements;
133+
changedMeasurements[0].xHeight = 5;
134+
ParagraphEventEmitter eventEmitter(nullptr, eventDispatcher_);
135+
136+
eventEmitter.onTextLayout(measurements);
137+
ASSERT_EQ(events_.size(), 1);
138+
139+
eventEmitter.onTextLayout(measurements);
140+
ASSERT_EQ(events_.size(), 1);
141+
142+
eventEmitter.onTextLayout(changedMeasurements);
143+
ASSERT_EQ(events_.size(), 2);
144+
auto payload = events_[1].payload->asJSIValue(*runtime_).asObject(*runtime_);
145+
auto lines = payload.getProperty(*runtime_, "lines")
146+
.asObject(*runtime_)
147+
.asArray(*runtime_);
148+
ASSERT_EQ(lines.size(*runtime_), changedMeasurements.size());
149+
auto line = lines.getValueAtIndex(*runtime_, 0).asObject(*runtime_);
150+
EXPECT_EQ(
151+
line.getProperty(*runtime_, "xHeight").asNumber(),
152+
changedMeasurements[0].xHeight);
153+
}
154+
155+
TEST_F(
156+
ParagraphEventEmitterTest,
157+
testOnTextLayoutDispatchesTransitionToEmptyMeasurements) {
158+
const LinesMeasurements measurements{
159+
{"Removed line", {{1, 2}, {30, 10}}, -2, 7, 8, 4},
160+
};
161+
ParagraphEventEmitter eventEmitter(nullptr, eventDispatcher_);
162+
163+
eventEmitter.onTextLayout(measurements);
164+
ASSERT_EQ(events_.size(), 1);
165+
166+
eventEmitter.onTextLayout({});
167+
ASSERT_EQ(events_.size(), 2);
168+
auto payload = events_[1].payload->asJSIValue(*runtime_).asObject(*runtime_);
169+
auto lines = payload.getProperty(*runtime_, "lines")
170+
.asObject(*runtime_)
171+
.asArray(*runtime_);
172+
EXPECT_EQ(lines.size(*runtime_), 0);
173+
174+
eventEmitter.onTextLayout({});
175+
EXPECT_EQ(events_.size(), 2);
176+
}
177+
178+
} // namespace
179+
180+
} // namespace facebook::react

0 commit comments

Comments
 (0)