Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions WebDriverAgent.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
641EE5D92240C5CA00173FCB /* XCUIElement+FBPickerWheel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7136A4781E8918E60024FC3D /* XCUIElement+FBPickerWheel.m */; };
641EE5DA2240C5CA00173FCB /* XCUIApplicationProcessDelay.m in Sources */ = {isa = PBXBuildFile; fileRef = 6385F4A5220A40760095BBDB /* XCUIApplicationProcessDelay.m */; };
641EE5DB2240C5CA00173FCB /* FBXPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 711084431DA3AA7500F913D6 /* FBXPath.m */; };
71B2E0042733FB970074B004 /* FBXPathExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B2E0022733FB970074B002 /* FBXPathExtensions.m */; };
641EE5DC2240C5CA00173FCB /* XCUIApplication+FBAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = 719CD8FB2126C88B00C7D0C2 /* XCUIApplication+FBAlert.m */; };
641EE5DE2240C5CA00173FCB /* XCUIApplication+FBTouchAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BD20721F86116100B36EC2 /* XCUIApplication+FBTouchAction.m */; };
641EE5DF2240C5CA00173FCB /* FBWebServer.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB78D1CAEDF0C008C271F /* FBWebServer.m */; };
Expand Down Expand Up @@ -316,6 +317,7 @@
64E3502F2AC0B6FE005F3ACB /* NSDictionary+FBUtf8SafeDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 716F0D9F2A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.h */; };
711084441DA3AA7500F913D6 /* FBXPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 711084421DA3AA7500F913D6 /* FBXPath.h */; settings = {ATTRIBUTES = (Public, ); }; };
711084451DA3AA7500F913D6 /* FBXPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 711084431DA3AA7500F913D6 /* FBXPath.m */; };
71B2E0062733FB970074B006 /* FBXPathExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B2E0022733FB970074B002 /* FBXPathExtensions.m */; };
7119097C2152580600BA3C7E /* XCUIScreen.h in Headers */ = {isa = PBXBuildFile; fileRef = 7119097B2152580600BA3C7E /* XCUIScreen.h */; settings = {ATTRIBUTES = (Public, ); }; };
7119E1EC1E891F8600D0B125 /* FBPickerWheelSelectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7119E1EB1E891F8600D0B125 /* FBPickerWheelSelectTests.m */; };
711CD03425ED1106001C01D2 /* XCUIScreenDataSource-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 711CD03325ED1106001C01D2 /* XCUIScreenDataSource-Protocol.h */; };
Expand Down Expand Up @@ -976,6 +978,8 @@
64B26509228CE4FF002A5025 /* FBTVNavigationTracker-Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FBTVNavigationTracker-Private.h"; sourceTree = "<group>"; };
711084421DA3AA7500F913D6 /* FBXPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXPath.h; sourceTree = "<group>"; };
711084431DA3AA7500F913D6 /* FBXPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBXPath.m; sourceTree = "<group>"; };
71B2E0012733FB970074B001 /* FBXPathExtensions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBXPathExtensions.h; sourceTree = "<group>"; };
71B2E0022733FB970074B002 /* FBXPathExtensions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBXPathExtensions.m; sourceTree = "<group>"; };
7119097B2152580600BA3C7E /* XCUIScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XCUIScreen.h; sourceTree = "<group>"; };
7119E1EB1E891F8600D0B125 /* FBPickerWheelSelectTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBPickerWheelSelectTests.m; sourceTree = "<group>"; };
711CD03325ED1106001C01D2 /* XCUIScreenDataSource-Protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCUIScreenDataSource-Protocol.h"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2000,9 +2004,11 @@
714D88CA2733FB970074A925 /* FBXMLGenerationOptions.h */,
714D88CB2733FB970074A925 /* FBXMLGenerationOptions.m */,
712A0C861DA3E55D007D02E5 /* FBXPath-Private.h */,
711084421DA3AA7500F913D6 /* FBXPath.h */,
711084431DA3AA7500F913D6 /* FBXPath.m */,
EE6B64FB1D0F86EF00E85F5D /* XCTestPrivateSymbols.h */,
711084421DA3AA7500F913D6 /* FBXPath.h */,
711084431DA3AA7500F913D6 /* FBXPath.m */,
71B2E0012733FB970074B001 /* FBXPathExtensions.h */,
71B2E0022733FB970074B002 /* FBXPathExtensions.m */,
EE6B64FB1D0F86EF00E85F5D /* XCTestPrivateSymbols.h */,
EE6B64FC1D0F86EF00E85F5D /* XCTestPrivateSymbols.m */,
633E904A220DEE7F007CADF9 /* XCUIApplicationProcessDelay.h */,
6385F4A5220A40760095BBDB /* XCUIApplicationProcessDelay.m */,
Expand Down Expand Up @@ -3156,6 +3162,7 @@
641EE5D92240C5CA00173FCB /* XCUIElement+FBPickerWheel.m in Sources */,
641EE5DA2240C5CA00173FCB /* XCUIApplicationProcessDelay.m in Sources */,
641EE5DB2240C5CA00173FCB /* FBXPath.m in Sources */,
71B2E0042733FB970074B004 /* FBXPathExtensions.m in Sources */,
71C8E55425399A6B008572C1 /* XCUIApplication+FBQuiescence.m in Sources */,
641EE5DC2240C5CA00173FCB /* XCUIApplication+FBAlert.m in Sources */,
641EE70F2240CE4800173FCB /* FBTVNavigationTracker.m in Sources */,
Expand Down Expand Up @@ -3277,6 +3284,7 @@
6385F4A7220A40760095BBDB /* XCUIApplicationProcessDelay.m in Sources */,
71A5C67529A4F39600421C37 /* XCTIssue+FBPatcher.m in Sources */,
711084451DA3AA7500F913D6 /* FBXPath.m in Sources */,
71B2E0062733FB970074B006 /* FBXPathExtensions.m in Sources */,
719CD8FD2126C88B00C7D0C2 /* XCUIApplication+FBAlert.m in Sources */,
13DE7A45287C2A8D003243C6 /* FBXCAccessibilityElement.m in Sources */,
641EE70E2240CE4800173FCB /* FBTVNavigationTracker.m in Sources */,
Expand Down
5 changes: 5 additions & 0 deletions WebDriverAgentLib/Utilities/FBXPath-Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ NS_ASSUME_NONNULL_BEGIN
document:(xmlDocPtr)doc
contextNode:(nullable xmlNodePtr)contextNode;

