From 6fe5b2edc611bd4ac1dd69f9e8fa6323c301b9c8 Mon Sep 17 00:00:00 2001 From: Maciek Grzybowski Date: Thu, 18 Feb 2021 17:34:42 +0100 Subject: [PATCH 1/3] RUMM-1097 Fix default `UIKitRUMViewsPredicate` to capture custom Objc `UIViewControllers` --- .../xcshareddata/xcschemes/Example.xcscheme | 7 +++- .../Example/Scenarios/RUM/RUMScenarios.swift | 17 ++++++++- .../TrackingConsentScenarios.swift | 2 +- .../Views/UIKitRUMViewsPredicate.swift | 21 +++++++---- .../RUM/RUMResourcesScenarioTests.swift | 37 +++++++++++++++++-- .../Views/UIKitRUMViewsPredicateTests.swift | 1 + 6 files changed, 69 insertions(+), 16 deletions(-) diff --git a/Datadog/Datadog.xcodeproj/xcshareddata/xcschemes/Example.xcscheme b/Datadog/Datadog.xcodeproj/xcshareddata/xcschemes/Example.xcscheme index 990e9c8586..71e9e2d788 100644 --- a/Datadog/Datadog.xcodeproj/xcshareddata/xcschemes/Example.xcscheme +++ b/Datadog/Datadog.xcodeproj/xcshareddata/xcschemes/Example.xcscheme @@ -98,7 +98,12 @@ + + RUMView? { - let canonicalClassName = viewController.canonicalClassName - let isCustomClass = canonicalClassName.contains(".") // custom class contains module prefix - - if isCustomClass { - var view = RUMView(name: canonicalClassName) - view.path = canonicalClassName - return view - } else { + guard !isUIKit(class: type(of: viewController)) else { + // do not track bare UIKit's view controllers (UINavigationController, UITabBarController, ...) return nil } + + let canonicalClassName = viewController.canonicalClassName + var view = RUMView(name: canonicalClassName) + view.path = canonicalClassName + return view + } + + /// If given `class` comes from UIKit framework. + private func isUIKit(`class`: AnyClass) -> Bool { + let bundle = Bundle(for: `class`) + return bundle.bundleURL.lastPathComponent == "UIKitCore.framework" } } diff --git a/Tests/DatadogIntegrationTests/Scenarios/RUM/RUMResourcesScenarioTests.swift b/Tests/DatadogIntegrationTests/Scenarios/RUM/RUMResourcesScenarioTests.swift index ca0c1b98e8..5b93fb8ad0 100644 --- a/Tests/DatadogIntegrationTests/Scenarios/RUM/RUMResourcesScenarioTests.swift +++ b/Tests/DatadogIntegrationTests/Scenarios/RUM/RUMResourcesScenarioTests.swift @@ -14,7 +14,34 @@ private extension ExampleApplication { } class RUMResourcesScenarioTests: IntegrationTests, RUMCommonAsserts { - func testRUMResourcesScenario() throws { + private struct Expectations { + let expectedFirstPartyRequestsViewControllerName: String + let expectedThirdPartyRequestsViewControllerName: String + } + + func testRUMURLSessionResourcesScenario() throws { + try runTest( + for: "RUMURLSessionResourcesScenario", + expectations: Expectations( + expectedFirstPartyRequestsViewControllerName: "Example.SendFirstPartyRequestsViewController", + expectedThirdPartyRequestsViewControllerName: "Example.SendThirdPartyRequestsViewController" + ) + ) + } + + func testRUMNSURLSessionResourcesScenario() throws { + try runTest( + for: "RUMNSURLSessionResourcesScenario", + expectations: Expectations( + expectedFirstPartyRequestsViewControllerName: "ObjcSendFirstPartyRequestsViewController", + expectedThirdPartyRequestsViewControllerName: "ObjcSendThirdPartyRequestsViewController" + ) + ) + } + + /// Both, `URLSession` (Swift) and `NSURLSession` (Objective-C) scenarios use different storyboards + /// and different view controllers to run this test, but the the logic and the instrumentation is the same. + private func runTest(for testScenarioClassName: String, expectations: Expectations) throws { // Server session recording first party requests send to `HTTPServerMock`. // Used to assert that trace propagation headers are send for first party requests. let customFirstPartyServerSession = server.obtainUniqueRecordingSession() @@ -40,7 +67,7 @@ class RUMResourcesScenarioTests: IntegrationTests, RUMCommonAsserts { let app = ExampleApplication() app.launchWith( - testScenarioClassName: "RUMResourcesScenario", + testScenarioClassName: testScenarioClassName, serverConfiguration: HTTPServerMockConfiguration( tracesEndpoint: tracingServerSession.recordingURL, rumEndpoint: rumServerSession.recordingURL, @@ -88,7 +115,8 @@ class RUMResourcesScenarioTests: IntegrationTests, RUMCommonAsserts { XCTAssertEqual(session.viewVisits.count, 2) // Asserts in `SendFirstPartyRequestsVC` RUM View - XCTAssertEqual(session.viewVisits[0].path, "Example.SendFirstPartyRequestsViewController") + XCTAssertEqual(session.viewVisits[0].name, expectations.expectedFirstPartyRequestsViewControllerName) + XCTAssertEqual(session.viewVisits[0].path, expectations.expectedFirstPartyRequestsViewControllerName) XCTAssertEqual(session.viewVisits[0].resourceEvents.count, 2, "1st screen should track 2 RUM Resources") XCTAssertEqual(session.viewVisits[0].errorEvents.count, 1, "1st screen should track 1 RUM Errors") @@ -126,7 +154,8 @@ class RUMResourcesScenarioTests: IntegrationTests, RUMCommonAsserts { XCTAssertEqual(firstPartyResourceError1.error.resource?.method, .get) // Asserts in `SendThirdPartyRequestsVC` RUM View - XCTAssertEqual(session.viewVisits[1].path, "Example.SendThirdPartyRequestsViewController") + XCTAssertEqual(session.viewVisits[1].name, expectations.expectedThirdPartyRequestsViewControllerName) + XCTAssertEqual(session.viewVisits[1].path, expectations.expectedThirdPartyRequestsViewControllerName) XCTAssertEqual(session.viewVisits[1].resourceEvents.count, 2, "2nd screen should track 2 RUM Resources") XCTAssertEqual(session.viewVisits[1].errorEvents.count, 0, "2nd screen should track no RUM Errors") diff --git a/Tests/DatadogTests/Datadog/RUM/AutoInstrumentation/Views/UIKitRUMViewsPredicateTests.swift b/Tests/DatadogTests/Datadog/RUM/AutoInstrumentation/Views/UIKitRUMViewsPredicateTests.swift index b8ca26e4b6..9eac350592 100644 --- a/Tests/DatadogTests/Datadog/RUM/AutoInstrumentation/Views/UIKitRUMViewsPredicateTests.swift +++ b/Tests/DatadogTests/Datadog/RUM/AutoInstrumentation/Views/UIKitRUMViewsPredicateTests.swift @@ -17,6 +17,7 @@ class UIKitRUMViewsPredicateTests: XCTestCase { let rumView = predicate.rumView(for: customViewController) // Then + XCTAssertEqual(rumView?.name, "Module.CustomViewController") XCTAssertEqual(rumView?.path, "Module.CustomViewController") XCTAssertTrue(rumView!.attributes.isEmpty) } From 72af151a5497cf72133f2ba191cf77c08e18c980 Mon Sep 17 00:00:00 2001 From: Maciek Grzybowski Date: Thu, 18 Feb 2021 18:54:34 +0100 Subject: [PATCH 2/3] RUMM-1097 Add unit test for Objc view controller passed to default RUM Views predicate --- Datadog/Datadog.xcodeproj/project.pbxproj | 6 +++++ .../DatadogTests-Bridging-Header.h | 1 + .../Views/UIKitRUMViewsPredicateTests.swift | 22 +++++++++++++++---- .../Helpers/CustomObjcViewController.h | 15 +++++++++++++ .../Helpers/CustomObjcViewController.m | 19 ++++++++++++++++ 5 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 Tests/DatadogTests/Helpers/CustomObjcViewController.h create mode 100644 Tests/DatadogTests/Helpers/CustomObjcViewController.m diff --git a/Datadog/Datadog.xcodeproj/project.pbxproj b/Datadog/Datadog.xcodeproj/project.pbxproj index eb0dea79ef..eb8ca9cc11 100644 --- a/Datadog/Datadog.xcodeproj/project.pbxproj +++ b/Datadog/Datadog.xcodeproj/project.pbxproj @@ -320,6 +320,7 @@ 61D6FF7E24E53D3B00D0E375 /* BenchmarkMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D6FF7D24E53D3B00D0E375 /* BenchmarkMocks.swift */; }; 61D980BA24E28D0100E03345 /* RUMIntegrations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D980B924E28D0100E03345 /* RUMIntegrations.swift */; }; 61D980BC24E293F600E03345 /* RUMIntegrationsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D980BB24E293F600E03345 /* RUMIntegrationsTests.swift */; }; + 61DB33B225DEDFC200F7EA71 /* CustomObjcViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 61DB33B125DEDFC200F7EA71 /* CustomObjcViewController.m */; }; 61DC6D922539E3E300FFAA22 /* LoggingCommonAsserts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61DC6D912539E3E300FFAA22 /* LoggingCommonAsserts.swift */; }; 61E36A11254B2280001AD6F2 /* LaunchTimeProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E36A10254B2280001AD6F2 /* LaunchTimeProvider.swift */; }; 61E45BCF2450A6EC00F2C652 /* TracingUUIDTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E45BCE2450A6EC00F2C652 /* TracingUUIDTests.swift */; }; @@ -772,6 +773,8 @@ 61D6FF7D24E53D3B00D0E375 /* BenchmarkMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BenchmarkMocks.swift; sourceTree = ""; }; 61D980B924E28D0100E03345 /* RUMIntegrations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMIntegrations.swift; sourceTree = ""; }; 61D980BB24E293F600E03345 /* RUMIntegrationsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMIntegrationsTests.swift; sourceTree = ""; }; + 61DB33B025DEDFC200F7EA71 /* CustomObjcViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CustomObjcViewController.h; sourceTree = ""; }; + 61DB33B125DEDFC200F7EA71 /* CustomObjcViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CustomObjcViewController.m; sourceTree = ""; }; 61DC6D912539E3E300FFAA22 /* LoggingCommonAsserts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggingCommonAsserts.swift; sourceTree = ""; }; 61E36A10254B2280001AD6F2 /* LaunchTimeProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchTimeProvider.swift; sourceTree = ""; }; 61E45BCE2450A6EC00F2C652 /* TracingUUIDTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracingUUIDTests.swift; sourceTree = ""; }; @@ -1362,6 +1365,8 @@ 61F1A622249B811200075390 /* Encoding.swift */, 61A763DA252DB2B3005A23F2 /* NSURLSessionBridge.h */, 61A763DB252DB2B3005A23F2 /* NSURLSessionBridge.m */, + 61DB33B025DEDFC200F7EA71 /* CustomObjcViewController.h */, + 61DB33B125DEDFC200F7EA71 /* CustomObjcViewController.m */, ); path = Helpers; sourceTree = ""; @@ -2951,6 +2956,7 @@ 61133C5A2423990D00786299 /* FileTests.swift in Sources */, 61AD4E3A24534075006E34EA /* TracingFeatureTests.swift in Sources */, 61133C6B2423990D00786299 /* LogMatcher.swift in Sources */, + 61DB33B225DEDFC200F7EA71 /* CustomObjcViewController.m in Sources */, 61F3CDAD25122C9200C816E5 /* UIKitRUMViewsHandlerTests.swift in Sources */, 61D980BC24E293F600E03345 /* RUMIntegrationsTests.swift in Sources */, 61363D9F24D99BAA0084CD6F /* DDErrorTests.swift in Sources */, diff --git a/Datadog/TargetSupport/DatadogTests/DatadogTests-Bridging-Header.h b/Datadog/TargetSupport/DatadogTests/DatadogTests-Bridging-Header.h index 19f2fef7dd..2b3b0697d3 100644 --- a/Datadog/TargetSupport/DatadogTests/DatadogTests-Bridging-Header.h +++ b/Datadog/TargetSupport/DatadogTests/DatadogTests-Bridging-Header.h @@ -5,3 +5,4 @@ */ #import "NSURLSessionBridge.h" +#import "CustomObjcViewController.h" diff --git a/Tests/DatadogTests/Datadog/RUM/AutoInstrumentation/Views/UIKitRUMViewsPredicateTests.swift b/Tests/DatadogTests/Datadog/RUM/AutoInstrumentation/Views/UIKitRUMViewsPredicateTests.swift index 9eac350592..ced5ee0ad7 100644 --- a/Tests/DatadogTests/Datadog/RUM/AutoInstrumentation/Views/UIKitRUMViewsPredicateTests.swift +++ b/Tests/DatadogTests/Datadog/RUM/AutoInstrumentation/Views/UIKitRUMViewsPredicateTests.swift @@ -8,17 +8,31 @@ import XCTest import Datadog class UIKitRUMViewsPredicateTests: XCTestCase { - func testGivenDefaultPredicate_whenAskingForCustomViewController_itNamesTheViewByItsClassName() { + func testGivenDefaultPredicate_whenAskingForCustomSwiftViewController_itNamesTheViewByItsClassName() { // Given let predicate = DefaultUIKitRUMViewsPredicate() // When - let customViewController = createMockView(viewControllerClassName: "Module.CustomViewController") + let customViewController = createMockView(viewControllerClassName: "CustomSwiftViewController") let rumView = predicate.rumView(for: customViewController) // Then - XCTAssertEqual(rumView?.name, "Module.CustomViewController") - XCTAssertEqual(rumView?.path, "Module.CustomViewController") + XCTAssertEqual(rumView?.name, "CustomSwiftViewController") + XCTAssertEqual(rumView?.path, "CustomSwiftViewController") + XCTAssertTrue(rumView!.attributes.isEmpty) + } + + func testGivenDefaultPredicate_whenAskingForCustomObjcViewController_itNamesTheViewByItsClassName() { + // Given + let predicate = DefaultUIKitRUMViewsPredicate() + + // When + let customViewController = CustomObjcViewController() + let rumView = predicate.rumView(for: customViewController) + + // Then + XCTAssertEqual(rumView?.name, "CustomObjcViewController") + XCTAssertEqual(rumView?.path, "CustomObjcViewController") XCTAssertTrue(rumView!.attributes.isEmpty) } diff --git a/Tests/DatadogTests/Helpers/CustomObjcViewController.h b/Tests/DatadogTests/Helpers/CustomObjcViewController.h new file mode 100644 index 0000000000..ddfed91715 --- /dev/null +++ b/Tests/DatadogTests/Helpers/CustomObjcViewController.h @@ -0,0 +1,15 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2019-2020 Datadog, Inc. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface CustomObjcViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tests/DatadogTests/Helpers/CustomObjcViewController.m b/Tests/DatadogTests/Helpers/CustomObjcViewController.m new file mode 100644 index 0000000000..8a91e69422 --- /dev/null +++ b/Tests/DatadogTests/Helpers/CustomObjcViewController.m @@ -0,0 +1,19 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2019-2020 Datadog, Inc. + */ + +#import "CustomObjcViewController.h" + +@interface CustomObjcViewController () + +@end + +@implementation CustomObjcViewController + +- (void)viewDidLoad { + [super viewDidLoad]; +} + +@end From a1118a0b8a2164dc65a3041bb97f243460344013 Mon Sep 17 00:00:00 2001 From: Maciek Grzybowski Date: Mon, 22 Feb 2021 11:50:07 +0100 Subject: [PATCH 3/3] RUMM-1097 CR fix - add extension and update comment --- Datadog/Datadog.xcodeproj/project.pbxproj | 4 ++ .../Views/UIKitRUMViewsPredicate.swift | 7 ++-- Sources/Datadog/Utils/UIKitExtensions.swift | 4 ++ .../Datadog/Utils/UIKitExtensionsTests.swift | 39 +++++++++++++++++++ 4 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 Tests/DatadogTests/Datadog/Utils/UIKitExtensionsTests.swift diff --git a/Datadog/Datadog.xcodeproj/project.pbxproj b/Datadog/Datadog.xcodeproj/project.pbxproj index eb8ca9cc11..9a0f3b155f 100644 --- a/Datadog/Datadog.xcodeproj/project.pbxproj +++ b/Datadog/Datadog.xcodeproj/project.pbxproj @@ -93,6 +93,7 @@ 6114FE23257671F00084E372 /* ConsentAwareDataWriterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6114FE22257671F00084E372 /* ConsentAwareDataWriterTests.swift */; }; 6114FE2F257687310084E372 /* ConsentProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6114FE2E257687300084E372 /* ConsentProvider.swift */; }; 6114FE3B25768AA90084E372 /* ConsentProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6114FE3A25768AA90084E372 /* ConsentProviderTests.swift */; }; + 6115299725E3BEF9004F740E /* UIKitExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6115299625E3BEF9004F740E /* UIKitExtensionsTests.swift */; }; 61163C37252DDD60007DD5BF /* RUMMVSViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61163C36252DDD60007DD5BF /* RUMMVSViewController.swift */; }; 61163C3E252E0015007DD5BF /* RUMMVSModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61163C3D252E0015007DD5BF /* RUMMVSModalViewController.swift */; }; 61163C4A252E03D6007DD5BF /* RUMModalViewsScenarioTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61163C49252E03D6007DD5BF /* RUMModalViewsScenarioTests.swift */; }; @@ -543,6 +544,7 @@ 6114FE22257671F00084E372 /* ConsentAwareDataWriterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsentAwareDataWriterTests.swift; sourceTree = ""; }; 6114FE2E257687300084E372 /* ConsentProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsentProvider.swift; sourceTree = ""; }; 6114FE3A25768AA90084E372 /* ConsentProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsentProviderTests.swift; sourceTree = ""; }; + 6115299625E3BEF9004F740E /* UIKitExtensionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitExtensionsTests.swift; sourceTree = ""; }; 61163C36252DDD60007DD5BF /* RUMMVSViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMMVSViewController.swift; sourceTree = ""; }; 61163C3D252E0015007DD5BF /* RUMMVSModalViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMMVSModalViewController.swift; sourceTree = ""; }; 61163C49252E03D6007DD5BF /* RUMModalViewsScenarioTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMModalViewsScenarioTests.swift; sourceTree = ""; }; @@ -1310,6 +1312,7 @@ children = ( 61133C362423990D00786299 /* InternalLoggersTests.swift */, 9E36D92124373EA700BFBDB7 /* SwiftExtensionsTests.swift */, + 6115299625E3BEF9004F740E /* UIKitExtensionsTests.swift */, ); path = Utils; sourceTree = ""; @@ -3061,6 +3064,7 @@ 61133C4E2423990D00786299 /* UIKitMocks.swift in Sources */, 61B0387B252724AB00518F3C /* URLSessionTracingHandlerTests.swift in Sources */, 61133C4D2423990D00786299 /* CoreTelephonyMocks.swift in Sources */, + 6115299725E3BEF9004F740E /* UIKitExtensionsTests.swift in Sources */, 614B0A4D24EBD71500A2A780 /* RUMUserInfoProviderTests.swift in Sources */, 9EF963E82537556300235F98 /* DDURLSessionDelegateAsSuperclassTests.swift in Sources */, 61133C552423990D00786299 /* BatteryStatusProviderTests.swift in Sources */, diff --git a/Sources/Datadog/RUM/AutoInstrumentation/Views/UIKitRUMViewsPredicate.swift b/Sources/Datadog/RUM/AutoInstrumentation/Views/UIKitRUMViewsPredicate.swift index 45c4b79d0b..94e4d93dd9 100644 --- a/Sources/Datadog/RUM/AutoInstrumentation/Views/UIKitRUMViewsPredicate.swift +++ b/Sources/Datadog/RUM/AutoInstrumentation/Views/UIKitRUMViewsPredicate.swift @@ -59,7 +59,9 @@ public struct DefaultUIKitRUMViewsPredicate: UIKitRUMViewsPredicate { public func rumView(for viewController: UIViewController) -> RUMView? { guard !isUIKit(class: type(of: viewController)) else { - // do not track bare UIKit's view controllers (UINavigationController, UITabBarController, ...) + // Part of our heuristic for (auto) tracking view controllers is to ignore + // container view controllers coming from `UIKit` if they are not subclassed. + // This condition is wider and it ignores all view controllers defined in `UIKit` bundle. return nil } @@ -71,7 +73,6 @@ public struct DefaultUIKitRUMViewsPredicate: UIKitRUMViewsPredicate { /// If given `class` comes from UIKit framework. private func isUIKit(`class`: AnyClass) -> Bool { - let bundle = Bundle(for: `class`) - return bundle.bundleURL.lastPathComponent == "UIKitCore.framework" + return Bundle(for: `class`).isUIKit } } diff --git a/Sources/Datadog/Utils/UIKitExtensions.swift b/Sources/Datadog/Utils/UIKitExtensions.swift index adacffcd4e..ae5171ebe1 100644 --- a/Sources/Datadog/Utils/UIKitExtensions.swift +++ b/Sources/Datadog/Utils/UIKitExtensions.swift @@ -24,3 +24,7 @@ internal extension UIViewController { return NSStringFromClass(type(of: self)) } } + +internal extension Bundle { + var isUIKit: Bool { bundleURL.lastPathComponent == "UIKitCore.framework" } +} diff --git a/Tests/DatadogTests/Datadog/Utils/UIKitExtensionsTests.swift b/Tests/DatadogTests/Datadog/Utils/UIKitExtensionsTests.swift new file mode 100644 index 0000000000..5486f3d2c3 --- /dev/null +++ b/Tests/DatadogTests/Datadog/Utils/UIKitExtensionsTests.swift @@ -0,0 +1,39 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2019-2020 Datadog, Inc. + */ + +import XCTest +import UIKit +@testable import Datadog + +class CustomSwiftViewController: UIViewController {} + +class UIKitExtensionsTests: XCTestCase { + func testViewControllerCanonicalClassName() { + let swiftViewController = CustomSwiftViewController() + let objcViewController = CustomObjcViewController() + + XCTAssertEqual(swiftViewController.canonicalClassName, "DatadogTests.CustomSwiftViewController") + XCTAssertEqual(objcViewController.canonicalClassName, "CustomObjcViewController") + } + + func testBundleIsUIKit() { + let someUIKitClasses: [AnyClass] = [ + UIViewController.self, + UIButton.self, + UINavigationBar.self, + UIScrollView.self + ] + + let someNonUIKitClasses: [AnyClass] = [ + CustomSwiftViewController.self, + CustomObjcViewController.self, + OperationQueue.self, + ] + + someUIKitClasses.forEach { XCTAssertTrue(Bundle(for: $0).isUIKit) } + someNonUIKitClasses.forEach { XCTAssertFalse(Bundle(for: $0).isUIKit) } + } +}