diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/tests/TurboModuleTestFixture.h b/packages/react-native/ReactCommon/react/nativemodule/core/tests/TurboModuleTestFixture.h index c0039e3405906f..824af01fb09497 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/tests/TurboModuleTestFixture.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/tests/TurboModuleTestFixture.h @@ -10,7 +10,10 @@ #include #include #include +#include +#include #include +#include namespace facebook::react { @@ -22,6 +25,75 @@ class TurboModuleTestFixture : public ::testing::Test { jsInvoker_(std::make_shared(runtime_)), module_(std::make_shared(jsInvoker_, std::forward(args)...)) {} + void SetUp() override { + auto setImmediateName = + jsi::PropNameID::forAscii(*runtime_, "setImmediate"); + runtime_->global().setProperty( + *runtime_, + setImmediateName, + jsi::Function::createFromHostFunction( + *runtime_, + setImmediateName, + 1, + [jsInvoker = jsInvoker_]( + jsi::Runtime& rt, + [[maybe_unused]] const jsi::Value& thisVal, + const jsi::Value* args, + size_t count) { + react_native_assert(count >= 1); + jsInvoker->invokeAsync([cb = std::make_shared( + rt, args[0])](jsi::Runtime& rt) { + cb->asObject(rt).asFunction(rt).call(rt); + }); + return jsi::Value::undefined(); + })); + } + + void TearDown() override { + module_ = nullptr; + jsInvoker_ = nullptr; + runtime_ = nullptr; + } + + template + std::optional resolvePromise( + const AsyncPromise& asyncPromise) { + auto promise = asyncPromise.get(*runtime_); + std::optional result = std::nullopt; + promise.getPropertyAsFunction(*runtime_, "then") + .callWithThis( + *runtime_, + promise, + bridging::toJs( + *runtime_, + [&](TPromise value) { result = std::move(value); }, + jsInvoker_)); + jsInvoker_->flushQueue(); + return result; + } + + template + std::optional handleError( + const AsyncPromise& asyncPromise) { + auto promise = asyncPromise.get(*runtime_); + std::optional message; + promise.getPropertyAsFunction(*runtime_, "catch") + .callWithThis( + *runtime_, + promise, + bridging::toJs( + *runtime_, + [&](jsi::Object error) { + message = bridging::fromJs( + *runtime_, + error.getProperty(*runtime_, "message"), + jsInvoker_); + }, + jsInvoker_)); + jsInvoker_->flushQueue(); + return message; + } + protected: std::shared_ptr runtime_{}; std::shared_ptr jsInvoker_{}; diff --git a/packages/rn-tester/NativeCxxModuleExample/tests/NativeCxxModuleExampleTests.cpp b/packages/rn-tester/NativeCxxModuleExample/tests/NativeCxxModuleExampleTests.cpp index b182b529151c32..616ff56fee20f7 100644 --- a/packages/rn-tester/NativeCxxModuleExample/tests/NativeCxxModuleExampleTests.cpp +++ b/packages/rn-tester/NativeCxxModuleExample/tests/NativeCxxModuleExampleTests.cpp @@ -154,6 +154,16 @@ TEST_F(NativeCxxModuleExampleTests, GetValueReturnsCorrectValues) { EXPECT_EQ(result.z.c, "seven"); } +TEST_F(NativeCxxModuleExampleTests, GetValueWithPromiseReturnsCorrectValues) { + auto promise1 = module_->getValueWithPromise(*runtime_, false); + auto result = resolvePromise(promise1); + EXPECT_EQ(result, "result!"); + + auto promise2 = module_->getValueWithPromise(*runtime_, true); + auto message = handleError(promise2); + EXPECT_EQ(message, "intentional promise rejection"); +} + TEST_F( NativeCxxModuleExampleTests, GetWithWithOptionalArgsReturnsCorrectValues) {