+ (xmlXPathObjectPtr)evaluate:(NSString *)xpathQuery
document:(xmlDocPtr)doc
contextNode:(nullable xmlNodePtr)contextNode
errorMessage:(NSString * _Nullable * _Nullable)errorMessage;

@end

NS_ASSUME_NONNULL_END
40 changes: 36 additions & 4 deletions WebDriverAgentLib/Utilities/FBXPath.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#import "FBLogger.h"
#import "FBMacros.h"
#import "FBXMLGenerationOptions.h"
#import "FBXPathExtensions.h"
#import "FBXCElementSnapshotWrapper+Helpers.h"
#import "NSString+FBXMLSafeString.h"
#import "XCUIApplication.h"
Expand Down Expand Up @@ -152,7 +153,17 @@ @implementation FBXPath

+ (id)throwException:(NSString *)name forQuery:(NSString *)xpathQuery
{
NSString *reason = [NSString stringWithFormat:@"Cannot evaluate results for XPath expression \"%@\"", xpathQuery];
return [self throwException:name forQuery:xpathQuery detail:nil];
}

+ (id)throwException:(NSString *)name forQuery:(NSString *)xpathQuery detail:(nullable NSString *)detail
{
NSString *reason;
if (nil != detail) {
reason = [NSString stringWithFormat:@"Cannot evaluate results for XPath expression \"%@\": %@", xpathQuery, detail];
} else {
reason = [NSString stringWithFormat:@"Cannot evaluate results for XPath expression \"%@\"", xpathQuery];
}
@throw [NSException exceptionWithName:name reason:reason userInfo:@{}];
return nil;
}
Expand Down Expand Up @@ -284,16 +295,18 @@ + (nullable NSString *)xmlStringWithRootElement:(id<FBElement>)root
contextNode = nodeSet->nodeTab[0];
}
}
NSString *evaluationError = nil;
xmlXPathObjectPtr queryResult = [self evaluate:xpathQuery
document:doc
contextNode:contextNode];
contextNode:contextNode
errorMessage:&evaluationError];
if (NULL != contextNodeQueryResult) {
xmlXPathFreeObject(contextNodeQueryResult);
}
if (NULL == queryResult) {
xmlFreeTextWriter(writer);
xmlFreeDoc(doc);
return [self throwException:FBInvalidXPathException forQuery:xpathQuery];
return [self throwException:FBInvalidXPathException forQuery:xpathQuery detail:evaluationError];
}

