diff --git a/StreamVideo.xcodeproj/project.pbxproj b/StreamVideo.xcodeproj/project.pbxproj index b99752296..11faf215e 100644 --- a/StreamVideo.xcodeproj/project.pbxproj +++ b/StreamVideo.xcodeproj/project.pbxproj @@ -41,6 +41,9 @@ 404A5CF12AD5487A00EF1C62 /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 404A5CF02AD5487A00EF1C62 /* SnapshotTesting */; }; 404A5CF32AD5488F00EF1C62 /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 404A5CF22AD5488F00EF1C62 /* SnapshotTesting */; }; 404A5CF52AD5489500EF1C62 /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 404A5CF42AD5489500EF1C62 /* SnapshotTesting */; }; + 404A5CF72AD549F400EF1C62 /* CALayer+Swizzle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 404A5CF62AD549F400EF1C62 /* CALayer+Swizzle.swift */; }; + 404A5CF82AD549F400EF1C62 /* CALayer+Swizzle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 404A5CF62AD549F400EF1C62 /* CALayer+Swizzle.swift */; }; + 404A5CF92AD54A0B00EF1C62 /* CALayer+Swizzle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 404A5CF62AD549F400EF1C62 /* CALayer+Swizzle.swift */; }; 4059C3422AAF0CE40006928E /* DemoChatViewModel+Injection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4059C3412AAF0CE40006928E /* DemoChatViewModel+Injection.swift */; }; 406A8E8D2AA1D78C001F598A /* AppEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4030E59F2A9DF5BD003E8CBA /* AppEnvironment.swift */; }; 406A8E8E2AA1D79D001F598A /* UserState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F445AD2A9DFC34004BE3DA /* UserState.swift */; }; @@ -899,6 +902,7 @@ 4046DEE82A9E381F00CA6D2F /* AppIntentVocabulary.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = AppIntentVocabulary.plist; sourceTree = ""; }; 4046DEEA2A9E38DC00CA6D2F /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 4046DEF12A9F510C00CA6D2F /* DebugMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugMenu.swift; sourceTree = ""; }; + 404A5CF62AD549F400EF1C62 /* CALayer+Swizzle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CALayer+Swizzle.swift"; sourceTree = ""; }; 4059C3412AAF0CE40006928E /* DemoChatViewModel+Injection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DemoChatViewModel+Injection.swift"; sourceTree = ""; }; 407D5D3C2ACEF0C500B5044E /* VisibilityThresholdModifier_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisibilityThresholdModifier_Tests.swift; sourceTree = ""; }; 409386192AA09E4A00FF5AF4 /* MemoryLogDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryLogDestination.swift; sourceTree = ""; }; @@ -2089,6 +2093,7 @@ children = ( 824DBAA229F93DBC005ACD09 /* SnapshotVariant.swift */, 824DBAA429F93E1F005ACD09 /* AssertSnapshot.swift */, + 404A5CF62AD549F400EF1C62 /* CALayer+Swizzle.swift */, ); path = SnapshotTesting; sourceTree = ""; @@ -4213,6 +4218,7 @@ 84F58B7F29EE97C800010C4C /* VirtualTimer.swift in Sources */, 84F58B7A29EE972A00010C4C /* WebSocketPingController_Tests.swift in Sources */, 8490033129D6D2BF00AD9BB4 /* MockResponseBuilder.swift in Sources */, + 404A5CF92AD54A0B00EF1C62 /* CALayer+Swizzle.swift in Sources */, 84F58B8F29EEB32700010C4C /* WebSocketPingController_Mock.swift in Sources */, 84F58B7229EE922700010C4C /* WebSocketConnectionState_Tests.swift in Sources */, 40AB31262A49838000C270E1 /* EventTests.swift in Sources */, @@ -4372,6 +4378,7 @@ 82E3BA482A0BAE2A001AB93E /* AssertAsync.swift in Sources */, 82FF40BB2A17C6DF00B4D95E /* ScreenSharingView_Tests.swift in Sources */, 84D425102AA72F3500473150 /* LivestreamPlayer_Tests.swift in Sources */, + 404A5CF72AD549F400EF1C62 /* CALayer+Swizzle.swift in Sources */, 82FF40C02A17C73C00B4D95E /* CallingGroupView_Tests.swift in Sources */, 82E3BA3C2A0BADCA001AB93E /* MockResponseBuilder.swift in Sources */, 82E3BA502A0BAEAA001AB93E /* MockFunc.swift in Sources */, @@ -4427,6 +4434,7 @@ 8251E6312A17BEEF00E7257A /* ImageFactory.swift in Sources */, 82E3BA412A0BADFA001AB93E /* WebSocketPingController_Mock.swift in Sources */, 8493227B290938930013C029 /* StreamVideoUITestCase.swift in Sources */, + 404A5CF82AD549F400EF1C62 /* CALayer+Swizzle.swift in Sources */, 82E3BA572A0BAF65001AB93E /* WebSocketEngine_Mock.swift in Sources */, 824DBAA629F93E1F005ACD09 /* AssertSnapshot.swift in Sources */, 8251E62D2A17BEB400E7257A /* StreamVideoTestResources.swift in Sources */, diff --git a/StreamVideoSwiftUITests/StreamVideoUITestCase.swift b/StreamVideoSwiftUITests/StreamVideoUITestCase.swift index d31b44126..67894238b 100644 --- a/StreamVideoSwiftUITests/StreamVideoUITestCase.swift +++ b/StreamVideoSwiftUITests/StreamVideoUITestCase.swift @@ -18,14 +18,16 @@ class StreamVideoUITestCase: XCTestCase { var callCid: String { "\(callType):\(callId)" } let sizeThatFits = CGSize(width: 100, height: 100) - override func setUpWithError() throws { - try super.setUpWithError() + override func setUp() { + super.setUp() let streamVideo = StreamVideo.mock(httpClient: httpClient) streamVideoUI = StreamVideoUI(streamVideo: streamVideo) + CALayer.swizzleShadow() + animations(enabled: false) } - - override func tearDownWithError() throws { - try super.tearDownWithError() + + func animations(enabled: Bool) { + UIView.setAnimationsEnabled(enabled) } } diff --git a/StreamVideoSwiftUITests/Utils/ToastView_Tests.swift b/StreamVideoSwiftUITests/Utils/ToastView_Tests.swift index 9c150c4ea..6f3caadc5 100644 --- a/StreamVideoSwiftUITests/Utils/ToastView_Tests.swift +++ b/StreamVideoSwiftUITests/Utils/ToastView_Tests.swift @@ -7,9 +7,7 @@ import SwiftUI import SnapshotTesting import XCTest -final class ToastView_Tests: XCTestCase { - - private let perceptualPrecision: Float = 0.96 +final class ToastView_Tests: StreamVideoTestCase { func test_toastView_errorSnapshot() { // Given @@ -23,7 +21,7 @@ final class ToastView_Tests: XCTestCase { // Then - AssertSnapshot(view, perceptualPrecision: perceptualPrecision) + AssertSnapshot(view) } func test_toastView_successSnapshot() { @@ -38,7 +36,7 @@ final class ToastView_Tests: XCTestCase { // Then - AssertSnapshot(view, perceptualPrecision: perceptualPrecision) + AssertSnapshot(view) } func test_toastView_warningSnapshot() { @@ -53,7 +51,7 @@ final class ToastView_Tests: XCTestCase { // Then - AssertSnapshot(view, perceptualPrecision: perceptualPrecision) + AssertSnapshot(view) } func test_toastView_infoSnapshot() { @@ -68,7 +66,7 @@ final class ToastView_Tests: XCTestCase { // Then - AssertSnapshot(view, perceptualPrecision: perceptualPrecision) + AssertSnapshot(view) } func test_toastView_errorSnapshotBottom() { @@ -83,7 +81,7 @@ final class ToastView_Tests: XCTestCase { // Then - AssertSnapshot(view, perceptualPrecision: perceptualPrecision) + AssertSnapshot(view) } } diff --git a/StreamVideoTests/StreamVideoTestCase.swift b/StreamVideoTests/StreamVideoTestCase.swift index dd2710380..daed51601 100644 --- a/StreamVideoTests/StreamVideoTestCase.swift +++ b/StreamVideoTests/StreamVideoTestCase.swift @@ -13,10 +13,16 @@ open class StreamVideoTestCase: XCTestCase { open override func setUp() { super.setUp() streamVideo = StreamVideo.mock(httpClient: httpClient) + CALayer.swizzleShadow() + animations(enabled: false) } // TODO: replace this with something a bit better func waitForCallEvent(nanoseconds: UInt64 = 500_000_000) async throws { try await Task.sleep(nanoseconds: nanoseconds) } + + func animations(enabled: Bool) { + UIView.setAnimationsEnabled(enabled) + } } diff --git a/TestTools/SnapshotTesting/CALayer+Swizzle.swift b/TestTools/SnapshotTesting/CALayer+Swizzle.swift new file mode 100644 index 000000000..7376c55eb --- /dev/null +++ b/TestTools/SnapshotTesting/CALayer+Swizzle.swift @@ -0,0 +1,36 @@ +// +// Copyright © 2023 Stream.io Inc. All rights reserved. +// + +import UIKit +import XCTest + +extension CALayer { + static func swizzleShadow() { + swizzle(original: #selector(getter: shadowOpacity), modified: #selector(_swizzled_shadowOpacity)) + swizzle(original: #selector(getter: shadowRadius), modified: #selector(_swizzled_shadowRadius)) + swizzle(original: #selector(getter: shadowColor), modified: #selector(_swizzled_shadowColor)) + swizzle(original: #selector(getter: shadowOffset), modified: #selector(_swizzled_shadowOffset)) + swizzle(original: #selector(getter: shadowPath), modified: #selector(_swizzled_shadowPath)) + } + + static func reverSwizzleShadow() { + swizzle(original: #selector(_swizzled_shadowOpacity), modified: #selector(getter: shadowOpacity)) + swizzle(original: #selector(_swizzled_shadowRadius), modified: #selector(getter: shadowRadius)) + swizzle(original: #selector(_swizzled_shadowColor), modified: #selector(getter: shadowColor)) + swizzle(original: #selector(_swizzled_shadowOffset), modified: #selector(getter: shadowOffset)) + swizzle(original: #selector(_swizzled_shadowPath), modified: #selector(getter: shadowPath)) + } + + private static func swizzle(original: Selector, modified: Selector) { + let originalMethod = class_getInstanceMethod(self, original)! + let swizzledMethod = class_getInstanceMethod(self, modified)! + method_exchangeImplementations(originalMethod, swizzledMethod) + } + + @objc func _swizzled_shadowOpacity() -> Float { .zero } + @objc func _swizzled_shadowRadius() -> CGFloat { .zero } + @objc func _swizzled_shadowColor() -> CGColor? { nil } + @objc func _swizzled_shadowOffset() -> CGSize { .zero } + @objc func _swizzled_shadowPath() -> CGPath? { nil } +}