// Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // XCTest is weakly linked. #if __has_include() #import "FLTIntegrationTestCase.h" #import "FLTIntegrationTestRunner.h" #import "IntegrationTestPlugin.h" @import ObjectiveC.runtime; @import XCTest; @implementation FLTIntegrationTestCase + (NSArray *)testInvocations { if (self == [FLTIntegrationTestCase class]) { // Do not add any tests for this base class. return @[]; } FLTIntegrationTestRunner *integrationTestRunner = [FLTIntegrationTestRunner new]; NSMutableArray *testInvocations = [NSMutableArray new]; [integrationTestRunner testIntegrationTestWithResults:^(NSString *testName, BOOL success, NSString *failureMessage) { // For every Flutter dart test, dynamically generate an Objective-C method mirroring the test results // so it is reported as a native XCTest run result. IMP assertImplementation = imp_implementationWithBlock(^(id _self) { XCTAssertTrue(success, @"%@", failureMessage); }); // Create an appropriate XCTest method name based on the dart test name. // Example: dart test "verify widget" becomes "testVerifyWidget" NSString *upperCamelTestName = [testName.localizedCapitalizedString stringByReplacingOccurrencesOfString:@" " withString:@""]; NSString *testSelectorName = [NSString stringWithFormat:@"test%@", upperCamelTestName]; SEL testSelector = NSSelectorFromString(testSelectorName); class_addMethod(self, testSelector, assertImplementation, "v@:"); // Add the new class method as a test invocation to the XCTestCase. NSMethodSignature *signature = [self instanceMethodSignatureForSelector:testSelector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; invocation.selector = testSelector; [testInvocations addObject:invocation]; }]; NSDictionary *capturedScreenshotsByName = integrationTestRunner.capturedScreenshotsByName; if (capturedScreenshotsByName.count > 0) { // If the Flutter dart tests have captured screenshots, add them to the XCTest bundle. IMP screenshotImplementation = imp_implementationWithBlock(^(id _self) { [capturedScreenshotsByName enumerateKeysAndObjectsUsingBlock:^(NSString *name, UIImage *screenshot, BOOL *stop) { XCTAttachment *attachment = [XCTAttachment attachmentWithImage:screenshot]; attachment.lifetime = XCTAttachmentLifetimeKeepAlways; if (name != nil) { attachment.name = name; } [_self addAttachment:attachment]; }]; }); SEL attachmentSelector = NSSelectorFromString(@"screenshotPlaceholder"); class_addMethod(self, attachmentSelector, screenshotImplementation, "v@:"); NSMethodSignature *attachmentSignature = [self instanceMethodSignatureForSelector:attachmentSelector]; NSInvocation *attachmentInvocation = [NSInvocation invocationWithMethodSignature:attachmentSignature]; attachmentInvocation.selector = attachmentSelector; [testInvocations addObject:attachmentInvocation]; } return testInvocations; } @end #endif