NSArray *matchingSnapshots = [self collectMatchingSnapshots:queryResult->nodesetval
Expand Down Expand Up @@ -435,6 +448,14 @@ + (int)xmlRepresentationWithRootElement:(id<FBXCElementSnapshot>)root
+ (xmlXPathObjectPtr)evaluate:(NSString *)xpathQuery
document:(xmlDocPtr)doc
contextNode:(nullable xmlNodePtr)contextNode
{
return [self evaluate:xpathQuery document:doc contextNode:contextNode errorMessage:nil];
}

+ (xmlXPathObjectPtr)evaluate:(NSString *)xpathQuery
document:(xmlDocPtr)doc
contextNode:(nullable xmlNodePtr)contextNode
errorMessage:(NSString * _Nullable * _Nullable)errorMessage
{
xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
if (NULL == xpathCtx) {
Expand All @@ -443,10 +464,21 @@ + (xmlXPathObjectPtr)evaluate:(NSString *)xpathQuery
}
xpathCtx->node = NULL == contextNode ? doc->children : contextNode;

FBXPathExtensions *extensions = [FBXPathExtensions new];
[extensions registerFunctionsWithContext:xpathCtx];

xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression((const xmlChar *)[xpathQuery UTF8String], xpathCtx);
if (NULL == xpathObj) {
NSString *detail = extensions.lastEvaluationError;
if (NULL != errorMessage) {
*errorMessage = detail;
}
if (nil != detail) {
[FBLogger logFmt:@"Failed to evaluate XPath query \"%@\": %@", xpathQuery, detail];
} else {
[FBLogger logFmt:@"Failed to invoke libxml2>xmlXPathEvalExpression for XPath query \"%@\"", xpathQuery];
}
xmlXPathFreeContext(xpathCtx);
[FBLogger logFmt:@"Failed to invoke libxml2>xmlXPathEvalExpression for XPath query \"%@\"", xpathQuery];
return NULL;
}
xmlXPathFreeContext(xpathCtx);
Expand Down
40 changes: 40 additions & 0 deletions WebDriverAgentLib/Utilities/FBXPathExtensions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

#import <Foundation/Foundation.h>

#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpadded"
#endif

#import <libxml/xpath.h>

#ifdef __clang__
#pragma clang diagnostic pop
#endif

NS_ASSUME_NONNULL_BEGIN

@interface FBXPathExtensions : NSObject

/**
Registers XPath 2-compatible extension functions on the given libxml2 context.
*/
- (void)registerFunctionsWithContext:(xmlXPathContextPtr)xpathCtx;

/**
Human-readable message for the most recent XPath extension evaluation failure on this instance,
for example an invalid regular expression pattern or flags. Nil when no extension error has occurred.
Scoped to the libxml2 context this instance is registered with; each evaluation should use its own instance.
*/
@property (nonatomic, nullable, readonly, copy) NSString *lastEvaluationError;

@end

NS_ASSUME_NONNULL_END
Loading
Loading