/* * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "RCTTestModule.h" #import #import #import #import #import #import "FBSnapshotTestController.h" #import "RCTTestPlugins.h" @protocol NativeTestModuleSpec - (void)markTestCompleted; - (void)markTestPassed:(BOOL)success; - (void)verifySnapshot:(RCTResponseSenderBlock)callback; @end namespace facebook { namespace react { /** * ObjC++ class for module 'TestModule' */ class JSI_EXPORT NativeTestModuleSpecJSI : public ObjCTurboModule { public: NativeTestModuleSpecJSI(id instance, std::shared_ptr jsInvoker, std::shared_ptr nativeInvoker, id perfLogger); }; } // namespace react } // namespace facebook namespace facebook { namespace react { static facebook::jsi::Value __hostFunction_NativeTestModuleSpecJSI_markTestCompleted(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "markTestCompleted", @selector(markTestCompleted), args, count); } static facebook::jsi::Value __hostFunction_NativeTestModuleSpecJSI_markTestPassed(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "markTestPassed", @selector(markTestPassed:), args, count); } static facebook::jsi::Value __hostFunction_NativeTestModuleSpecJSI_verifySnapshot(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "verifySnapshot", @selector(verifySnapshot:), args, count); } NativeTestModuleSpecJSI::NativeTestModuleSpecJSI(id instance, std::shared_ptr jsInvoker, std::shared_ptr nativeInvoker, id perfLogger) : ObjCTurboModule("TestModule", instance, jsInvoker, nativeInvoker, perfLogger) { methodMap_["markTestCompleted"] = MethodMetadata {0, __hostFunction_NativeTestModuleSpecJSI_markTestCompleted}; methodMap_["markTestPassed"] = MethodMetadata {1, __hostFunction_NativeTestModuleSpecJSI_markTestPassed}; methodMap_["verifySnapshot"] = MethodMetadata {1, __hostFunction_NativeTestModuleSpecJSI_verifySnapshot}; } } // namespace react } // namespace facebook @interface RCTTestModule() @end @implementation RCTTestModule { NSMutableDictionary *_snapshotCounter; } @synthesize bridge = _bridge; RCT_EXPORT_MODULE() - (dispatch_queue_t)methodQueue { return _bridge.uiManager.methodQueue; } RCT_EXPORT_METHOD(verifySnapshot:(RCTResponseSenderBlock)callback) { RCTAssert(_controller != nil, @"No snapshot controller configured."); [_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) { NSString *testName = NSStringFromSelector(self->_testSelector); if (!self->_snapshotCounter) { self->_snapshotCounter = [NSMutableDictionary new]; } NSNumber *counter = @([self->_snapshotCounter[testName] integerValue] + 1); self->_snapshotCounter[testName] = counter; NSError *error = nil; NSString *identifier = [counter stringValue]; if (self->_testSuffix) { identifier = [identifier stringByAppendingString:self->_testSuffix]; } BOOL success = [self->_controller compareSnapshotOfView:self->_view selector:self->_testSelector identifier:identifier error:&error]; if (!success) { RCTLogInfo(@"Failed to verify snapshot %@ (error: %@)", identifier, error); } callback(@[@(success)]); }]; } RCT_EXPORT_METHOD(sendAppEvent:(NSString *)name body:(nullable id)body) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" [_bridge.eventDispatcher sendAppEventWithName:name body:body]; #pragma clang diagnostic pop } RCT_REMAP_METHOD(shouldResolve, shouldResolve_resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) { resolve(@1); } RCT_REMAP_METHOD(shouldReject, shouldReject_resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) { reject(nil, nil, nil); } RCT_EXPORT_METHOD(markTestCompleted) { [self markTestPassed:YES]; } RCT_EXPORT_METHOD(markTestPassed:(BOOL)success) { [_bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, __unused NSDictionary *viewRegistry) { self->_status = success ? RCTTestStatusPassed : RCTTestStatusFailed; }]; } - (std::shared_ptr) getTurboModuleWithJsInvoker:(std::shared_ptr)jsInvoker nativeInvoker:(std::shared_ptr)nativeInvoker perfLogger:(id)perfLogger { return std::make_shared(self, jsInvoker, nativeInvoker, perfLogger); } @end Class RCTTestModuleCls(void) { return RCTTestModule.class; }