Skip to content

Commit

Permalink
fix: Update swizzling of waitForQuiescenceIncludingAnimationsIdle: AP…
Browse files Browse the repository at this point in the history
…I for Xcode16-beta5 (#935)
  • Loading branch information
mykola-mokhnach authored Aug 9, 2024
1 parent bf7652a commit 2ccc436
Show file tree
Hide file tree
Showing 12 changed files with 71 additions and 1 deletion.
4 changes: 4 additions & 0 deletions PrivateHeaders/XCTest/XCUIApplicationProcess.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@
- (void)terminate;
- (void)waitForViewControllerViewDidDisappearWithTimeout:(double)arg1;
- (void)waitForAutomationSession;
// Before Xcode16-beta5
- (void)waitForQuiescenceIncludingAnimationsIdle:(BOOL)arg1;
// Since Xcode16-beta5
- (void)waitForQuiescenceIncludingAnimationsIdle:(BOOL)arg1 isPreEvent:(BOOL)arg2;


- (id)shortDescription;
- (id)_queue_description;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ @implementation XCAXClient_iOS (FBSnapshotReqParams)

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-load-method"
#pragma clang diagnostic ignored "-Wcast-function-type-strict"

+ (void)load
{
Expand Down
3 changes: 3 additions & 0 deletions WebDriverAgentLib/Categories/XCTIssue+FBPatcher.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ @implementation XCTIssue (AMPatcher)

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-load-method"
#pragma clang diagnostic ignored "-Wcast-function-type-strict"

+ (void)load
{
SEL originalShouldInterruptTest = NSSelectorFromString(@"shouldInterruptTest");
Expand All @@ -28,6 +30,7 @@ + (void)load
if (nil == originalShouldInterruptTestMethod) return;
method_setImplementation(originalShouldInterruptTestMethod, (IMP)swizzledShouldInterruptTest);
}

#pragma clang diagnostic pop

@end
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ NS_ASSUME_NONNULL_BEGIN
/*! Defines wtether the process should perform quiescence checks. YES by default */
@property (nonatomic) NSNumber* fb_shouldWaitForQuiescence;

/**
@param waitForAnimations Set it to YES if XCTest should also wait for application animations to complete
*/
- (void)fb_waitForQuiescenceIncludingAnimationsIdle:(bool)waitForAnimations;

@end

NS_ASSUME_NONNULL_END
42 changes: 42 additions & 0 deletions WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
#import <objc/runtime.h>

#import "FBConfiguration.h"
#import "FBExceptions.h"
#import "FBLogger.h"
#import "FBSettings.h"

static void (*original_waitForQuiescenceIncludingAnimationsIdle)(id, SEL, BOOL);
static void (*original_waitForQuiescenceIncludingAnimationsIdlePreEvent)(id, SEL, BOOL, BOOL);

static void swizzledWaitForQuiescenceIncludingAnimationsIdle(id self, SEL _cmd, BOOL includingAnimations)
{
Expand All @@ -38,17 +40,43 @@ static void swizzledWaitForQuiescenceIncludingAnimationsIdle(id self, SEL _cmd,
}
}

static void swizzledWaitForQuiescenceIncludingAnimationsIdlePreEvent(id self, SEL _cmd, BOOL includingAnimations, BOOL isPreEvent)
{
NSString *bundleId = [self bundleID];
if (![[self fb_shouldWaitForQuiescence] boolValue] || FBConfiguration.waitForIdleTimeout < DBL_EPSILON) {
[FBLogger logFmt:@"Quiescence checks are disabled for %@ application. Making it to believe it is idling",
bundleId];
return;
}

NSTimeInterval desiredTimeout = FBConfiguration.waitForIdleTimeout;
NSTimeInterval previousTimeout = _XCTApplicationStateTimeout();
_XCTSetApplicationStateTimeout(desiredTimeout);
[FBLogger logFmt:@"Waiting up to %@s until %@ is in idle state (%@ animations)",
@(desiredTimeout), bundleId, includingAnimations ? @"including" : @"excluding"];
@try {
original_waitForQuiescenceIncludingAnimationsIdlePreEvent(self, _cmd, includingAnimations, isPreEvent);
} @finally {
_XCTSetApplicationStateTimeout(previousTimeout);
}
}

@implementation XCUIApplicationProcess (FBQuiescence)

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-load-method"
#pragma clang diagnostic ignored "-Wcast-function-type-strict"

+ (void)load
{
Method waitForQuiescenceIncludingAnimationsIdleMethod = class_getInstanceMethod(self.class, @selector(waitForQuiescenceIncludingAnimationsIdle:));
Method waitForQuiescenceIncludingAnimationsIdlePreEventMethod = class_getInstanceMethod(self.class, @selector(waitForQuiescenceIncludingAnimationsIdle:isPreEvent:));
if (nil != waitForQuiescenceIncludingAnimationsIdleMethod) {
IMP swizzledImp = (IMP)swizzledWaitForQuiescenceIncludingAnimationsIdle;
original_waitForQuiescenceIncludingAnimationsIdle = (void (*)(id, SEL, BOOL)) method_setImplementation(waitForQuiescenceIncludingAnimationsIdleMethod, swizzledImp);
} else if (nil != waitForQuiescenceIncludingAnimationsIdlePreEventMethod) {
IMP swizzledImp = (IMP)swizzledWaitForQuiescenceIncludingAnimationsIdlePreEvent;
original_waitForQuiescenceIncludingAnimationsIdlePreEvent = (void (*)(id, SEL, BOOL, BOOL)) method_setImplementation(waitForQuiescenceIncludingAnimationsIdlePreEventMethod, swizzledImp);
} else {
[FBLogger log:@"Could not find method -[XCUIApplicationProcess waitForQuiescenceIncludingAnimationsIdle:]"];
}
Expand All @@ -74,4 +102,18 @@ - (void)setFb_shouldWaitForQuiescence:(NSNumber *)value
objc_setAssociatedObject(self, &XCUIAPPLICATIONPROCESS_SHOULD_WAIT_FOR_QUIESCENCE, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (void)fb_waitForQuiescenceIncludingAnimationsIdle:(bool)waitForAnimations
{
if ([self respondsToSelector:@selector(waitForQuiescenceIncludingAnimationsIdle:)]) {
[self waitForQuiescenceIncludingAnimationsIdle:waitForAnimations];
} else if ([self respondsToSelector:@selector(waitForQuiescenceIncludingAnimationsIdle:isPreEvent:)]) {
[self waitForQuiescenceIncludingAnimationsIdle:waitForAnimations isPreEvent:NO];
} else {
@throw [NSException exceptionWithName:FBIncompatibleWdaException
reason:@"The current WebDriverAgent build is not compatible to your device OS version"
userInfo:@{}];
}
}


@end
1 change: 1 addition & 0 deletions WebDriverAgentLib/Categories/XCUIElement+FBUID.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ static void swizzled_validatePredicateWithExpressionsAllowed(id self, SEL _cmd,

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-load-method"
#pragma clang diagnostic ignored "-Wcast-function-type-strict"
+ (void)load
{
Class XCElementSnapshotCls = objc_lookUpClass("XCElementSnapshot");
Expand Down
3 changes: 2 additions & 1 deletion WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#import "XCTElementSetTransformer-Protocol.h"
#import "XCTestPrivateSymbols.h"
#import "XCTRunnerDaemonSession.h"
#import "XCUIApplicationProcess+FBQuiescence.h"
#import "XCUIElement+FBCaching.h"
#import "XCUIElement+FBWebDriverAttributes.h"
#import "XCUIElementQuery.h"
Expand Down Expand Up @@ -190,7 +191,7 @@ - (void)fb_waitUntilStableWithTimeout:(NSTimeInterval)timeout
self.application.fb_shouldWaitForQuiescence = YES;
}
[[[self.application applicationImpl] currentProcess]
waitForQuiescenceIncludingAnimationsIdle:YES];
fb_waitForQuiescenceIncludingAnimationsIdle:YES];
if (previousQuiescence != self.application.fb_shouldWaitForQuiescence) {
self.application.fb_shouldWaitForQuiescence = previousQuiescence;
}
Expand Down
3 changes: 3 additions & 0 deletions WebDriverAgentLib/Routing/FBExceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,7 @@ extern NSString *const FBApplicationCrashedException;
/*! Exception used to notify about the application is not installed */
extern NSString *const FBApplicationMissingException;

/*! Exception used to notify about WDA incompatibility with the current platform version */
extern NSString *const FBIncompatibleWdaException;

NS_ASSUME_NONNULL_END
1 change: 1 addition & 0 deletions WebDriverAgentLib/Routing/FBExceptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@
NSString *const FBClassChainQueryParseException = @"FBClassChainQueryParseException";
NSString *const FBApplicationCrashedException = @"FBApplicationCrashedException";
NSString *const FBApplicationMissingException = @"FBApplicationMissingException";
NSString *const FBIncompatibleWdaException = @"FBIncompatibleWdaException";
3 changes: 3 additions & 0 deletions WebDriverAgentLib/Routing/FBRoute.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ @implementation FBRoute_TargetAction
- (void)mountRequest:(FBRouteRequest *)request intoResponse:(RouteResponse *)response
{
[self decorateRequest:request];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcast-function-type-strict"
id<FBResponsePayload> (*requestMsgSend)(id, SEL, FBRouteRequest *) = ((id<FBResponsePayload>(*)(id, SEL, FBRouteRequest *))objc_msgSend);
#pragma clang diagnostic pop
id<FBResponsePayload> payload = requestMsgSend(self.target, self.action, request);
[payload dispatchWithResponse:response];
}
Expand Down
3 changes: 3 additions & 0 deletions WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,12 @@ + (void)swizzleLaunchApp {
[FBLogger log:@"Could not find method -[XCTRunnerDaemonSession launchApplicationWithPath:]"];
return;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcast-function-type-strict"
// Workaround for https://github.com/appium/WebDriverAgent/issues/702
originalLaunchAppMethod = (void(*)(id, SEL, NSString*, NSString*, NSArray*, NSDictionary*, void (^)(_Bool, NSError *))) method_getImplementation(original);
method_setImplementation(original, (IMP)swizzledLaunchApp);
#pragma clang diagnostic pop
}

+ (id<XCTestManager_ManagerInterface>)testRunnerProxy
Expand Down
3 changes: 3 additions & 0 deletions WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.m
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ + (void)swizzleSetEventLoopHasIdled {
[FBLogger log:@"Could not find method -[XCUIApplicationProcess setEventLoopHasIdled:]"];
return;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcast-function-type-strict"
orig_set_event_loop_has_idled = (void(*)(id, SEL, BOOL)) method_getImplementation(original);
#pragma clang diagnostic pop
Method replace = class_getClassMethod([XCUIApplicationProcessDelay class], @selector(setEventLoopHasIdled:));
method_setImplementation(original, method_getImplementation(replace));
isSwizzled = YES;
Expand Down

0 comments on commit 2ccc436

Please sign in to comment.