├── README.md └── XCTestWD-master ├── .gitignore ├── .jshintignore ├── .jshintrc ├── .npmignore ├── .travis.yml ├── CONTRIBUTING.md ├── Cartfile ├── LICENSE ├── Makefile ├── README.md ├── XCTestWD ├── XCTestWD-Info.plist ├── XCTestWD.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ ├── XCTestWD.xcscheme │ │ ├── XCTestWDAggregation.xcscheme │ │ ├── XCTestWDUITests.xcscheme │ │ └── XCTestWDUnitTest.xcscheme ├── XCTestWD │ ├── Info.plist │ ├── PrivateHeaders │ │ ├── CDStructures.h │ │ ├── Macaca │ │ │ ├── NSPredicate+XCTestWD.h │ │ │ ├── NSPredicate+XCTestWD.m │ │ │ ├── XCTestWDApplication.h │ │ │ ├── XCTestWDApplication.m │ │ │ ├── XCTestWDImplementationFailureHoldingProxy.h │ │ │ └── XCTestWDImplementationFailureHoldingProxy.m │ │ ├── XCAXClient_iOS.h │ │ ├── XCDebugLogDelegate-Protocol.h │ │ ├── XCElementSnapshot.h │ │ ├── XCRuntimeUtils.h │ │ ├── XCRuntimeUtils.m │ │ ├── XCTRunnerDaemonSession.h │ │ ├── XCTestCase.h │ │ ├── XCTestDaemonsProxy.h │ │ ├── XCTestDaemonsProxy.m │ │ ├── XCTestDriver.h │ │ ├── XCTestDriverInterface-Protocol.h │ │ ├── XCTestManager_IDEInterface-Protocol.h │ │ ├── XCTestManager_ManagerInterface-Protocol.h │ │ ├── XCTestManager_TestsInterface-Protocol.h │ │ ├── XCTestPrivateSymbols.h │ │ ├── XCTestPrivateSymbols.m │ │ ├── XCUIApplication.h │ │ ├── XCUICoordinate.h │ │ ├── XCUIElement.h │ │ ├── XCUIElementQuery.h │ │ └── _XCTestCaseImplementation.h │ ├── Server │ │ ├── Controllers │ │ │ ├── Monkey.swift │ │ │ ├── MonkeyUIAutomation.swift │ │ │ ├── MonkeyXCTest.swift │ │ │ ├── MonkeyXCTestPrivate.swift │ │ │ ├── Random.swift │ │ │ ├── XCTestWDActionsController.swift │ │ │ ├── XCTestWDAlertController.swift │ │ │ ├── XCTestWDContextController.swift │ │ │ ├── XCTestWDElementController.swift │ │ │ ├── XCTestWDExecuteController.swift │ │ │ ├── XCTestWDKeysController.swift │ │ │ ├── XCTestWDMonkeyController.swift │ │ │ ├── XCTestWDScreenshotController.swift │ │ │ ├── XCTestWDSessionController.swift │ │ │ ├── XCTestWDSourceController.swift │ │ │ ├── XCTestWDStatusController.swift │ │ │ ├── XCTestWDTimeoutController.swift │ │ │ ├── XCTestWDTitleController.swift │ │ │ ├── XCTestWDUrlController.swift │ │ │ └── XCTestWDWindowController.swift │ │ ├── Modules │ │ │ ├── Extensions │ │ │ │ ├── XCTestWDFindElementUtils.swift │ │ │ │ ├── XCTestWDMathUtils.swift │ │ │ │ └── XCTestWDXPath.swift │ │ │ ├── Utils │ │ │ │ ├── XCTestWDAccessibility.swift │ │ │ │ └── XCTestWDApplicationTree.swift │ │ │ ├── XCTestWDAlert.swift │ │ │ ├── XCTestWDErrors.swift │ │ │ ├── XCTestWDReponse.swift │ │ │ ├── XCTestWDSession.swift │ │ │ ├── XCTestWDStatus.swift │ │ │ └── XCUIElementTypeTransformer.swift │ │ ├── XCTestWDController.swift │ │ ├── XCTestWDDispatch.swift │ │ ├── XCTestWDFailureProofTestCase.swift │ │ ├── XCTestWDMonkey.swift │ │ └── XCTestWDServer.swift │ └── XCTestWD.h ├── XCTestWDUITests │ ├── Info.plist │ └── XCTestWDRunner.swift ├── XCTestWDUnitTest │ ├── ControllerTests │ │ ├── XCTestWDScreenShotControllerTest.swift │ │ ├── XCTestWDSourceControllerTests.swift │ │ ├── XCTestWDTitleControllerTests.swift │ │ ├── XCTestWDUrlControllerTests.swift │ │ └── XCTestWDWindowControllerTests.swift │ ├── Info.plist │ ├── XCTestWDSessionTest.swift │ └── XCTestWDUnitTestBase.swift ├── curlTests.sh └── libxml2 │ └── libxml2-fuzi.h ├── index.html ├── index.js ├── lib ├── helper.js ├── logger.js ├── proxy.js ├── xctest-client.js └── xctestwd.js ├── package.json ├── scripts ├── aggregate.sh ├── install.js └── integration-testing.sh └── test ├── mocha.opts └── xctest.test.js /README.md: -------------------------------------------------------------------------------- 1 | # FastMonkey 2 | 3 | > A Swift implementation of Monkey TEST(Non-Stub) for iOS that runs on Simulator/iOS devices. 4 | 5 | 1.0.0.1002 支持 6 | 1. 非插桩monkey点击事件 7 | 2. app后台或退出检测 8 | 3. 基于控件点击事件 9 | 4. 自定义业务序列事件 10 | 11 | 12 | - homepage : https://testerhome.com/topics/9524 13 | 14 | ## 1. Requirements 15 | 16 | - XCode version 8.3.0 and above. 17 | - iOS version 9.0 and above. 18 | 19 | ## 2. Starting 20 | 21 | FastMonkey can be either started with XCode IDE or via simple xcodebuild command line. 22 | 23 | ### 2.1. Using Xcode 24 | 25 | Download the project and open the XCode project, checkout the scheme `XCTestWDUITests` and run the test case `XCTextWDRunner` 26 | 27 | ### 2.2. Using XcodeBuild 28 | 29 | Open the terminal, go to the directory where contains `XCTestWD.xcodeproj` file and execute the following command: 30 | 31 | ``` bash 32 | # 33 | #Change the port number to override the default port 34 | # 35 | $ xcodebuild -project XCTestWD.xcodeproj \ 36 | -scheme XCTestWDUITests \ 37 | -destination 'platform=iOS Simulator,name=iPhone 6' \ 38 | XCTESTWD_PORT=8001 \ 39 | clean test 40 | ``` 41 | 42 | To execute Monkey for iOS device, run the following command: 43 | 44 | ``` bash 45 | # 46 | #Change the port number to override the default port 47 | #Specify the device name 48 | # 49 | $ iproxy 8001 8001 50 | 51 | $ xcodebuild -project XCTestWD.xcodeproj -scheme XCTestWDUITests -destination 'platform=iOS,name=(your device name)' XCTESTWD_PORT=8001 clean test 52 | # 53 | # Now server is started and listening in 8001 54 | # To start Monkey run: 55 | 56 | $curl -X POST -H "Content-Type:application/json" -d "{\"desiredCapabilities\":{\"deviceName\":\"xxxx\",\"platformName\":\"iOS\", \"bundleId\":\"com.PandaTV.Live-iPhone\",\"autoAcceptAlerts\":\"false\"}}" http://127.0.0.1:8001/wd/hub/monkey 57 | 58 | 59 | ``` 60 | -------------------------------------------------------------------------------- /XCTestWD-master/.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | # Normal 20 | .project 21 | .settings 22 | node_modules/ 23 | logs/ 24 | Carthage/ 25 | Cartfile.resolved 26 | UserInterfaceState.xcuserstate 27 | .*.sw[a-z] 28 | .sw? 29 | *.un~ 30 | .DS_Store 31 | node_modules 32 | npm-debug.log 33 | .idea/* 34 | Thumbs.db 35 | coverage/ 36 | .project 37 | logs/ 38 | *.un~ 39 | -------------------------------------------------------------------------------- /XCTestWD-master/.jshintignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | node_modules/ 3 | coverage/ 4 | build/ 5 | assets/ 6 | dist/ 7 | XCTestWD/ 8 | -------------------------------------------------------------------------------- /XCTestWD-master/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "indent": 2, 3 | "latedef": "nofunc", 4 | "newcap": true, 5 | "curly": true, 6 | "eqeqeq": true, 7 | "eqnull": true, 8 | "strict": true, 9 | "undef": true, 10 | "unused": true, 11 | "laxcomma": false, 12 | "asi": false, 13 | "boss": false, 14 | "expr": true, 15 | "sub": true, 16 | "quotmark": "single", 17 | "loopfunc": false, 18 | "lastsemic": true, 19 | "funcscope": false, 20 | "esnext": true, 21 | "noyield": true, 22 | "browser": true, 23 | "nonstandard": true, 24 | "devel": true, 25 | "node": true, 26 | "mocha": true, 27 | "validthis": true, 28 | "globals": { 29 | "define": false 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /XCTestWD-master/.npmignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | *.xcworkspace 12 | !default.xcworkspace 13 | xcuserdata 14 | profile 15 | *.moved-aside 16 | DerivedData 17 | .idea/ 18 | # Normal 19 | .project 20 | .settings 21 | node_modules/ 22 | logs/ 23 | Cartfile.resolved 24 | UserInterfaceState.xcuserstate 25 | Cartfile 26 | XCTestWD/build 27 | *.un~ 28 | coverage.html 29 | lib-cov/ 30 | node_modules 31 | .travis.yml 32 | .drone.yml 33 | examples/ 34 | Makefile 35 | .jshintrc 36 | .jshintignore 37 | coverage/ 38 | logs/ 39 | -------------------------------------------------------------------------------- /XCTestWD-master/.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode8.3 3 | script: 4 | - make build 5 | -------------------------------------------------------------------------------- /XCTestWD-master/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to XCTestWD 2 | 3 | We love pull requests from everyone. 4 | 5 | ## Link Global To Local 6 | 7 | ```bash 8 | $ cd path/to/macaca-ios 9 | $ npm link path/to/XCTestWD 10 | # now project XCTestWD is linked to macaca-ios 11 | ``` 12 | 13 | ## Run with XCode 14 | 15 | ```bash 16 | $ open ./XCTestWD/XCTestWD.xcodeproj 17 | # run test(command + u) in XCTestWDUITests schema 18 | # ./XCTestWD/curlTests.sh is some useful restful testing scripts 19 | ``` 20 | -------------------------------------------------------------------------------- /XCTestWD-master/Cartfile: -------------------------------------------------------------------------------- 1 | github "httpswift/swifter" == 1.4.3 2 | github "SwiftyJSON/SwiftyJSON" 3 | github "cezheng/Fuzi" ~> 2.1.0 4 | github "tadija/AEXML" == 4.2.2 5 | github "CocoaLumberjack/CocoaLumberjack" 6 | github "Quick/Nimble" 7 | -------------------------------------------------------------------------------- /XCTestWD-master/LICENSE: -------------------------------------------------------------------------------- 1 | MIT LICENSE 2 | 3 | Copyright (c) 2017 Alibaba Group Holding Limited and other contributors. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /XCTestWD-master/Makefile: -------------------------------------------------------------------------------- 1 | install: 2 | carthage update --platform iOS --verbose 3 | .PHONY: coverage 4 | -------------------------------------------------------------------------------- /XCTestWD-master/README.md: -------------------------------------------------------------------------------- 1 | # XCTestWD 2 | 3 | [![NPM version][npm-image]][npm-url] 4 | [![node version][node-image]][node-url] 5 | [![npm download][download-image]][download-url] 6 | [![CircleCI](https://circleci.com/gh/macacajs/XCTestWD.svg?style=svg)](https://circleci.com/gh/macacajs/XCTestWD) 7 | 8 | [npm-image]: https://img.shields.io/npm/v/xctestwd.svg?style=flat-square 9 | [npm-url]: https://npmjs.org/package/xctestwd 10 | [node-image]: https://img.shields.io/badge/node.js-%3E=_8-green.svg?style=flat-square 11 | [node-url]: http://nodejs.org/download/ 12 | [download-image]: https://img.shields.io/npm/dm/xctestwd.svg?style=flat-square 13 | [download-url]: https://npmjs.org/package/xctestwd 14 | 15 | > Swift implementation of WebDriver server for iOS that runs on Simulator/iOS devices. 16 | 17 | ## 1. Requirements 18 | 19 | - XCode version 9.0 and above. 20 | - iOS version 11.0 and above. (there is significant change on XCUITest interfaces and system private headers, hence we decide to support newest OS version only) 21 | 22 | ## 2. Starting XCTestWD 23 | 24 | XCTestWD can be either started with XCode IDE or via simple xcodebuild command line. By default, the webdriver agent occupies port `8001`. You can override the default port in XCode by searching `XCTESTWD_PORT` under project build settings. Alternatively, it can also be overrided when you execute command line method as specified in `2.2. Using Xcodebuild` 25 | 26 | ### 2.1. Using Xcode 27 | 28 | Download the project and open the XCode project, checkout the scheme `XCTestWDUITests` and run the test case `XCTextWDRunner` 29 | 30 | ### 2.2. Using XcodeBuild 31 | 32 | Open the terminal, go to the directory where contains `XCTestWD.xcodeproj` file and execute the following command: 33 | 34 | ```bash 35 | # 36 | # Change the port number to override the default port 37 | # 38 | $ xcodebuild -project XCTestWD.xcodeproj \ 39 | -scheme XCTestWDUITests \ 40 | -destination 'platform=iOS Simulator,name=iPhone 6' \ 41 | XCTESTWD_PORT=8001 \ 42 | clean test 43 | ``` 44 | 45 | To execute for iOS device, run the following command: 46 | 47 | ```bash 48 | # 49 | # Change the port number to override the default port 50 | # Specify the device name 51 | # 52 | $ xcodebuild -project XCTestWD.xcodeproj \ 53 | -scheme XCTestWDUITests \ 54 | -destination 'platform=iOS,name=(your device name)' \ 55 | XCTESTWD_PORT=8001 \ 56 | clean test 57 | ``` 58 | **Note:** For versions above wxtestwd 2.0.0, please install ideviceinstaller for supporting real device testing 59 | 60 | 61 | ## 3. Element Types 62 | 63 | In the current protocol, element strings for each `XCUIElementType` are generated based on the existing mapping in [reference/xctest/xcuielementtype](https://developer.apple.com/reference/xctest/xcuielementtype) 64 | 65 | 66 | ## 4. Common Issues 67 | 68 | ### 4.1 Socket hangup error 69 | 70 | Socket Hangup Error happens in the following two scenarios:
71 | - **Case 1**
72 | Issue:
73 | When you have some existing XCTestWD instances running and creating new ones.
74 | Solution:
75 | verify whether ideviceinstaller and xcrun is properly working on your device and simulator.
76 | Hint:
77 | https://github.com/libimobiledevice/ideviceinstaller/issues/48 78 | 79 | - **Case 2**
80 | Issue:
81 | When you have started the XCTestWD instance properly but fails in middle of a testing process.
82 | Solution:
83 | See the Macaca Service log to checkout which command leads the error. With detailed and comprehensive log information, please submit an issue to us.
84 | Optional:
85 | If you cannot get anything from macaca server log, open the XCTestWD in your node installation path and attatch for debugging on process 'XCTRunnerUITests-Runner'.
86 | 87 | **Additional Info**
88 | `The project path is at`

89 | ``` 90 | cd "$(npm root -g)/macaca-ios/node_modules/xctestwd" 91 | ``` 92 | 93 | `Set up the linebreak for swift error and exceptions:`

94 | 2017-12-14 10 56 33 95 | 96 | `Run your command regularly, once the driver has been initialized, attach the process:`

97 | 2017-12-14 10 55 14 98 | 99 | ### 4.2 Swift modules fails to compile 100 | 101 | Check carthage installation 102 | 103 | ### 4.3 Debug info 104 | 105 | Now XCTestWD supports gathering debug log into log files which is stored in "Your-App-Sandbox-Root"/Documents/Logs dir. For real devices, you can connect to itunes and choose backup for `XCTestWDUITests` and get the debug log. For iOS simulators, the log file is in your computer's simulator app directory like: 106 | 107 | ``` 108 | "/Users/${user-name}/Library/Developer/CoreSimulator/Devices \ 109 | /${device-id}/data/Containers/Data/Application/${app-id}/Documents/Logs" 110 | ``` 111 | 112 | You can use `xcrun simctl list` to get the id of the booted device. 113 | 114 | 115 | 116 | ## Contributors 117 | 118 | |[
SamuelZhaoY](https://github.com/SamuelZhaoY)
|[
xudafeng](https://github.com/xudafeng)
|[
holy-lousie](https://github.com/holy-lousie)
|[
adudurant](https://github.com/adudurant)
|[
Chan-Chun](https://github.com/Chan-Chun)
|[
gurisxie](https://github.com/gurisxie)
119 | | :---: | :---: | :---: | :---: | :---: | :---: | 120 | |[
fengguochao](https://github.com/fengguochao)
|[
butterflyingdog](https://github.com/butterflyingdog)
121 | 122 | This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto upated at `Mon Aug 13 2018 13:47:20 GMT+0800`. 123 | 124 | 125 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD.xcodeproj/xcshareddata/xcschemes/XCTestWD.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 47 | 48 | 54 | 55 | 56 | 57 | 58 | 59 | 65 | 66 | 72 | 73 | 74 | 75 | 77 | 78 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD.xcodeproj/xcshareddata/xcschemes/XCTestWDAggregation.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 47 | 48 | 54 | 55 | 56 | 57 | 58 | 59 | 65 | 66 | 72 | 73 | 74 | 75 | 77 | 78 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD.xcodeproj/xcshareddata/xcschemes/XCTestWDUITests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD.xcodeproj/xcshareddata/xcschemes/XCTestWDUnitTest.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 16 | 18 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 41 | 42 | 43 | 44 | 50 | 51 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/CDStructures.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | #pragma mark Blocks 8 | 9 | typedef void (^CDUnknownBlockType)(void); // return type and parameters are unknown 10 | 11 | typedef struct { 12 | unsigned int _field1; 13 | unsigned int _field2; 14 | unsigned int _field3; 15 | unsigned int _field4; 16 | unsigned int _field5; 17 | unsigned int _field6; 18 | unsigned int _field7; 19 | } CDStruct_a561fd19; 20 | 21 | typedef struct { 22 | unsigned short _field1; 23 | unsigned short _field2; 24 | unsigned short _field3[1]; 25 | } CDStruct_27a325c0; 26 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/Macaca/NSPredicate+XCTestWD.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSPredicate+XCTestWD.h 3 | // XCTestWD 4 | // 5 | // Created by SamuelZhaoY on 18/8/18. 6 | // Copyright © 2018 XCTestWD. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSPredicate (XCTestWD) 12 | 13 | // utility method for providing xctestwd predicates 14 | + (instancetype)xctestWDPredicateWithFormat:(NSString *)predicateFormat; 15 | 16 | + (instancetype)xctestWDformatSearchPredicate:(NSPredicate *)input; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/Macaca/NSPredicate+XCTestWD.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSPredicate+XCTestWD.m 3 | // XCTestWD 4 | // 5 | // Created by SamuelZhaoY on 18/8/18. 6 | // Copyright © 2018 XCTestWD. All rights reserved. 7 | // 8 | 9 | #import "NSPredicate+XCTestWD.h" 10 | 11 | @implementation NSPredicate(XCTestWD) 12 | 13 | + (instancetype)xctestWDPredicateWithFormat:(NSString *)predicateFormat 14 | { 15 | NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateFormat arguments:nil]; 16 | NSPredicate *hackPredicate = [NSPredicate predicateWithFormat:self.forceResolvePredicateString]; 17 | return [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate, hackPredicate]]; 18 | } 19 | 20 | + (NSString *)forceResolvePredicateString 21 | { 22 | return @"1 == 1 or identifier == 0 or frame == 0 or value == 0 or title == 0 or label == 0 or elementType == 0 or enabled == 0 or placeholderValue == 0"; 23 | } 24 | 25 | + (instancetype)xctestWDPredicateWithPredicate:(NSPredicate *)original comparisonModifier:(NSPredicate *(^)(NSComparisonPredicate *))comparisonModifier 26 | { 27 | if ([original isKindOfClass:NSCompoundPredicate.class]) { 28 | NSCompoundPredicate *compPred = (NSCompoundPredicate *)original; 29 | NSMutableArray *predicates = [NSMutableArray array]; 30 | for (NSPredicate *predicate in [compPred subpredicates]) { 31 | if ([predicate.predicateFormat.lowercaseString isEqualToString:NSPredicate.forceResolvePredicateString.lowercaseString]) { 32 | // Do not translete this predicate 33 | [predicates addObject:predicate]; 34 | continue; 35 | } 36 | NSPredicate *newPredicate = [self.class xctestWDPredicateWithPredicate:predicate comparisonModifier:comparisonModifier]; 37 | if (nil != newPredicate) { 38 | [predicates addObject:newPredicate]; 39 | } 40 | } 41 | return [[NSCompoundPredicate alloc] initWithType:compPred.compoundPredicateType 42 | subpredicates:predicates]; 43 | } 44 | if ([original isKindOfClass:NSComparisonPredicate.class]) { 45 | return comparisonModifier((NSComparisonPredicate *)original); 46 | } 47 | return original; 48 | } 49 | 50 | + (instancetype)xctestWDformatSearchPredicate:(NSPredicate *)input 51 | { 52 | return [self.class xctestWDPredicateWithPredicate:input comparisonModifier:^NSPredicate *(NSComparisonPredicate *cp) { 53 | return [NSComparisonPredicate predicateWithLeftExpression:[cp leftExpression] 54 | rightExpression:[cp rightExpression] 55 | modifier:cp.comparisonPredicateModifier 56 | type:cp.predicateOperatorType 57 | options:cp.options]; 58 | }]; 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/Macaca/XCTestWDApplication.h: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDApplication.h 3 | // XCTestWDUITests 4 | // 5 | // Created by zhaoy on 24/9/17. 6 | // Copyright © 2017 XCTestWD. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "XCUIApplication.h" 11 | 12 | @interface XCTestWDApplication : NSObject 13 | 14 | + (XCUIApplication*)activeApplication; 15 | 16 | + (XCUIApplication*)createByPID:(pid_t)pid; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/Macaca/XCTestWDApplication.m: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDApplication.m 3 | // XCTestWDUITests 4 | // 5 | // Created by zhaoy on 24/9/17. 6 | // Copyright © 2017 XCTestWD. All rights reserved. 7 | // 8 | 9 | #import "XCTestWDApplication.h" 10 | #import "XCUIApplication.h" 11 | #import "XCAXClient_iOS.h" 12 | 13 | @implementation XCTestWDApplication 14 | 15 | + (XCUIApplication*)activeApplication 16 | { 17 | id activeApplicationElement = ((NSArray*)[[XCAXClient_iOS sharedClient] activeApplications]).lastObject; 18 | 19 | if (!activeApplicationElement) { 20 | activeApplicationElement = ((XCAXClient_iOS*)[XCAXClient_iOS sharedClient]).systemApplication; 21 | } 22 | 23 | XCUIApplication* application = [XCTestWDApplication createByPID:[[activeApplicationElement valueForKey:@"processIdentifier"] intValue]]; 24 | 25 | if (application.state != XCUIApplicationStateRunningForeground) { 26 | application = [[XCUIApplication alloc] initPrivateWithPath:nil bundleID:@"com.apple.springboard"]; 27 | } 28 | 29 | [application query]; 30 | return application; 31 | } 32 | 33 | + (XCUIApplication*)createByPID:(pid_t)pid 34 | { 35 | if ([XCUIApplication respondsToSelector:@selector(appWithPID:)]) { 36 | return [XCUIApplication appWithPID:pid]; 37 | } 38 | 39 | return [XCUIApplication applicationWithPID:pid]; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/Macaca/XCTestWDImplementationFailureHoldingProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDImplementationFailureHoldingProxy.h 3 | // XCTestWD 4 | // 5 | // Created by SamuelZhaoY on 3/10/18. 6 | // Copyright © 2018 XCTestWD. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @class _XCTestCaseImplementation; 14 | /** 15 | Class that can be used to proxy existing _XCTestCaseImplementation and 16 | prevent currently running test from being terminated on any XCTest failure 17 | */ 18 | @interface XCTestWDImplementationFailureHoldingProxy : NSObject 19 | 20 | /** 21 | Constructor for given existing _XCTestCaseImplementation instance 22 | */ 23 | + (_XCTestCaseImplementation *)proxyWithXCTestCaseImplementation:(_XCTestCaseImplementation *)internalImplementation; 24 | 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/Macaca/XCTestWDImplementationFailureHoldingProxy.m: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDImplementationFailureHoldingProxy.m 3 | // XCTestWD 4 | // 5 | // Created by SamuelZhaoY on 3/10/18. 6 | // Copyright © 2018 XCTestWD. All rights reserved. 7 | // 8 | 9 | #import "XCTestWDImplementationFailureHoldingProxy.h" 10 | #import "_XCTestCaseImplementation.h" 11 | 12 | @interface XCTestWDImplementationFailureHoldingProxy() 13 | 14 | @property (nonatomic, strong) _XCTestCaseImplementation *internalImplementation; 15 | 16 | @end 17 | 18 | @implementation XCTestWDImplementationFailureHoldingProxy 19 | 20 | + (_XCTestCaseImplementation *)proxyWithXCTestCaseImplementation:(_XCTestCaseImplementation *)internalImplementation 21 | { 22 | XCTestWDImplementationFailureHoldingProxy *proxy = [super alloc]; 23 | proxy.internalImplementation = internalImplementation; 24 | return (_XCTestCaseImplementation *)proxy; 25 | } 26 | 27 | - (id)forwardingTargetForSelector:(SEL)aSelector 28 | { 29 | return self.internalImplementation; 30 | } 31 | 32 | // This will prevent test from quiting on app crash or any other test failure 33 | - (BOOL)shouldHaltWhenReceivesControl 34 | { 35 | return NO; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCAXClient_iOS.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | #import "CDStructures.h" 8 | #import 9 | 10 | @class NSMutableDictionary; 11 | @class XCAccessibilityElement; 12 | 13 | @interface XCAXClient_iOS : NSObject 14 | { 15 | NSMutableDictionary *_userTestingNotificationHandlers; 16 | NSMutableDictionary *_cacheAccessibilityLoadedValuesForPIDs; 17 | unsigned long long *_alertNotificationCounter; 18 | } 19 | @property double AXTimeout; 20 | 21 | + (id)sharedClient; 22 | - (BOOL)_setAXTimeout:(double)arg1 error:(id *)arg2; 23 | - (NSData *)screenshotData; 24 | - (BOOL)performAction:(int)arg1 onElement:(id)arg2 value:(id)arg3 error:(id *)arg4; 25 | - (id)parameterizedAttributeForElement:(id)arg1 attribute:(id)arg2 parameter:(id)arg3; 26 | - (BOOL)setAttribute:(id)arg1 value:(id)arg2 element:(id)arg3 outError:(id *)arg4; 27 | - (id)attributesForElement:(id)arg1 attributes:(id)arg2; 28 | - (id)attributesForElementSnapshot:(id)arg1 attributeList:(id)arg2; 29 | - (id)snapshotForApplication:(id)arg1 attributeList:(id)arg2 parameters:(id)arg3; 30 | - (id)defaultParameters; 31 | - (id)defaultAttributes; 32 | - (void)notifyWhenViewControllerViewDidDisappearReply:(CDUnknownBlockType)arg1; 33 | - (void)notifyWhenViewControllerViewDidAppearReply:(CDUnknownBlockType)arg1; 34 | - (void)notifyWhenNoAnimationsAreActiveForApplication:(id)arg1 reply:(CDUnknownBlockType)arg2; 35 | - (void)notifyWhenEventLoopIsIdleForApplication:(id)arg1 reply:(CDUnknownBlockType)arg2; 36 | - (id)interruptingUIElementAffectingSnapshot:(id)arg1; 37 | - (void)handleAccessibilityNotification:(int)arg1 withPayload:(id)arg2; 38 | - (void)notifyOnNextOccurrenceOfUserTestingEvent:(id)arg1 handler:(CDUnknownBlockType)arg2; 39 | - (void)handleUserTestingNotification:(id)arg1; 40 | - (id)elementAtPoint:(CGPoint)arg1 error:(id *)arg2; 41 | - (BOOL)cachedAccessibilityLoadedValueForPID:(int)arg1; 42 | - (id)activeApplications; 43 | - (id)systemApplication; 44 | - (BOOL)enableFauxCollectionViewCells:(id *)arg1; 45 | - (BOOL)loadAccessibility:(id *)arg1; 46 | - (BOOL)_registerForAXNotification:(int)arg1 error:(id *)arg2; 47 | - (BOOL)_loadAccessibility:(id *)arg1; 48 | - (id)init; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCDebugLogDelegate-Protocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | @class NSString; 8 | 9 | @protocol XCDebugLogDelegate 10 | - (void)logDebugMessage:(NSString *)arg1; 11 | @end 12 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCElementSnapshot.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | #import "CDStructures.h" 8 | 9 | #import 10 | 11 | @class NSArray, NSDictionary, NSString, XCAccessibilityElement, XCUIApplication; 12 | 13 | @interface XCElementSnapshot : NSObject 14 | { 15 | NSString *_identifier; 16 | id _value; 17 | NSString *_placeholderValue; 18 | BOOL _enabled; 19 | BOOL _selected; 20 | BOOL _isMainWindow; 21 | BOOL _hasKeyboardFocus; 22 | BOOL _hasFocus; 23 | XCUIApplication *_application; 24 | unsigned long long _generation; 25 | NSString *_title; 26 | NSString *_label; 27 | unsigned long long _elementType; 28 | long long _horizontalSizeClass; 29 | long long _verticalSizeClass; 30 | XCAccessibilityElement *_accessibilityElement; 31 | XCAccessibilityElement *_parentAccessibilityElement; 32 | XCElementSnapshot *_parent; 33 | NSArray *_children; 34 | unsigned long long _traits; 35 | NSArray *_userTestingAttributes; 36 | NSDictionary *_additionalAttributes; 37 | struct CGRect _frame; 38 | } 39 | @property BOOL hasFocus; // @synthesize hasFocus=_hasFocus; 40 | @property BOOL hasKeyboardFocus; // @synthesize hasKeyboardFocus=_hasKeyboardFocus; 41 | @property(copy) NSDictionary *additionalAttributes; // @synthesize additionalAttributes=_additionalAttributes; 42 | @property(copy) NSArray *userTestingAttributes; // @synthesize userTestingAttributes=_userTestingAttributes; 43 | @property unsigned long long traits; // @synthesize traits=_traits; 44 | @property BOOL isMainWindow; // @synthesize isMainWindow=_isMainWindow; 45 | @property(copy) NSArray *children; // @synthesize children=_children; 46 | @property XCElementSnapshot *parent; // @synthesize parent=_parent; 47 | @property(retain) XCAccessibilityElement *parentAccessibilityElement; // @synthesize parentAccessibilityElement=_parentAccessibilityElement; 48 | @property(retain) XCAccessibilityElement *accessibilityElement; // @synthesize accessibilityElement=_accessibilityElement; 49 | @property(readonly) NSArray *suggestedHitpoints; 50 | @property(readonly) struct CGRect visibleFrame; 51 | @property(readonly) XCElementSnapshot *scrollView; 52 | @property(readonly, copy) NSString *truncatedValueString; 53 | @property(readonly) long long depth; 54 | @property(readonly, copy) XCElementSnapshot *pathFromRoot; 55 | @property(readonly) BOOL isTopLevelTouchBarElement; 56 | @property(readonly) BOOL isTouchBarElement; 57 | @property(readonly, copy) NSString *sparseTreeDescription; 58 | @property(readonly, copy) NSString *compactDescription; 59 | @property(readonly, copy) NSString *pathDescription; 60 | @property(readonly) NSString *recursiveDescriptionIncludingAccessibilityElement; 61 | @property(readonly) NSString *recursiveDescription; 62 | @property(readonly, copy) NSArray *identifiers; 63 | @property(nonatomic) unsigned long long generation; // @synthesize generation=_generation; 64 | @property(nonatomic) XCUIApplication *application; // @synthesize application=_application; 65 | @property(readonly) struct CGPoint hitPointForScrolling; 66 | @property(readonly) struct CGPoint hitPoint; 67 | 68 | - (id)_uniquelyIdentifyingObjectiveCCode; 69 | - (id)_uniquelyIdentifyingSwiftCode; 70 | - (BOOL)_isAncestorOfElement:(id)arg1; 71 | - (BOOL)_isDescendantOfElement:(id)arg1; 72 | - (id)rootElement; 73 | - (BOOL)_frameFuzzyMatchesElement:(id)arg1; 74 | - (BOOL)_fuzzyMatchesElement:(id)arg1; 75 | - (BOOL)_matchesElement:(id)arg1; 76 | - (BOOL)matchesTreeWithRoot:(id)arg1; 77 | - (void)mergeTreeWithSnapshot:(id)arg1; 78 | - (id)_childMatchingElement:(id)arg1; 79 | - (NSArray *)_allDescendants; 80 | - (BOOL)hasDescendantMatchingFilter:(CDUnknownBlockType)arg1; 81 | - (NSArray *)descendantsByFilteringWithBlock:(BOOL(^)(XCElementSnapshot *snapshot))block; 82 | - (id)elementSnapshotMatchingAccessibilityElement:(id)arg1; 83 | - (void)enumerateDescendantsUsingBlock:(void(^)(XCElementSnapshot *snapshot))block; 84 | - (id)recursiveDescriptionWithIndent:(id)arg1 includeAccessibilityElement:(BOOL)arg2; 85 | - (id)init; 86 | - (struct CGPoint)hostingAndOrientationTransformedPoint:(struct CGPoint)arg1; 87 | - (struct CGPoint)_transformPoint:(struct CGPoint)arg1 windowContextID:(id)arg2 windowDisplayID:(id)arg3; 88 | - (id)hitTest:(struct CGPoint)arg1; 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCRuntimeUtils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | /** 15 | Returns array of classes that conforms to given protocol 16 | */ 17 | NSArray *FBClassesThatConformsToProtocol(Protocol *protocol); 18 | 19 | /** 20 | Method used to retrieve pointer for given symbol 'name' from given 'binary' 21 | 22 | @param binary path to binary we want to retrieve symbols pointer from 23 | @param name name of the symbol 24 | @return pointer to symbol 25 | */ 26 | void *FBRetrieveSymbolFromBinary(const char *binary, const char *name); 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCRuntimeUtils.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "XCRuntimeUtils.h" 11 | #import 12 | #include 13 | #import 14 | 15 | NSUInteger const ddLogLevel = DDLogLevelDebug; 16 | 17 | NSArray *FBClassesThatConformsToProtocol(Protocol *protocol) 18 | { 19 | Class *classes = NULL; 20 | NSMutableArray *collection = [NSMutableArray array]; 21 | int numClasses = objc_getClassList(NULL, 0); 22 | if (numClasses == 0 ) { 23 | return @[]; 24 | } 25 | 26 | classes = (__unsafe_unretained Class*)malloc(sizeof(Class) * numClasses); 27 | numClasses = objc_getClassList(classes, numClasses); 28 | for (int index = 0; index < numClasses; index++) { 29 | Class aClass = classes[index]; 30 | if (class_conformsToProtocol(aClass, protocol)) { 31 | [collection addObject:aClass]; 32 | } 33 | } 34 | 35 | free(classes); 36 | return collection.copy; 37 | } 38 | 39 | void *FBRetrieveSymbolFromBinary(const char *binary, const char *name) 40 | { 41 | void *handle = dlopen(binary, RTLD_LAZY); 42 | NSCAssert(handle, @"%s could not be opened", binary); 43 | void *pointer = dlsym(handle, name); 44 | NSCAssert(pointer, @"%s could not be located", name); 45 | return pointer; 46 | } 47 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCTRunnerDaemonSession.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | #import "XCTestManager_TestsInterface-Protocol.h" 8 | #import "CDStructures.h" 9 | #import 10 | 11 | @class NSMutableDictionary, NSXPCConnection; 12 | @protocol XCTUIApplicationMonitor, XCTAXClient; 13 | 14 | // iOS since 10.3 15 | @interface XCTRunnerDaemonSession : NSObject 16 | { 17 | NSObject *_queue; 18 | id _applicationMonitor; 19 | id _accessibilityClient; 20 | NSXPCConnection *_connection; 21 | unsigned long long _daemonProtocolVersion; 22 | NSMutableDictionary *_invalidationHandlers; 23 | } 24 | @property(retain) NSObject *queue; // @synthesize queue=_queue; 25 | @property id accessibilityClient; // @synthesize accessibilityClient=_accessibilityClient; 26 | @property id applicationMonitor; // @synthesize applicationMonitor=_applicationMonitor; 27 | @property(retain) NSMutableDictionary *invalidationHandlers; // @synthesize invalidationHandlers=_invalidationHandlers; 28 | @property(retain) NSXPCConnection *connection; // @synthesize connection=_connection; 29 | @property(readonly) BOOL useLegacyEventCoordinateTransformationPath; 30 | @property unsigned long long daemonProtocolVersion; 31 | @property(readonly) id daemonProxy; 32 | 33 | + (instancetype)sharedSession; 34 | 35 | - (void)injectVoiceRecognitionAudioInputPaths:(id)arg1 completion:(CDUnknownBlockType)arg2; 36 | - (void)injectAssistantRecognitionStrings:(id)arg1 completion:(CDUnknownBlockType)arg2; 37 | - (void)startSiriUIRequestWithAudioFileURL:(id)arg1 completion:(CDUnknownBlockType)arg2; 38 | - (void)startSiriUIRequestWithText:(id)arg1 completion:(CDUnknownBlockType)arg2; 39 | - (void)requestDTServiceHubConnectionWithReply:(CDUnknownBlockType)arg1; 40 | - (void)enableFauxCollectionViewCells:(CDUnknownBlockType)arg1; 41 | - (void)loadAccessibilityWithTimeout:(double)arg1 reply:(CDUnknownBlockType)arg2; 42 | - (void)setAXTimeout:(double)arg1 reply:(CDUnknownBlockType)arg2; 43 | - (void)requestScreenshotWithReply:(CDUnknownBlockType)arg1; 44 | - (void)sendString:(id)arg1 maximumFrequency:(unsigned long long)arg2 completion:(CDUnknownBlockType)arg3; 45 | - (void)updateDeviceOrientation:(long long)arg1 completion:(CDUnknownBlockType)arg2; 46 | - (void)performDeviceEvent:(id)arg1 completion:(CDUnknownBlockType)arg2; 47 | - (void)synthesizeEvent:(id)arg1 completion:(CDUnknownBlockType)arg2; 48 | - (void)requestElementAtPoint:(CGPoint)arg1 reply:(CDUnknownBlockType)arg2; 49 | - (void)fetchParameterizedAttributeForElement:(id)arg1 attribute:(id)arg2 parameter:(id)arg3 reply:(CDUnknownBlockType)arg4; 50 | - (void)setAttribute:(id)arg1 value:(id)arg2 element:(id)arg3 reply:(CDUnknownBlockType)arg4; 51 | - (void)fetchAttributesForElement:(id)arg1 attributes:(id)arg2 reply:(CDUnknownBlockType)arg3; 52 | - (void)snapshotForElement:(id)arg1 attributes:(id)arg2 parameters:(id)arg3 reply:(CDUnknownBlockType)arg4; 53 | - (void)terminateApplicationWithBundleID:(id)arg1 completion:(CDUnknownBlockType)arg2; 54 | - (void)performAccessibilityAction:(int)arg1 onElement:(id)arg2 value:(id)arg3 reply:(CDUnknownBlockType)arg4; 55 | - (void)unregisterForAccessibilityNotification:(int)arg1 registrationToken:(id)arg2 reply:(CDUnknownBlockType)arg3; 56 | - (void)registerForAccessibilityNotification:(int)arg1 reply:(CDUnknownBlockType)arg2; 57 | - (void)launchApplicationWithBundleID:(id)arg1 arguments:(id)arg2 environment:(id)arg3 completion:(CDUnknownBlockType)arg4; 58 | - (void)startMonitoringApplicationWithBundleID:(id)arg1; 59 | - (void)requestBackgroundAssertionForPID:(int)arg1 reply:(CDUnknownBlockType)arg2; 60 | - (void)requestAutomationSessionForTestTargetWithPID:(int)arg1 reply:(CDUnknownBlockType)arg2; 61 | - (void)requestIDEConnectionSocketForSessionIdentifier:(id)arg1 reply:(CDUnknownBlockType)arg2; 62 | - (void)_XCT_receivedAccessibilityNotification:(int)arg1 withPayload:(id)arg2; 63 | - (void)_XCT_applicationWithBundleID:(id)arg1 didUpdatePID:(int)arg2 andState:(unsigned long long)arg3; 64 | - (void)unregisterInvalidationHandlerWithToken:(id)arg1; 65 | - (id)registerInvalidationHandler:(CDUnknownBlockType)arg1; 66 | - (void)_reportInvalidation; 67 | - (id)initWithConnection:(id)arg1; 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCTestCase.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | #import 8 | 9 | #import "CDStructures.h" 10 | 11 | @class NSInvocation, XCTestCaseRun, XCTestContext, _XCTestCaseImplementation; 12 | 13 | @interface XCTestCase() 14 | { 15 | id _internalImplementation; 16 | } 17 | @property(retain) _XCTestCaseImplementation *internalImplementation; // @synthesize internalImplementation=_internalImplementation; 18 | @property(readonly) XCTestContext *testContext; 19 | @property(readonly) unsigned long long activityRecordStackDepth; 20 | @property(nonatomic) BOOL shouldHaltWhenReceivesControl; 21 | @property(retain) XCTestCaseRun *testCaseRun; 22 | 23 | + (id)_baselineDictionary; 24 | + (BOOL)_treatMissingBaselinesAsTestFailures; 25 | + (id)knownMemoryMetrics; 26 | + (id)measurementFormatter; 27 | + (BOOL)_reportPerformanceFailuresForLargeImprovements; 28 | + (BOOL)_enableSymbolication; 29 | 30 | + (BOOL)isInheritingTestCases; 31 | + (id)_testStartActvityDateFormatter; 32 | + (id)testCaseWithSelector:(SEL)arg1; 33 | 34 | 35 | + (void)tearDown; 36 | + (void)setUp; 37 | + (id)defaultTestSuite; 38 | + (id)allTestMethodInvocations; 39 | + (void)_allTestMethodInvocations:(id)arg1; 40 | + (id)testMethodInvocations; 41 | + (id)allSubclasses; 42 | - (void)startActivityWithTitle:(id)arg1 block:(CDUnknownBlockType)arg2; 43 | - (void)registerDefaultMetrics; 44 | - (id)baselinesDictionaryForTest; 45 | - (void)_logAndReportPerformanceMetrics:(id)arg1 perfMetricResultsForIDs:(id)arg2 withBaselinesForTest:(id)arg3; 46 | - (void)_logAndReportPerformanceMetrics:(id)arg1 perfMetricResultsForIDs:(id)arg2 withBaselinesForTest:(id)arg3 defaultBaselinesForPerfMetricID:(id)arg4; 47 | - (void)registerMetricID:(id)arg1 name:(id)arg2 unitString:(id)arg3; 48 | - (void)registerMetricID:(id)arg1 name:(id)arg2 unit:(id)arg3; 49 | - (void)reportMetric:(id)arg1 reportFailures:(BOOL)arg2; 50 | - (void)reportMeasurements:(id)arg1 forMetricID:(id)arg2 reportFailures:(BOOL)arg3; 51 | - (void)_recordValues:(id)arg1 forPerformanceMetricID:(id)arg2 name:(id)arg3 unitsOfMeasurement:(id)arg4 baselineName:(id)arg5 baselineAverage:(id)arg6 maxPercentRegression:(id)arg7 maxPercentRelativeStandardDeviation:(id)arg8 maxRegression:(id)arg9 maxStandardDeviation:(id)arg10 file:(id)arg11 line:(unsigned long long)arg12; 52 | - (id)_symbolicationRecordForTestCodeInAddressStack:(id)arg1; 53 | - (void)measureBlock:(CDUnknownBlockType)arg1; 54 | - (void)stopMeasuring; 55 | - (void)startMeasuring; 56 | - (BOOL)_isMeasuringMetrics; 57 | - (BOOL)_didStopMeasuring; 58 | - (BOOL)_didStartMeasuring; 59 | - (BOOL)_didMeasureMetrics; 60 | - (id)_perfMetricsForID; 61 | - (void)_logMemoryGraphDataFromFilePath:(id)arg1 withTitle:(id)arg2; 62 | - (void)_logMemoryGraphData:(id)arg1 withTitle:(id)arg2; 63 | - (unsigned long long)numberOfTestIterationsForTestWithSelector:(SEL)arg1; 64 | - (void)afterTestIteration:(unsigned long long)arg1 selector:(SEL)arg2; 65 | - (void)beforeTestIteration:(unsigned long long)arg1 selector:(SEL)arg2; 66 | - (void)tearDownTestWithSelector:(SEL)arg1; 67 | - (void)setUpTestWithSelector:(SEL)arg1; 68 | - (void)performTest:(id)arg1; 69 | - (void)invokeTest; 70 | - (Class)testRunClass; 71 | - (Class)_requiredTestRunBaseClass; 72 | - (void)_recordUnexpectedFailureWithDescription:(id)arg1 error:(id)arg2; 73 | - (void)_recordUnexpectedFailureWithDescription:(id)arg1 exception:(id)arg2; 74 | - (void)_enqueueFailureWithDescription:(NSString *)description inFile:(NSString *)filePath atLine:(NSUInteger)lineNumber expected:(BOOL)expected; 75 | - (void)_dequeueFailures; 76 | - (void)_interruptTest; 77 | - (BOOL)isEqual:(id)arg1; 78 | - (id)nameForLegacyLogging; 79 | - (id)name; 80 | - (id)languageAgnosticTestMethodName; 81 | - (unsigned long long)testCaseCount; 82 | - (id)initWithSelector:(SEL)arg1; 83 | - (id)init; 84 | - (void)waiter:(id)arg1 didFulfillInvertedExpectation:(id)arg2; 85 | - (void)waiter:(id)arg1 fulfillmentDidViolateOrderingConstraintsForExpectation:(id)arg2 requiredExpectation:(id)arg3; 86 | - (void)waiter:(id)arg1 didTimeoutWithUnfulfilledExpectations:(id)arg2; 87 | - (id)expectationForPredicate:(id)arg1 evaluatedWithObject:(id)arg2 handler:(CDUnknownBlockType)arg3; 88 | - (id)expectationForNotification:(id)arg1 object:(id)arg2 handler:(CDUnknownBlockType)arg3; 89 | - (id)keyValueObservingExpectationForObject:(id)arg1 keyPath:(id)arg2 handler:(CDUnknownBlockType)arg3; 90 | - (id)keyValueObservingExpectationForObject:(id)arg1 keyPath:(id)arg2 expectedValue:(id)arg3; 91 | - (void)_addExpectation:(id)arg1; 92 | - (void)waitForExpectations:(id)arg1 timeout:(double)arg2 enforceOrder:(BOOL)arg3; 93 | - (void)waitForExpectations:(id)arg1 timeout:(double)arg2; 94 | - (void)waitForExpectationsWithTimeout:(double)arg1 handler:(CDUnknownBlockType)arg2; 95 | - (void)_waitForExpectations:(id)arg1 timeout:(double)arg2 enforceOrder:(BOOL)arg3 handler:(CDUnknownBlockType)arg4; 96 | - (id)expectationWithDescription:(id)arg1; 97 | - (id)_expectationForDarwinNotification:(id)arg1; 98 | - (void)nestedWaiter:(id)arg1 wasInterruptedByTimedOutWaiter:(id)arg2; 99 | 100 | @end 101 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCTestDaemonsProxy.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | @protocol XCTestManager_ManagerInterface; 5 | 6 | /** 7 | Temporary class used to abstract interactions with TestManager daemon between Xcode 8.2.1 and Xcode 8.3-beta 8 | */ 9 | @interface XCTestDaemonsProxy : NSObject 10 | 11 | + (id)testRunnerProxy; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCTestDaemonsProxy.m: -------------------------------------------------------------------------------- 1 | 2 | #import "XCTestDaemonsProxy.h" 3 | #import "XCTestDriver.h" 4 | #import "XCTRunnerDaemonSession.h" 5 | #import 6 | 7 | @implementation XCTestDaemonsProxy 8 | 9 | + (id)testRunnerProxy 10 | { 11 | static id proxy = nil; 12 | static dispatch_once_t onceToken; 13 | dispatch_once(&onceToken, ^{ 14 | if ([[XCTestDriver sharedTestDriver] respondsToSelector:@selector(managerProxy)]) { 15 | proxy = [XCTestDriver sharedTestDriver].managerProxy; 16 | return; 17 | } 18 | Class runnerClass = objc_lookUpClass("XCTRunnerDaemonSession"); 19 | proxy = ((XCTRunnerDaemonSession *)[runnerClass sharedSession]).daemonProxy; 20 | }); 21 | NSAssert(proxy != NULL, @"Could not determin testRunnerProxy", proxy); 22 | return proxy; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCTestDriver.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | #import "CDStructures.h" 8 | #import "XCDebugLogDelegate-Protocol.h" 9 | #import "XCTestDriverInterface-Protocol.h" 10 | #import "XCTestManager_TestsInterface-Protocol.h" 11 | #import "XCTestManager_IDEInterface-Protocol.h" 12 | #import "XCTestManager_ManagerInterface-Protocol.h" 13 | 14 | @class DTXConnection, NSMutableArray, NSString, NSUUID, NSXPCConnection, XCTestConfiguration, XCTestSuite; 15 | 16 | @interface XCTestDriver : NSObject 17 | { 18 | XCTestConfiguration *_testConfiguration; 19 | NSObject *_queue; 20 | NSMutableArray *_debugMessageBuffer; 21 | int _debugMessageBufferOverflow; 22 | } 23 | @property int debugMessageBufferOverflow; // @synthesize debugMessageBufferOverflow=_debugMessageBufferOverflow; 24 | @property(retain) NSMutableArray *debugMessageBuffer; // @synthesize debugMessageBuffer=_debugMessageBuffer; 25 | @property(retain) NSObject *queue; // @synthesize queue=_queue; 26 | @property(readonly) XCTestConfiguration *testConfiguration; // @synthesize testConfiguration=_testConfiguration; 27 | 28 | + (instancetype)sharedTestDriver; 29 | 30 | - (void)runTestConfiguration:(id)arg1 completionHandler:(CDUnknownBlockType)arg2; 31 | - (void)runTestSuite:(id)arg1 completionHandler:(CDUnknownBlockType)arg2; 32 | - (void)reportStallOnMainThreadInTestCase:(id)arg1 method:(id)arg2 file:(id)arg3 line:(unsigned long long)arg4; 33 | - (BOOL)runTestsAndReturnError:(id *)arg1; 34 | - (id)_readyIDESession:(id *)arg1; 35 | - (int)_connectedSocketForIDESession:(id *)arg1; 36 | - (void)logDebugMessage:(id)arg1; 37 | - (id)initWithTestConfiguration:(id)arg1; 38 | 39 | // Removed with iOS 10.3 40 | @property(readonly) id managerProxy; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCTestDriverInterface-Protocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | @class NSNumber; 8 | 9 | @protocol XCTestDriverInterface 10 | - (id)_IDE_processWithToken:(NSNumber *)arg1 exitedWithStatus:(NSNumber *)arg2; 11 | - (id)_IDE_stopTrackingProcessWithToken:(NSNumber *)arg1; 12 | - (id)_IDE_processWithBundleID:(NSString *)arg1 path:(NSString *)arg2 pid:(NSNumber *)arg3 crashedUnderSymbol:(NSString *)arg4; 13 | - (id)_IDE_startExecutingTestPlanWithProtocolVersion:(NSNumber *)arg1; 14 | @end 15 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCTestManager_IDEInterface-Protocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | @class NSArray, NSDictionary, NSNumber, NSString, XCAccessibilityElement, XCActivityRecord, XCElementSnapshot; 8 | 9 | @protocol XCTestManager_IDEInterface 10 | - (id)_XCT_handleCrashReportData:(NSData *)arg1 fromFileWithName:(NSString *)arg2; 11 | - (id)_XCT_nativeFocusItemDidChangeAtTime:(NSNumber *)arg1 parameterSnapshot:(XCElementSnapshot *)arg2 applicationSnapshot:(XCElementSnapshot *)arg3; 12 | - (id)_XCT_recordedEventNames:(NSArray *)arg1 timestamp:(NSNumber *)arg2 duration:(NSNumber *)arg3 startLocation:(NSDictionary *)arg4 startElementSnapshot:(XCElementSnapshot *)arg5 startApplicationSnapshot:(XCElementSnapshot *)arg6 endLocation:(NSDictionary *)arg7 endElementSnapshot:(XCElementSnapshot *)arg8 endApplicationSnapshot:(XCElementSnapshot *)arg9; 13 | - (id)_XCT_testCase:(NSString *)arg1 method:(NSString *)arg2 didFinishActivity:(XCActivityRecord *)arg3; 14 | - (id)_XCT_testCase:(NSString *)arg1 method:(NSString *)arg2 willStartActivity:(XCActivityRecord *)arg3; 15 | - (id)_XCT_recordedOrientationChange:(NSString *)arg1; 16 | - (id)_XCT_recordedFirstResponderChangedWithApplicationSnapshot:(XCElementSnapshot *)arg1; 17 | - (id)_XCT_exchangeCurrentProtocolVersion:(NSNumber *)arg1 minimumVersion:(NSNumber *)arg2; 18 | - (id)_XCT_recordedKeyEventsWithApplicationSnapshot:(XCElementSnapshot *)arg1 characters:(NSString *)arg2 charactersIgnoringModifiers:(NSString *)arg3 modifierFlags:(NSNumber *)arg4; 19 | - (id)_XCT_logDebugMessage:(NSString *)arg1; 20 | - (id)_XCT_logMessage:(NSString *)arg1; 21 | - (id)_XCT_testMethod:(NSString *)arg1 ofClass:(NSString *)arg2 didMeasureMetric:(NSDictionary *)arg3 file:(NSString *)arg4 line:(NSNumber *)arg5; 22 | - (id)_XCT_testCase:(NSString *)arg1 method:(NSString *)arg2 didStallOnMainThreadInFile:(NSString *)arg3 line:(NSNumber *)arg4; 23 | - (id)_XCT_testCaseDidFinishForTestClass:(NSString *)arg1 method:(NSString *)arg2 withStatus:(NSString *)arg3 duration:(NSNumber *)arg4; 24 | - (id)_XCT_testCaseDidFailForTestClass:(NSString *)arg1 method:(NSString *)arg2 withMessage:(NSString *)arg3 file:(NSString *)arg4 line:(NSNumber *)arg5; 25 | - (id)_XCT_testCaseDidStartForTestClass:(NSString *)arg1 method:(NSString *)arg2; 26 | - (id)_XCT_testSuite:(NSString *)arg1 didFinishAt:(NSString *)arg2 runCount:(NSNumber *)arg3 withFailures:(NSNumber *)arg4 unexpected:(NSNumber *)arg5 testDuration:(NSNumber *)arg6 totalDuration:(NSNumber *)arg7; 27 | - (id)_XCT_testSuite:(NSString *)arg1 didStartAt:(NSString *)arg2; 28 | - (id)_XCT_initializationForUITestingDidFailWithError:(NSError *)arg1; 29 | - (id)_XCT_didBeginInitializingForUITesting; 30 | - (id)_XCT_didFinishExecutingTestPlan; 31 | - (id)_XCT_didBeginExecutingTestPlan; 32 | - (id)_XCT_testBundleReadyWithProtocolVersion:(NSNumber *)arg1 minimumVersion:(NSNumber *)arg2; 33 | - (id)_XCT_getProgressForLaunch:(id)arg1; 34 | - (id)_XCT_terminateProcess:(id)arg1; 35 | - (id)_XCT_launchProcessWithPath:(NSString *)arg1 bundleID:(NSString *)arg2 arguments:(NSArray *)arg3 environmentVariables:(NSDictionary *)arg4; 36 | @end 37 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCTestManager_ManagerInterface-Protocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | #import 8 | 9 | @class NSArray, NSDictionary, NSNumber, NSString, NSUUID, XCAccessibilityElement, XCDeviceEvent, XCSynthesizedEventRecord, XCTouchGesture, NSXPCListenerEndpoint; 10 | 11 | @protocol XCTestManager_ManagerInterface 12 | - (void)_XCT_loadAccessibilityWithTimeout:(double)arg1 reply:(void (^)(BOOL, NSError *))arg2; 13 | - (void)_XCT_injectVoiceRecognitionAudioInputPaths:(NSArray *)arg1 completion:(void (^)(BOOL, NSError *))arg2; 14 | - (void)_XCT_injectAssistantRecognitionStrings:(NSArray *)arg1 completion:(void (^)(BOOL, NSError *))arg2; 15 | - (void)_XCT_startSiriUIRequestWithAudioFileURL:(NSURL *)arg1 completion:(void (^)(BOOL, NSError *))arg2; 16 | - (void)_XCT_startSiriUIRequestWithText:(NSString *)arg1 completion:(void (^)(BOOL, NSError *))arg2; 17 | - (void)_XCT_requestDTServiceHubConnectionWithReply:(void (^)(NSXPCListenerEndpoint *, NSError *))arg1; 18 | - (void)_XCT_enableFauxCollectionViewCells:(void (^)(BOOL, NSError *))arg1; 19 | - (void)_XCT_setAXTimeout:(double)arg1 reply:(void (^)(int))arg2; 20 | - (void)_XCT_requestScreenshotWithReply:(void (^)(NSData *, NSError *))arg1; 21 | - (void)_XCT_sendString:(NSString *)arg1 maximumFrequency:(NSUInteger)arg2 completion:(void (^)(NSError *))arg3; 22 | - (void)_XCT_updateDeviceOrientation:(long long)arg1 completion:(void (^)(NSError *))arg2; 23 | - (void)_XCT_performDeviceEvent:(XCDeviceEvent *)arg1 completion:(void (^)(NSError *))arg2; 24 | - (void)_XCT_synthesizeEvent:(XCSynthesizedEventRecord *)arg1 completion:(void (^)(NSError *))arg2; 25 | - (void)_XCT_requestElementAtPoint:(CGPoint)arg1 reply:(void (^)(XCAccessibilityElement *, NSError *))arg2; 26 | - (void)_XCT_fetchParameterizedAttributeForElement:(XCAccessibilityElement *)arg1 attributes:(NSNumber *)arg2 parameter:(id)arg3 reply:(void (^)(id, NSError *))arg4; 27 | - (void)_XCT_setAttribute:(NSNumber *)arg1 value:(id)arg2 element:(XCAccessibilityElement *)arg3 reply:(void (^)(BOOL, NSError *))arg4; 28 | - (void)_XCT_fetchAttributesForElement:(XCAccessibilityElement *)arg1 attributes:(NSArray *)arg2 reply:(void (^)(NSDictionary *, NSError *))arg3; 29 | - (void)_XCT_snapshotForElement:(XCAccessibilityElement *)arg1 attributes:(NSArray *)arg2 parameters:(NSDictionary *)arg3 reply:(void (^)(XCElementSnapshot *, NSError *))arg4; 30 | - (void)_XCT_terminateApplicationWithBundleID:(NSString *)arg1 completion:(void (^)(NSError *))arg2; 31 | - (void)_XCT_performAccessibilityAction:(int)arg1 onElement:(XCAccessibilityElement *)arg2 withValue:(id)arg3 reply:(void (^)(NSError *))arg4; 32 | - (void)_XCT_unregisterForAccessibilityNotification:(int)arg1 withRegistrationToken:(NSNumber *)arg2 reply:(void (^)(NSError *))arg3; 33 | - (void)_XCT_registerForAccessibilityNotification:(int)arg1 reply:(void (^)(NSNumber *, NSError *))arg2; 34 | - (void)_XCT_launchApplicationWithBundleID:(NSString *)arg1 arguments:(NSArray *)arg2 environment:(NSDictionary *)arg3 completion:(void (^)(NSError *))arg4; 35 | - (void)_XCT_startMonitoringApplicationWithBundleID:(NSString *)arg1; 36 | - (void)_XCT_requestBackgroundAssertionForPID:(int)arg1 reply:(void (^)(BOOL))arg2; 37 | - (void)_XCT_requestBackgroundAssertionWithReply:(void (^)(void))arg1; 38 | - (void)_XCT_registerTarget; 39 | - (void)_XCT_requestEndpointForTestTargetWithPID:(int)arg1 preferredBackendPath:(NSString *)arg2 reply:(void (^)(NSXPCListenerEndpoint *, NSError *))arg3; 40 | - (void)_XCT_requestSocketForSessionIdentifier:(NSUUID *)arg1 reply:(void (^)(NSFileHandle *))arg2; 41 | - (void)_XCT_exchangeProtocolVersion:(unsigned long long)arg1 reply:(void (^)(unsigned long long))arg2; 42 | @end 43 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCTestManager_TestsInterface-Protocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | @class NSData, NSString; 8 | 9 | @protocol XCTestManager_TestsInterface 10 | - (void)_XCT_receivedAccessibilityNotification:(int)arg1 withPayload:(NSData *)arg2; 11 | - (void)_XCT_applicationWithBundleID:(NSString *)arg1 didUpdatePID:(int)arg2 andState:(unsigned long long)arg3; 12 | @end 13 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCTestPrivateSymbols.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | @protocol XCDebugLogDelegate; 13 | 14 | /*! Accessibility identifier for is visible attribute */ 15 | extern NSNumber *XCAXAIsVisibleAttribute; 16 | 17 | /*! Accessibility identifier for is accessible attribute */ 18 | extern NSNumber *XCAXAIsElementAttribute; 19 | 20 | /*! Getter for XCTest logger */ 21 | extern id (*XCDebugLogger)(void); 22 | 23 | /*! Setter for XCTest logger */ 24 | extern void (*XCSetDebugLogger)(id ); 25 | 26 | /** 27 | Method used to retrieve pointer for given symbol 'name' from given 'binary' 28 | 29 | @param name name of the symbol 30 | @return pointer to symbol 31 | */ 32 | void *RetrieveXCTestSymbol(const char *name); 33 | 34 | /*! Static constructor that will retrieve XCTest private symbols */ 35 | __attribute__((constructor)) void LoadXCTestSymbols(void); 36 | 37 | int portNumber(void); 38 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCTestPrivateSymbols.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "XCTestPrivateSymbols.h" 11 | 12 | #import "XCRuntimeUtils.h" 13 | 14 | NSNumber *XCAXAIsVisibleAttribute; 15 | NSNumber *XCAXAIsElementAttribute; 16 | 17 | void (*XCSetDebugLogger)(id ); 18 | id (*XCDebugLogger)(void); 19 | 20 | __attribute__((constructor)) void LoadXCTestSymbols(void) 21 | { 22 | NSString *XC_kAXXCAttributeIsVisible = *(NSString*__autoreleasing*)RetrieveXCTestSymbol("XC_kAXXCAttributeIsVisible"); 23 | NSString *XC_kAXXCAttributeIsElement = *(NSString*__autoreleasing*)RetrieveXCTestSymbol("XC_kAXXCAttributeIsElement"); 24 | 25 | NSArray *(*XCAXAccessibilityAttributesForStringAttributes)(NSArray *list) = 26 | (NSArray *(*)(NSArray *))RetrieveXCTestSymbol("XCAXAccessibilityAttributesForStringAttributes"); 27 | 28 | XCSetDebugLogger = (void (*)(id ))RetrieveXCTestSymbol("XCSetDebugLogger"); 29 | XCDebugLogger = (id(*)(void))RetrieveXCTestSymbol("XCDebugLogger"); 30 | 31 | NSArray *accessibilityAttributes = XCAXAccessibilityAttributesForStringAttributes(@[XC_kAXXCAttributeIsVisible, XC_kAXXCAttributeIsElement]); 32 | XCAXAIsVisibleAttribute = accessibilityAttributes[0]; 33 | XCAXAIsElementAttribute = accessibilityAttributes[1]; 34 | 35 | NSCAssert(XCAXAIsVisibleAttribute != nil , @"Failed to retrieve FB_XCAXAIsVisibleAttribute", XCAXAIsVisibleAttribute); 36 | NSCAssert(XCAXAIsElementAttribute != nil , @"Failed to retrieve FB_XCAXAIsElementAttribute", XCAXAIsElementAttribute); 37 | } 38 | 39 | void *RetrieveXCTestSymbol(const char *name) 40 | { 41 | Class XCTestClass = NSClassFromString(@"XCTestCase"); 42 | NSCAssert(XCTestClass != nil, @"XCTest should be already linked", XCTestClass); 43 | NSString *XCTestBinary = [NSBundle bundleForClass:XCTestClass].executablePath; 44 | const char *binaryPath = XCTestBinary.UTF8String; 45 | NSCAssert(binaryPath != nil, @"XCTest binary path should not be nil", binaryPath); 46 | return FBRetrieveSymbolFromBinary(binaryPath, name); 47 | } 48 | 49 | int portNumber() 50 | { 51 | return XCTESTWD_PORT; 52 | } 53 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCUIApplication.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | #import 8 | 9 | @class NSArray, NSDictionary, NSString, XCAccessibilityElement, XCApplicationQuery, XCUIApplicationImpl; 10 | 11 | @interface XCUIApplication () 12 | { 13 | BOOL _ancillary; 14 | BOOL _doesNotHandleUIInterruptions; 15 | BOOL _idleAnimationWaitEnabled; 16 | XCUIElement *_keyboard; 17 | NSArray *_launchArguments; 18 | NSDictionary *_launchEnvironment; 19 | XCUIApplicationImpl *_applicationImpl; 20 | XCApplicationQuery *_applicationQuery; 21 | unsigned long long _generation; 22 | } 23 | @property unsigned long long generation; // @synthesize generation=_generation; 24 | @property(retain) XCApplicationQuery *applicationQuery; // @synthesize applicationQuery=_applicationQuery; 25 | @property(retain) XCUIApplicationImpl *applicationImpl; // @synthesize applicationQuery=_applicationQuery; 26 | @property(readonly, copy) NSString *bundleID; // @synthesize bundleID=_bundleID; 27 | @property(readonly, copy) NSString *path; // @synthesize path=_path; 28 | @property BOOL ancillary; // @synthesize ancillary=_ancillary; 29 | @property(readonly) XCUIElement *keyboard; // @synthesize keyboard=_keyboard; 30 | 31 | @property(getter=isIdleAnimationWaitEnabled) BOOL idleAnimationWaitEnabled; // @synthesize idleAnimationWaitEnabled=_idleAnimationWaitEnabled; 32 | @property(nonatomic) BOOL doesNotHandleUIInterruptions; // @synthesize doesNotHandleUIInterruptions=_doesNotHandleUIInterruptions; 33 | @property(readonly) BOOL fauxCollectionViewCellsEnabled; 34 | @property(readonly, nonatomic) UIInterfaceOrientation interfaceOrientation; //TODO tvos 35 | @property(readonly, nonatomic) BOOL running; 36 | @property(nonatomic) pid_t processID; // @synthesize processID=_processID; 37 | @property XCUIApplicationState state; // @synthesize state=_state; // @synthesize state=_state; 38 | @property(readonly) XCAccessibilityElement *accessibilityElement; 39 | 40 | + (instancetype)appWithPID:(pid_t)processID; 41 | + (instancetype)applicationWithPID:(pid_t)processID; 42 | 43 | - (void)dismissKeyboard; 44 | - (BOOL)setFauxCollectionViewCellsEnabled:(BOOL)arg1 error:(id *)arg2; 45 | - (void)_waitForViewControllerViewDidDisappearWithTimeout:(double)arg1; 46 | - (void)_waitForQuiescence; 47 | - (void)terminate; 48 | - (void)_launchUsingXcode:(BOOL)arg1; 49 | - (void)launch; 50 | - (id)application; 51 | - (id)description; 52 | - (id)lastSnapshot; 53 | - (id)query; 54 | - (void)clearQuery; 55 | - (void)resolveHandleUIInterruption:(BOOL)arg1; 56 | - (id)initPrivateWithPath:(id)arg1 bundleID:(id)arg2; 57 | - (id)init; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCUICoordinate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | #import 8 | #import 9 | 10 | @class XCUIElement; 11 | 12 | #if !TARGET_OS_TV 13 | @interface XCUICoordinate () 14 | { 15 | XCUIElement *_element; 16 | XCUICoordinate *_coordinate; 17 | CGVector _normalizedOffset; 18 | CGVector _pointsOffset; 19 | } 20 | 21 | @property(readonly) CGVector pointsOffset; // @synthesize pointsOffset=_pointsOffset; 22 | @property(readonly) CGVector normalizedOffset; // @synthesize normalizedOffset=_normalizedOffset; 23 | @property(readonly) XCUICoordinate *coordinate; // @synthesize coordinate=_coordinate; 24 | @property(readonly) XCUIElement *element; // @synthesize element=_element; 25 | 26 | - (id)initWithCoordinate:(id)arg1 pointsOffset:(CGVector)arg2; 27 | - (id)initWithElement:(id)arg1 normalizedOffset:(CGVector)arg2; 28 | - (id)init; 29 | 30 | - (void)pressForDuration:(double)arg1 thenDragToCoordinate:(id)arg2; 31 | - (void)pressForDuration:(double)arg1; 32 | - (void)doubleTap; 33 | - (void)tap; 34 | 35 | @end 36 | #endif 37 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCUIElement.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | #import 8 | 9 | @class NSString, XCElementSnapshot, XCUIApplication, XCUICoordinate, XCUIElementQuery; 10 | 11 | @interface XCUIElement () 12 | { 13 | BOOL _safeQueryResolutionEnabled; 14 | XCUIElementQuery *_query; 15 | XCElementSnapshot *_lastSnapshot; 16 | } 17 | 18 | @property BOOL safeQueryResolutionEnabled; // @synthesize safeQueryResolutionEnabled=_safeQueryResolutionEnabled; 19 | @property(retain) XCElementSnapshot *lastSnapshot; // @synthesize lastSnapshot=_lastSnapshot; 20 | @property(readonly) XCUIElementQuery *query; // @synthesize query=_query; 21 | @property(readonly, nonatomic) UIInterfaceOrientation interfaceOrientation; 22 | @property(readonly, copy) XCUICoordinate *hitPointCoordinate; 23 | @property(readonly) BOOL isTopLevelTouchBarElement; 24 | @property(readonly) BOOL isTouchBarElement; 25 | @property(readonly) BOOL hasKeyboardFocus; 26 | @property(readonly, nonatomic) XCUIApplication *application; 27 | 28 | - (id)initWithElementQuery:(id)arg1; 29 | 30 | - (unsigned long long)traits; 31 | - (void)resolveHandleUIInterruption:(BOOL)arg1; 32 | - (void)resolve; 33 | - (BOOL)_waitForExistenceWithTimeout:(double)arg1; 34 | - (BOOL)evaluatePredicateForExpectation:(id)arg1 debugMessage:(id *)arg2; 35 | - (void)_swipe:(unsigned long long)arg1; 36 | - (void)_tapWithNumberOfTaps:(unsigned long long)arg1 numberOfTouches:(unsigned long long)arg2 activityTitle:(id)arg3; 37 | - (id)_highestNonWindowAncestorOfElement:(id)arg1 notSharedWithElement:(id)arg2; 38 | - (id)_pointsInFrame:(CGRect)arg1 numberOfTouches:(unsigned long long)arg2; 39 | - (CGPoint)_hitPointByAttemptingToScrollToVisibleSnapshot:(id)arg1; 40 | - (void)forcePress; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/XCUIElementQuery.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | #import "CDStructures.h" 8 | #import 9 | 10 | @class NSArray, NSOrderedSet, NSString, XCUIApplication, XCUIElement; 11 | 12 | @interface XCUIElementQuery () 13 | { 14 | BOOL _changesScope; 15 | NSString *_queryDescription; 16 | XCUIElementQuery *_inputQuery; 17 | CDUnknownBlockType _filter; 18 | unsigned long long _expressedType; 19 | NSArray *_expressedIdentifiers; 20 | NSOrderedSet *_lastInput; 21 | NSOrderedSet *_lastOutput; 22 | } 23 | 24 | @property(copy) NSOrderedSet *lastOutput; // @synthesize lastOutput=_lastOutput; 25 | @property(copy) NSOrderedSet *lastInput; // @synthesize lastInput=_lastInput; 26 | @property(copy) NSArray *expressedIdentifiers; // @synthesize expressedIdentifiers=_expressedIdentifiers; 27 | @property unsigned long long expressedType; // @synthesize expressedType=_expressedType; 28 | @property BOOL changesScope; // @synthesize changesScope=_changesScope; 29 | @property(readonly, copy) CDUnknownBlockType filter; // @synthesize filter=_filter; 30 | @property(readonly) XCUIElementQuery *inputQuery; // @synthesize inputQuery=_inputQuery; 31 | @property(readonly, copy) NSString *queryDescription; // @synthesize queryDescription=_queryDescription; 32 | @property(readonly, copy) NSString *elementDescription; 33 | @property(readonly) XCUIApplication *application; 34 | 35 | - (id)matchingSnapshotsWithError:(id *)arg1; 36 | - (id)matchingSnapshotsHandleUIInterruption:(BOOL)arg1 withError:(id *)arg2; 37 | - (id)_elementMatchingAccessibilityElementOfSnapshot:(id)arg1; 38 | 39 | - (id)_containingPredicate:(id)arg1 queryDescription:(id)arg2; 40 | - (id)_predicateWithType:(unsigned long long)arg1 identifier:(id)arg2; 41 | - (id)_queryWithPredicate:(id)arg1; 42 | - (id)sorted:(CDUnknownBlockType)arg1; 43 | - (id)descending:(unsigned long long)arg1; 44 | - (id)ascending:(unsigned long long)arg1; 45 | - (id)filter:(CDUnknownBlockType)arg1; 46 | - (id)_debugInfoWithIndent:(id *)arg1; 47 | - (id)_derivedExpressedIdentifiers; 48 | - (unsigned long long)_derivedExpressedType; 49 | - (id)initWithInputQuery:(id)arg1 queryDescription:(id)arg2 filter:(CDUnknownBlockType)arg3; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/PrivateHeaders/_XCTestCaseImplementation.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | @class NSArray, NSInvocation, NSMutableArray, NSMutableDictionary, NSMutableSet, NSString, XCTestCaseRun, XCTestContext, XCTestExpectationWaiter, XCTWaiter; 8 | 9 | #import "CDStructures.h" 10 | 11 | @interface _XCTestCaseImplementation : NSObject 12 | { 13 | NSInvocation *_invocation; 14 | XCTestCaseRun *_testCaseRun; 15 | BOOL _continueAfterFailure; 16 | NSMutableSet *_expectations; 17 | NSArray *_activePerformanceMetricIDs; 18 | NSMutableDictionary *_perfMetricsForID; 19 | unsigned long long _startWallClockTime; 20 | struct time_value _startUserTime; 21 | struct time_value _startSystemTime; 22 | unsigned long long _measuringIteration; 23 | BOOL _isMeasuringMetrics; 24 | BOOL _didMeasureMetrics; 25 | BOOL _didStartMeasuring; 26 | BOOL _didStopMeasuring; 27 | NSString *_filePathForUnexpectedFailure; 28 | unsigned long long _lineNumberForUnexpectedFailure; 29 | unsigned long long _callAddressForCurrentWait; 30 | NSArray *_callAddressesForLastCreatedExpectation; 31 | long long _runLoopNestingCount; 32 | XCTWaiter *_currentWaiter; 33 | NSMutableArray *_failureRecords; 34 | BOOL _shouldHaltWhenReceivesControl; 35 | BOOL _shouldIgnoreSubsequentFailures; 36 | NSMutableArray *_activityRecordStack; 37 | XCTestContext *_testContext; 38 | } 39 | 40 | @property(readonly) XCTestContext *testContext; // @synthesize testContext=_testContext; 41 | @property(retain, nonatomic) XCTWaiter *currentWaiter; // @synthesize currentWaiter=_currentWaiter; 42 | @property(retain, nonatomic) NSMutableArray *activityRecordStack; // @synthesize activityRecordStack=_activityRecordStack; 43 | @property BOOL shouldIgnoreSubsequentFailures; // @synthesize shouldIgnoreSubsequentFailures=_shouldIgnoreSubsequentFailures; 44 | @property BOOL shouldHaltWhenReceivesControl; // @synthesize shouldHaltWhenReceivesControl=_shouldHaltWhenReceivesControl; 45 | @property(retain, nonatomic) NSMutableArray *failureRecords; // @synthesize failureRecords=_failureRecords; 46 | @property long long runLoopNestingCount; // @synthesize runLoopNestingCount=_runLoopNestingCount; 47 | @property(copy) NSArray *callAddressesForLastCreatedExpectation; // @synthesize callAddressesForLastCreatedExpectation=_callAddressesForLastCreatedExpectation; 48 | @property unsigned long long callAddressForCurrentWait; // @synthesize callAddressForCurrentWait=_callAddressForCurrentWait; 49 | @property unsigned long long lineNumberForUnexpectedFailure; // @synthesize lineNumberForUnexpectedFailure=_lineNumberForUnexpectedFailure; 50 | @property(copy) NSString *filePathForUnexpectedFailure; // @synthesize filePathForUnexpectedFailure=_filePathForUnexpectedFailure; 51 | @property(retain, nonatomic) NSMutableSet *expectations; // @synthesize expectations=_expectations; 52 | @property BOOL didStopMeasuring; // @synthesize didStopMeasuring=_didStopMeasuring; 53 | @property BOOL didStartMeasuring; // @synthesize didStartMeasuring=_didStartMeasuring; 54 | @property BOOL didMeasureMetrics; // @synthesize didMeasureMetrics=_didMeasureMetrics; 55 | @property BOOL isMeasuringMetrics; // @synthesize isMeasuringMetrics=_isMeasuringMetrics; 56 | @property unsigned long long measuringIteration; // @synthesize measuringIteration=_measuringIteration; 57 | @property struct time_value startUserTime; // @synthesize startUserTime=_startUserTime; 58 | @property struct time_value startSystemTime; // @synthesize startSystemTime=_startSystemTime; 59 | @property unsigned long long startWallClockTime; // @synthesize startWallClockTime=_startWallClockTime; 60 | @property(retain) NSMutableDictionary *perfMetricsForID; // @synthesize perfMetricsForID=_perfMetricsForID; 61 | @property(copy) NSArray *activePerformanceMetricIDs; // @synthesize activePerformanceMetricIDs=_activePerformanceMetricIDs; 62 | @property BOOL continueAfterFailure; // @synthesize continueAfterFailure=_continueAfterFailure; 63 | @property(retain) XCTestCaseRun *testCaseRun; // @synthesize testCaseRun=_testCaseRun; 64 | @property(retain) NSInvocation *invocation; // @synthesize invocation=_invocation; 65 | 66 | - (void)resetExpectations; 67 | - (void)addExpectation:(id)arg1; 68 | - (id)init; 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/MonkeyUIAutomation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MonkeyUIAutomation.swift 3 | // Fleek 4 | // 5 | // Created by Dag Agren on 23/03/16. 6 | // Copyright © 2016 Zalando SE. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | private let eventGenerator: UIASyntheticEvents = { 12 | let url = URL(fileURLWithPath: "/Developer/Library/PrivateFrameworks/UIAutomation.framework/UIAutomation") 13 | 14 | url.withUnsafeFileSystemRepresentation() { representation -> Void in 15 | dlopen(representation, RTLD_LOCAL) 16 | } 17 | 18 | let eventsclass = unsafeBitCast(NSClassFromString("UIASyntheticEvents"), to: UIASyntheticEvents.Type.self) 19 | return eventsclass.sharedEventGenerator() 20 | }() 21 | 22 | /** 23 | Extension using private funcctions from the UIAutomation 24 | API to generate events. Currently does not seem to work 25 | on actual devices for unknown reasons. 26 | 27 | The public XCTest API is far too slow for useful random testing, 28 | so currently using private APIs is the only option. 29 | 30 | As this code is only used in your tests, and never 31 | distributed, it will not cause problems with App Store 32 | approval. 33 | */ 34 | extension Monkey { 35 | /** 36 | Add a sane default set of event generation actions 37 | using the private UIAutomation API. Use this function if you 38 | just want to generate some events, and do not have 39 | strong requirements on exactly which ones you need. 40 | */ 41 | public func addDefaultUIAutomationActions() { 42 | addUIAutomationTapAction(weight: 50) 43 | addUIAutomationDragAction(weight: 1) 44 | addUIAutomationFlickAction(weight: 1) 45 | addUIAutomationPinchCloseAction(weight: 1) 46 | addUIAutomationPinchOpenAction(weight: 1) 47 | //addUIAutomationRotateAction(weight: 1) // TODO: Investigate why this is broken. 48 | addUIAutomationOrientationAction(weight: 1) 49 | addUIAutomationClickVolumeUpAction(weight: 1) 50 | addUIAutomationClickVolumeDownAction(weight: 1) 51 | addUIAutomationShakeAction(weight: 1) 52 | addUIAutomationLockAction(weight: 1) 53 | } 54 | 55 | /** 56 | Add an action that generates a single tap event 57 | using the private UIAutomation API. 58 | 59 | - Parameter weight: The relative probability of this 60 | event being generated. Can be any value larger than 61 | zero. Probabilities will be normalised to the sum 62 | of all relative probabilities. 63 | */ 64 | public func addUIAutomationSingleTapAction(weight: Double) { 65 | addAction(weight: weight) { [weak self] in 66 | eventGenerator.sendTap(self!.randomPoint()) 67 | } 68 | } 69 | 70 | /** 71 | Add an action that generates a tap, with a possibility for 72 | multiple taps with multiple fingers, or long taps, using 73 | the private UIAutomation API. 74 | 75 | - parameter weight: The relative probability of this 76 | event being generated. Can be any value larger than 77 | zero. Probabilities will be normalised to the sum 78 | of all relative probabilities. 79 | - parameter multipleTapProbability: Probability that 80 | the tap event will tap multiple times. Between 0 and 1. 81 | - parameter multipleTouchProbability: Probability that 82 | the tap event will use multiple fingers. Between 0 and 1. 83 | - parameter longPressProbability: Probability that 84 | the tap event will be a long press. Between 0 and 1. 85 | */ 86 | public func addUIAutomationTapAction(weight: Double, multipleTapProbability: Double = 0.05, 87 | multipleTouchProbability: Double = 0.05, longPressProbability: Double = 0.05) { 88 | addAction(weight: weight) { [weak self] in 89 | let numberOfTaps: Int 90 | if self!.r.randomDouble() UIASyntheticEvents 302 | 303 | //@property(readonly) struct __IOHIDEventSystemClient *ioSystemClient; // @synthesize ioSystemClient=_ioSystemClient; 304 | var voiceOverStyleTouchEventsEnabled: Bool { get set } 305 | var activePointCount: UInt64 { get set } 306 | //@property(nonatomic) CDStruct_3eca2549 *activePoints; // @synthesize activePoints=_activePoints; 307 | var gsScreenScale: Double { get set } 308 | var gsScreenSize: CGSize { get set } 309 | var screenSize: CGSize { get set } 310 | var screen: UIScreen { get set } 311 | var onScreenRect: CGRect { get set } 312 | 313 | func sendPinchCloseWithStartPoint(_: CGPoint, endPoint: CGPoint, duration: Double, inRect: CGRect) 314 | func sendPinchOpenWithStartPoint(_: CGPoint, endPoint: CGPoint, duration: Double, inRect: CGRect) 315 | func sendDragWithStartPoint(_: CGPoint, endPoint: CGPoint, duration: Double, withFlick: Bool, inRect: CGRect) 316 | func sendRotate(_: CGPoint, withRadius: Double, rotation: Double, duration: Double, touchCount: UInt64) 317 | func sendMultifingerDragWithPointArray(_: UnsafePointer, numPoints: Int32, duration: Double, numFingers: Int32) 318 | func sendPinchCloseWithStartPoint(_: CGPoint, endPoint: CGPoint, duration: Double) 319 | func sendPinchOpenWithStartPoint(_: CGPoint, endPoint: CGPoint, duration: Double) 320 | func sendFlickWithStartPoint(_: CGPoint, endPoint: CGPoint, duration: Double) 321 | func sendDragWithStartPoint(_: CGPoint, endPoint: CGPoint, duration: Double) 322 | func sendTaps(_: Int, location: CGPoint, withNumberOfTouches: Int, inRect: CGRect) 323 | func sendDoubleFingerTap(_: CGPoint) 324 | func sendDoubleTap(_: CGPoint) 325 | func _sendTap(_: CGPoint, withPressure: Double) 326 | func sendTap(_: CGPoint) 327 | func _setMajorRadiusForAllPoints(_: Double) 328 | func _setPressureForAllPoints(_: Double) 329 | func moveToPoints(_: UnsafePointer, touchCount: UInt64, duration: Double) 330 | func _moveLastTouchPoint(_: CGPoint) 331 | func liftUp(_: CGPoint) 332 | func liftUp(_: CGPoint, touchCount: UInt64) 333 | func liftUpAtPoints(_: UnsafePointer, touchCount: UInt64) 334 | func touchDown(_: CGPoint) 335 | func touchDown(_: CGPoint, touchCount: UInt64) 336 | func touchDownAtPoints(_: UnsafePointer, touchCount: UInt64) 337 | func shake() 338 | func setRinger(_: Bool) 339 | func holdVolumeDown(_: Double) 340 | func clickVolumeDown() 341 | func holdVolumeUp(_: Double) 342 | func clickVolumeUp() 343 | func holdLock(_: Double) 344 | func clickLock() 345 | func lockDevice() 346 | func holdMenu(_: Double) 347 | func clickMenu() 348 | func _sendSimpleEvent(_: Int) 349 | func setOrientation(_: Int32) 350 | func sendAccelerometerX(_: Double, Y: Double, Z: Double, duration: Double) 351 | func sendAccelerometerX(_: Double, Y: Double, Z: Double) 352 | func _updateTouchPoints(_: UnsafePointer, count: UInt64) 353 | func _sendHIDVendorDefinedEvent(_: UInt32, usage: UInt32, data: UnsafePointer, dataLength: UInt32) -> Bool 354 | func _sendHIDScrollEventX(_: Double, Y: Double, Z: Double) -> Bool 355 | func _sendHIDKeyboardEventPage(_: UInt32, usage: UInt32, duration: Double) -> Bool 356 | //- (_Bool)_sendHIDEvent:(struct __IOHIDEvent *)arg1; 357 | //- (struct __IOHIDEvent *)_UIACreateIOHIDEventType:(unsigned int)arg1; func _isEdgePoint(_: CGPoint) -> Bool 358 | func _normalizePoint(_: CGPoint) -> CGPoint 359 | //- (void)dealloc; 360 | func _initScreenProperties() 361 | //- (id)init; 362 | } 363 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/MonkeyXCTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDMonkeyController.swift 3 | // FastMonkey 4 | // 5 | // fixed by zhangzhao on 2017/7/17. 6 | // 7 | 8 | import Foundation 9 | import XCTest 10 | 11 | /** 12 | Extension using the public XCTest API to generate 13 | events. 14 | */ 15 | @available(iOS 9.0, *) 16 | extension Monkey { 17 | 18 | /** 19 | Add an action that checks, at a fixed interval, 20 | if an alert is being displayed, and if so, selects 21 | a random button on it. 22 | 23 | - parameter interval: How often to generate this 24 | event. One of these events will be generated after 25 | this many randomised events have been generated. 26 | - parameter application: The `XCUIApplication` object 27 | for the current application. 28 | */ 29 | public func addXCTestTapAlertAction(interval: Int, application: XCUIApplication) { 30 | addAction(interval: interval) { [weak self] in 31 | // The test for alerts on screen and dismiss them if there are any. 32 | // for i in 0 ..< application.alerts.count { 33 | // let alert = application.alerts.element(boundBy: i) 34 | // let buttons = alert.descendants(matching: .button) 35 | // XCTAssertNotEqual(buttons.count, 0, "No buttons in alert") 36 | // let index = UInt(self!.r.randomUInt32() % UInt32(buttons.count)) 37 | // let button = buttons.element(boundBy: index) 38 | // button.tap() 39 | // } 40 | usleep(2000000) 41 | //let isRunning = application.running 42 | //let current = Int(XCTestWDFindElementUtils.getAppPid()) 43 | //if current == 0 { 44 | // return 45 | //} 46 | if application.state == XCUIApplication.State.runningForeground { 47 | for i in 0 ..< application.alerts.count { 48 | let alert = application.alerts.element(boundBy: i) 49 | let buttons = alert.descendants(matching: .button) 50 | let index: Int = Int(self!.r.randomUInt32() % UInt32(buttons.count)) 51 | let button = buttons.element(boundBy: index) 52 | button.tap() 53 | } 54 | }else{ 55 | application.activate() 56 | self!.sleep(5) 57 | self?.pid = Int(XCTestWDFindElementUtils.getAppPid()) 58 | } 59 | } 60 | } 61 | 62 | /** 63 | Add an action that checks current app, at a fixed interval, 64 | if app is not running , so launch app 65 | */ 66 | 67 | public func addXCTestCheckCurrentApp(interval:Int, application:XCUIApplication) { 68 | addCheck(interval:interval){ [weak self] in 69 | //let work = DispatchWorkItem(qos:.userInteractive){ 70 | /** too slow **/ 71 | //application._waitForQuiescence() 72 | // let isRunning = application.running 73 | // let current = Int(XCTestWDFindElementUtils.getAppPid()) 74 | // if current != self?.pid || !isRunning{ 75 | // application.launch() 76 | // self?.sleep(5) 77 | // self?.pid = Int(XCTestWDFindElementUtils.getAppPid()) 78 | // } 79 | //} 80 | //DispatchQueue.main.async(execute:work) 81 | let work = DispatchWorkItem(qos:.userInteractive){ 82 | if (application.state != XCUIApplication.State.runningForeground){ 83 | application.activate() 84 | self?.sleep(5) 85 | self?.pid = Int(XCTestWDFindElementUtils.getAppPid()) 86 | } 87 | } 88 | DispatchQueue.main.async(execute:work) 89 | } 90 | } 91 | 92 | /** 93 | Add an action that check login keypoint, at a fixed interval, 94 | if find key point, take login event 95 | */ 96 | 97 | public func addXCTestAppLogin(interval:Int, application:XCUIApplication) { 98 | addAction(interval:interval){ [weak self] in 99 | do{ 100 | let session = try XCTestWDSessionManager.singleton.checkDefaultSession() 101 | let root = session.application 102 | if root != nil{ 103 | let usage = "xpath" 104 | let tag = "//XCUIElementTypeOther[@name='登录']/XCUIElementTypeTextField" 105 | let element = try? XCTestWDFindElementUtils.filterElement(usingText: usage, withvalue: tag, underElement: root!) 106 | if let element = element { 107 | if element != nil { 108 | self?.addXCTestLoginAction(application: application) 109 | } 110 | else{ 111 | return 112 | } 113 | } 114 | } 115 | }catch{ 116 | return 117 | } 118 | } 119 | } 120 | } 121 | 122 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/Random.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Random.swift 3 | // Fleek 4 | // 5 | // Created by Dag Agren on 14/03/16. 6 | // Copyright © 2016 Zalando SE. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Simple implementation of a PCG random number generator: 13 | http://www.pcg-random.org/ 14 | */ 15 | struct Random { 16 | var state: UInt64 = 0 17 | let increment: UInt64 18 | 19 | init() { 20 | self.init(seed: 0) 21 | } 22 | 23 | init(seed: UInt32) { 24 | self.init(seed: 0, sequence: 0) 25 | } 26 | 27 | init(seed: UInt32, sequence: UInt32) { 28 | state = 0 29 | increment = (UInt64(sequence) << 1) | 1 30 | _ = randomUInt32() 31 | state = state &+ UInt64(seed) 32 | _ = randomUInt32() 33 | } 34 | 35 | mutating func randomUInt32() -> UInt32 { 36 | let oldstate = state 37 | state = oldstate &* 6364136223846793005 &+ increment 38 | let xorshifted = UInt32((((oldstate >> 18) ^ oldstate) >> 27) & 0xffffffff) 39 | let rot = UInt32(oldstate >> 59) 40 | return (xorshifted >> rot) | (xorshifted << UInt32(-Int(rot) & 31)) 41 | } 42 | 43 | mutating func randomInt(lessThan: Int) -> Int { 44 | return Int(randomUInt32() % UInt32(lessThan)) 45 | } 46 | 47 | mutating func randomUInt(lessThan: UInt) -> UInt { 48 | return UInt(randomUInt32() % UInt32(lessThan)) 49 | } 50 | 51 | mutating func randomFloat() -> Float { 52 | return Float(randomUInt32()) / 4294967296.0 53 | } 54 | 55 | mutating func randomFloat(lessThan: Float) -> Float { 56 | return randomFloat() * lessThan 57 | } 58 | 59 | mutating func randomDouble() -> Double { 60 | return Double(randomUInt32()) / 4294967296.0 61 | } 62 | 63 | mutating func randomDouble(lessThan: Double) -> Double { 64 | return randomDouble() * lessThan 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/XCTestWDActionsController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestAlertViewCommand.swift 3 | // XCTestWebdriver 4 | // 5 | // Created by zhaoy on 21/4/17. 6 | // Copyright © 2017 XCTestWebdriver. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | 12 | internal class XCTestWDActionsController: Controller { 13 | 14 | //MARK: Controller - Protocol 15 | static func routes() -> [(RequestRoute, RoutingCall)] { 16 | return [(RequestRoute("/actions", "post"), actions)] 17 | } 18 | 19 | static func shouldRegisterAutomatically() -> Bool { 20 | return false 21 | } 22 | 23 | //MARK: Routing Logic Specification 24 | internal static func actions(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 25 | return HttpResponse.ok(.html("actions")) 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/XCTestWDAlertController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestAlertViewCommand.swift 3 | // XCTestWebdriver 4 | // 5 | // Created by zhaoy on 21/4/17. 6 | // Copyright © 2017 XCTestWebdriver. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | import SwiftyJSON 12 | import CocoaLumberjackSwift 13 | 14 | internal class XCTestWDAlertController: Controller { 15 | 16 | //MARK: Controller - Protocol 17 | static func routes() -> [(RequestRoute, RoutingCall)] { 18 | return [(RequestRoute("/wd/hub/session/:sessionId/accept_alert", "post"), acceptAlert), 19 | (RequestRoute("/wd/hub/session/:sessionId/dismiss_alert", "post"), dismissAlert), 20 | (RequestRoute("/wd/hub/session/:sessionId/alert_text", "get"), alertText), 21 | (RequestRoute("/wd/hub/session/:sessionId/alert_text", "post"), alertKeys)] 22 | } 23 | 24 | static func shouldRegisterAutomatically() -> Bool { 25 | return false 26 | } 27 | 28 | //MARK: Routing Logic Specification 29 | internal static func acceptAlert(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 30 | if request.session == nil { 31 | return XCTestWDResponse.response(session: nil, error: WDStatus.SessionNotCreatedException) 32 | } else { 33 | let alert = XCTestWDAlert(request.session!.application) 34 | if alert.accept() { 35 | DDLogDebug("\(XCTestWDDebugInfo.DebugLogPrefix) accepAlert success") 36 | return XCTestWDResponse.response(session: request.session!, value: nil) 37 | } else { 38 | DDLogDebug("\(XCTestWDDebugInfo.DebugLogPrefix) accepAlert failure") 39 | return XCTestWDResponse.response(session: request.session!, error: WDStatus.NoAlertOpenError) 40 | } 41 | } 42 | } 43 | 44 | internal static func dismissAlert(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 45 | if request.session == nil { 46 | return XCTestWDResponse.response(session: nil, error: WDStatus.SessionNotCreatedException) 47 | } else { 48 | let alert = XCTestWDAlert(request.session!.application) 49 | if alert.dismiss() { 50 | DDLogDebug("\(XCTestWDDebugInfo.DebugLogPrefix) dismissAlert success") 51 | return XCTestWDResponse.response(session: request.session!, value: nil) 52 | } else { 53 | DDLogDebug("\(XCTestWDDebugInfo.DebugLogPrefix) dismissAlert failure") 54 | return XCTestWDResponse.response(session: request.session!, error: WDStatus.NoAlertOpenError) 55 | } 56 | } 57 | } 58 | 59 | internal static func alertText(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 60 | if request.session == nil { 61 | return XCTestWDResponse.response(session: nil, error: WDStatus.SessionNotCreatedException) 62 | } else { 63 | let alert = XCTestWDAlert(request.session!.application) 64 | let text = alert.text() 65 | if text != nil { 66 | DDLogDebug("\(XCTestWDDebugInfo.DebugLogPrefix) retrieving alert text \(text!)") 67 | return XCTestWDResponse.response(session: request.session!, value: JSON(text!)) 68 | } else { 69 | DDLogDebug("\(XCTestWDDebugInfo.DebugLogPrefix) retrieving alert text nil") 70 | return XCTestWDResponse.response(session: request.session!, error: WDStatus.NoAlertOpenError) 71 | } 72 | } 73 | } 74 | 75 | internal static func alertKeys(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 76 | if request.session == nil { 77 | return XCTestWDResponse.response(session: nil, error: WDStatus.SessionNotCreatedException) 78 | } else { 79 | let alert = XCTestWDAlert(request.session!.application) 80 | if alert.keys(input: request.params["text"] ?? "") { 81 | return XCTestWDResponse.response(session: request.session!, value: JSON(text!)) 82 | } else { 83 | return XCTestWDResponse.response(session: request.session!, error: WDStatus.NoAlertOpenError) 84 | } 85 | } 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/XCTestWDContextController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestAlertViewCommand.swift 3 | // XCTestWebdriver 4 | // 5 | // Created by zhaoy on 21/4/17. 6 | // Copyright © 2017 XCTestWebdriver. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | 12 | internal class XCTestWDContextController: Controller { 13 | 14 | //MARK: Controller - Protocol 15 | static func routes() -> [(RequestRoute, RoutingCall)] { 16 | return [(RequestRoute("/context", "get"), getContext), 17 | (RequestRoute("/context", "post"), setContext), 18 | (RequestRoute("/contexts", "get"), getContexts)] 19 | } 20 | 21 | static func shouldRegisterAutomatically() -> Bool { 22 | return false 23 | } 24 | 25 | //MARK: Routing Logic Specification 26 | internal static func getContext(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 27 | return HttpResponse.ok(.html("getContext")) 28 | } 29 | 30 | internal static func setContext(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 31 | return HttpResponse.ok(.html("setContext")) 32 | } 33 | 34 | internal static func getContexts(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 35 | return HttpResponse.ok(.html("getContexts")) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/XCTestWDExecuteController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestAlertViewCommand.swift 3 | // XCTestWebdriver 4 | // 5 | // Created by zhaoy on 21/4/17. 6 | // Copyright © 2017 XCTestWebdriver. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | 12 | internal class XCTestWDExecuteController: Controller { 13 | 14 | //MARK: Controller - Protocol 15 | static func routes() -> [(RequestRoute, RoutingCall)] { 16 | return [(RequestRoute("/execute", "post"), execute)] 17 | } 18 | 19 | static func shouldRegisterAutomatically() -> Bool { 20 | return false 21 | } 22 | 23 | //MARK: Routing Logic Specification 24 | internal static func execute(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 25 | return HttpResponse.ok(.html("execute")) 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/XCTestWDKeysController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestAlertViewCommand.swift 3 | // XCTestWebdriver 4 | // 5 | // Created by zhaoy on 21/4/17. 6 | // Copyright © 2017 XCTestWebdriver. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | 12 | internal class XCTestWDKeysController: Controller { 13 | 14 | //MARK: Controller - Protocol 15 | static func routes() -> [(RequestRoute, RoutingCall)] { 16 | return [(RequestRoute("/keys", "post"), keys)] 17 | } 18 | 19 | static func shouldRegisterAutomatically() -> Bool { 20 | return false 21 | } 22 | 23 | //MARK: Routing Logic Specification 24 | internal static func keys(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 25 | return HttpResponse.ok(.html("keys")) 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/XCTestWDMonkeyController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDMonkeyController.swift 3 | // FastMonkey 4 | // 5 | // Created by zhangzhao on 2017/7/17. 6 | // Copyright © 2017年 FastMonkey. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | import XCTest 12 | import SwiftyJSON 13 | 14 | 15 | internal class XCTestWDMonkeyController: Controller { 16 | 17 | //MARK: Controller - Protocol 18 | static func routes() -> [(RequestRoute, RoutingCall)] { 19 | return [(RequestRoute("/wd/hub/monkey", "post"), swiftmonkey), 20 | (RequestRoute("/wd/hub/appname", "get"), getappname) 21 | ] 22 | } 23 | 24 | static func shouldRegisterAutomatically() -> Bool { 25 | return false 26 | } 27 | 28 | internal static func getappname(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 29 | let application = request.session?.application ?? XCTestWDSessionManager.singleton.checkDefaultSession().application 30 | let name = XCTestWDFindElementUtils.getAppName(underElement: application!) 31 | return HttpResponse.ok(.html(name)) 32 | } 33 | 34 | 35 | //MARK: Routing Logic Specification 36 | internal static func swiftmonkey(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 37 | var app : XCUIApplication! 38 | var session : XCTestWDSession! 39 | 40 | let desiredCapabilities = request.jsonBody["desiredCapabilities"].dictionary 41 | let path = desiredCapabilities?["app"]?.string ?? nil 42 | let bundleID = desiredCapabilities?["bundleId"]?.string ?? nil 43 | if bundleID == nil { 44 | app = XCTestWDSession.activeApplication() 45 | } else { 46 | app = XCUIApplication.init(privateWithPath: path, bundleID: bundleID)! 47 | app!.launchArguments = desiredCapabilities?["arguments"]?.arrayObject as! [String]? ?? [String]() 48 | app!.launchEnvironment = desiredCapabilities?["environment"]?.dictionaryObject as! [String : String]? ?? [String:String](); 49 | app!.launch() 50 | } 51 | 52 | if app != nil { 53 | session = XCTestWDSession.sessionWithApplication(app!) 54 | XCTestWDSessionManager.singleton.mountSession(session) 55 | try? session.resolve() 56 | } 57 | 58 | if app?.processID == 0 { 59 | return HttpResponse.internalServerError 60 | } 61 | 62 | sleep(10) 63 | NSLog("XCTestWDSetup->start fastmonkey<-XCTestWDSetup") 64 | 65 | _ = app.descendants(matching: .any).element(boundBy: 0).frame 66 | let monkey = Monkey(frame: app.frame) 67 | monkey.addDefaultXCTestPrivateActions() 68 | monkey.addXCTestTapAlertAction(interval: 100, application: app) 69 | monkey.addXCTestCheckCurrentApp(interval: 10, application: app) 70 | //monkey.addXCTestAppLogin(interval: 50, application: app) 71 | monkey.monkeyAround() 72 | 73 | return XCTestWDResponse.response(session: session, value: sessionInformation(session)) 74 | } 75 | 76 | //MARK: Response helpers 77 | private static func sessionInformation(_ session:XCTestWDSession) -> JSON { 78 | var result:JSON = ["sessionId":session.identifier] 79 | var capabilities:JSON = ["device": UIDevice.current.userInterfaceIdiom == UIUserInterfaceIdiom.pad ? "ipad" : "iphone"] 80 | capabilities["sdkVersion"] = JSON(UIDevice.current.systemVersion) 81 | capabilities["browserName"] = JSON(session.application.label) 82 | capabilities["CFBundleIdentifier"] = JSON(session.application.bundleID ?? "Null") 83 | result["capabilities"] = capabilities 84 | return result 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/XCTestWDScreenshotController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestAlertViewCommand.swift 3 | // XCTestWebdriver 4 | // 5 | // Created by zhaoy on 21/4/17. 6 | // Copyright © 2017 XCTestWebdriver. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | import SwiftyJSON 12 | 13 | internal class XCTestWDScreenshotController: Controller { 14 | 15 | //MARK: Controller - Protocol 16 | static func routes() -> [(RequestRoute, RoutingCall)] { 17 | return [(RequestRoute("/wd/hub/screenshot", "get"), getScreenshot), 18 | (RequestRoute("/wd/hub/session/:sessionId/screenshot", "get"), getScreenshot)] 19 | } 20 | 21 | static func shouldRegisterAutomatically() -> Bool { 22 | return false 23 | } 24 | 25 | //MARK: Routing Logic Specification 26 | internal static func getScreenshot(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 27 | var base64String:String! 28 | let xcScreen:AnyClass? = NSClassFromString("XCUIScreen") 29 | if xcScreen != nil { 30 | let data = xcScreen?.value(forKeyPath: "mainScreen.screenshot.PNGRepresentation") as? NSData 31 | base64String = ((data?.base64EncodedString()))! 32 | } else { 33 | let data = (XCAXClient_iOS.sharedClient() as! XCAXClient_iOS).screenshotData() 34 | base64String = ((data?.base64EncodedString()))! 35 | } 36 | 37 | return XCTestWDResponse.response(session: request.session, value: JSON(base64String!)) 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/XCTestWDSessionController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestAlertViewCommand.swift 3 | // XCTestWebdriver 4 | // 5 | // Created by zhaoy on 21/4/17. 6 | // Copyright © 2017 XCTestWebdriver. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | import XCTest 12 | import SwiftyJSON 13 | import CocoaLumberjackSwift 14 | 15 | let XCTestWDSessionShutDown = "XCTestWDSessionShutDown" 16 | 17 | internal class XCTestWDSessionController: Controller { 18 | 19 | //MARK: Controller - Protocol 20 | static func routes() -> [(RequestRoute, RoutingCall)] { 21 | return [(RequestRoute("/wd/hub/session", "post"), createSession), 22 | (RequestRoute("/wd/hub/sessions", "get"), getSessions), 23 | (RequestRoute("/wd/hub/session/:sessionId", "delete"), delSession)] 24 | } 25 | 26 | static func shouldRegisterAutomatically() -> Bool { 27 | return false 28 | } 29 | 30 | //MARK: Routing Logic Specification 31 | internal static func createSession(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 32 | var app : XCUIApplication! 33 | var session : XCTestWDSession! 34 | 35 | let desiredCapabilities = request.jsonBody["desiredCapabilities"].dictionary 36 | let path = desiredCapabilities?["app"]?.string ?? nil 37 | let bundleID = desiredCapabilities?["bundleId"]?.string ?? nil 38 | 39 | if bundleID == nil { 40 | DDLogDebug("\(XCTestWDDebugInfo.DebugLogPrefix) bundle ID input is nil, create session with current active app") 41 | app = XCTestWDSession.activeApplication() 42 | } else { 43 | DDLogDebug("\(XCTestWDDebugInfo.DebugLogPrefix) create bundle from launching input") 44 | app = XCUIApplication.init(privateWithPath: path, bundleID: bundleID)! 45 | app!.launchArguments = desiredCapabilities?["arguments"]?.arrayObject as! [String]? ?? [String]() 46 | app!.launchEnvironment = desiredCapabilities?["environment"]?.dictionaryObject as! [String : String]? ?? [String:String](); 47 | app!.launch() 48 | sleep(1) 49 | } 50 | 51 | if app != nil { 52 | DDLogDebug("\(XCTestWDDebugInfo.DebugLogPrefix) create app failure ") 53 | session = XCTestWDSession.sessionWithApplication(app!) 54 | XCTestWDSessionManager.singleton.defaultSession = session; 55 | XCTestWDSessionManager.singleton.mountSession(session) 56 | session.resolve() 57 | } 58 | 59 | if app?.processID == 0 { 60 | return HttpResponse.internalServerError 61 | } 62 | 63 | return XCTestWDResponse.response(session: session, value: sessionInformation(session)) 64 | } 65 | 66 | internal static func getSessions(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 67 | return XCTestWDResponse.response(session: nil, value: sessionList()) 68 | } 69 | 70 | internal static func delSession(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 71 | return XCTestWDResponse.response(session: nil, value: removeSessionById(request.session?.identifier ?? "")) 72 | } 73 | 74 | //MARK: Response helpers 75 | private static func sessionInformation(_ session:XCTestWDSession) -> JSON { 76 | var result:JSON = ["sessionId":session.identifier] 77 | var capabilities:JSON = ["device": UIDevice.current.userInterfaceIdiom == UIUserInterfaceIdiom.pad ? "ipad" : "iphone"] 78 | capabilities["sdkVersion"] = JSON(UIDevice.current.systemVersion) 79 | capabilities["browserName"] = JSON(session.application.label) 80 | capabilities["CFBundleIdentifier"] = JSON(session.application.bundleID ?? "Null") 81 | result["capabilities"] = capabilities 82 | return result 83 | } 84 | 85 | private static func sessionList() -> JSON { 86 | var raw = [[String:String]]() 87 | let sessionMap = XCTestWDSessionManager.singleton.queryAll() 88 | for (sessionId, _) in sessionMap { 89 | raw.append(["id":sessionId]) 90 | } 91 | return JSON(raw) 92 | } 93 | 94 | private static func removeSessionById(_ sessionId:String) -> JSON { 95 | XCTestWDSessionManager.singleton.deleteSession(sessionId) 96 | return JSON("") 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/XCTestWDSourceController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestAlertViewCommand.swift 3 | // XCTestWebdriver 4 | // 5 | // Created by zhaoy on 21/4/17. 6 | // Copyright © 2017 XCTestWebdriver. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | import SwiftyJSON 12 | 13 | internal class XCTestWDSourceController: Controller { 14 | 15 | //MARK: Controller - Protocol 16 | static func routes() -> [(RequestRoute, RoutingCall)] { 17 | return [(RequestRoute("/wd/hub/session/:sessionId/source", "get"), source), 18 | (RequestRoute("/wd/hub/source", "get"), sourceWithoutSession), 19 | (RequestRoute("/wd/hub/session/:sessionId/accessibleSource", "get"), accessiblitySource), 20 | (RequestRoute("/wd/hub/accessibleSource", "get"), accessiblitySourceWithoutSession)] 21 | } 22 | 23 | static func shouldRegisterAutomatically() -> Bool { 24 | return false 25 | } 26 | 27 | //MARK: Routing Logic Specification 28 | internal static func source(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 29 | let _ = request.session?.application.query() 30 | request.session?.application.resolve() 31 | let temp = request.session?.application.tree() 32 | return XCTestWDResponse.response(session: request.session, value: JSON(JSON(temp!).rawString() ?? "")) 33 | } 34 | 35 | internal static func sourceWithoutSession(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 36 | let temp = XCTestWDSession.activeApplication()?.tree() 37 | return XCTestWDResponse.response(session: request.session, value: JSON(temp!)) 38 | } 39 | 40 | internal static func accessiblitySource(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 41 | let _ = request.session?.application.query() 42 | request.session?.application.resolve() 43 | let temp = request.session?.application.accessibilityTree() 44 | return XCTestWDResponse.response(session: request.session, value: JSON(JSON(temp!).rawString() ?? "")) 45 | } 46 | 47 | internal static func accessiblitySourceWithoutSession(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 48 | let temp = XCTestWDSessionManager.singleton.checkDefaultSession().application.accessibilityTree() 49 | return XCTestWDResponse.response(session: request.session, value: JSON(temp!)) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/XCTestWDStatusController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestAlertViewCommand.swift 3 | // XCTestWebdriver 4 | // 5 | // Created by zhaoy on 21/4/17. 6 | // Copyright © 2017 XCTestWebdriver. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | 12 | internal class XCTestWDStatusController: Controller { 13 | 14 | //MARK: Controller - Protocol 15 | static func routes() -> [(RequestRoute, RoutingCall)] { 16 | return [(RequestRoute("/wd/hub/status", "get"), status)] 17 | } 18 | 19 | static func shouldRegisterAutomatically() -> Bool { 20 | return false 21 | } 22 | 23 | //MARK: Routing Logic Specification 24 | internal static func status(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 25 | return HttpResponse.ok(.html("status")) 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/XCTestWDTimeoutController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestAlertViewCommand.swift 3 | // XCTestWebdriver 4 | // 5 | // Created by zhaoy on 21/4/17. 6 | // Copyright © 2017 XCTestWebdriver. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | 12 | internal class XCTestWDTimeoutController: Controller { 13 | 14 | //MARK: Controller - Protocol 15 | static func routes() -> [(RequestRoute, RoutingCall)] { 16 | return [(RequestRoute("/timeouts/implicit_wait", "post"), implicitWait)] 17 | } 18 | 19 | static func shouldRegisterAutomatically() -> Bool { 20 | return false 21 | } 22 | 23 | //MARK: Routing Logic Specification 24 | internal static func implicitWait(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 25 | return HttpResponse.ok(.html("implicitWait")) 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/XCTestWDTitleController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestAlertViewCommand.swift 3 | // XCTestWebdriver 4 | // 5 | // Created by zhaoy on 21/4/17. 6 | // Copyright © 2017 XCTestWebdriver. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | 12 | internal class XCTestWDTitleController: Controller { 13 | 14 | //MARK: Controller - Protocol 15 | static func routes() -> [(RequestRoute, RoutingCall)] { 16 | return [(RequestRoute("/title", "get"), title)] 17 | } 18 | 19 | static func shouldRegisterAutomatically() -> Bool { 20 | return false 21 | } 22 | 23 | //MARK: Routing Logic Specification 24 | internal static func title(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 25 | return HttpResponse.ok(.html("title")) 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/XCTestWDUrlController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestAlertViewCommand.swift 3 | // XCTestWebdriver 4 | // 5 | // Created by zhaoy on 21/4/17. 6 | // Copyright © 2017 XCTestWebdriver. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | 12 | internal class XCTestWDUrlController: Controller { 13 | 14 | //MARK: Controller - Protocol 15 | static func routes() -> [(RequestRoute, RoutingCall)] { 16 | return [(RequestRoute("/wd/hub/session/:sessionId/url", "post"), url), 17 | (RequestRoute("/wd/hub/session/:sessionId/url", "get"), getUrl), 18 | (RequestRoute("/wd/hub/session/:sessionId/forward", "post"), forward), 19 | (RequestRoute("/wd/hub/session/:sessionId/back", "post"), back), 20 | (RequestRoute("/wd/hub/session/:sessionId/refresh", "post"), refresh)] 21 | } 22 | 23 | static func shouldRegisterAutomatically() -> Bool { 24 | return false 25 | } 26 | 27 | //MARK: Routing Logic Specification 28 | internal static func url(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 29 | return HttpResponse.ok(.html("url")) 30 | } 31 | 32 | internal static func getUrl(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 33 | return HttpResponse.ok(.html("getUrl")) 34 | } 35 | 36 | internal static func forward(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 37 | return HttpResponse.ok(.html("forward")) 38 | } 39 | 40 | internal static func back(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 41 | let session = request.session ?? XCTestWDSessionManager.singleton.checkDefaultSession() 42 | let application = session.application 43 | if ((application?.navigationBars.buttons.count) ?? 0 > 0) { 44 | application?.navigationBars.buttons.element(boundBy: 0).tap() 45 | return XCTestWDResponse.response(session: nil, error: WDStatus.Success) 46 | } 47 | 48 | return XCTestWDResponse.response(session: nil, error: WDStatus.ElementIsNotSelectable) 49 | } 50 | 51 | internal static func refresh(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 52 | return HttpResponse.ok(.html("refresh")) 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Controllers/XCTestWDWindowController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestAlertViewCommand.swift 3 | // XCTestWebdriver 4 | // 5 | // Created by zhaoy on 21/4/17. 6 | // Copyright © 2017 XCTestWebdriver. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | import SwiftyJSON 12 | 13 | internal class XCTestWDWindowController: Controller { 14 | 15 | //MARK: Controller - Protocol 16 | static func routes() -> [(RequestRoute, RoutingCall)] { 17 | return [(RequestRoute("/wd/hub/session/:sessionId/window/current/size", "get"), getWindowSize)] 18 | } 19 | 20 | static func shouldRegisterAutomatically() -> Bool { 21 | return false 22 | } 23 | 24 | //MARK: Routing Logic Specification 25 | internal static func getWindowSize(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 26 | let application = XCTestWDSessionManager.singleton.checkDefaultSession().application 27 | let frame = application?.wdFrame() 28 | let screenSize = MathUtils.adjustDimensionsForApplication(frame!.size, UIDeviceOrientation.init(rawValue:(application?.interfaceOrientation.rawValue)!)!) 29 | 30 | return XCTestWDResponse.response(session: nil, value: JSON(["width":screenSize.width,"height":screenSize.height])) 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Modules/Extensions/XCTestWDFindElementUtils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDFindElementUtils.swift 3 | // XCTestWD 4 | // 5 | // fixed by zhangzhao on 8/1/17. 6 | // 7 | 8 | import Foundation 9 | 10 | class XCTestWDFindElementUtils { 11 | 12 | // TODO: provide alert filter here 13 | 14 | static func tree(underElement:XCUIElement) throws -> [CGPoint]? { 15 | return underElement.pageSourceToPoint() 16 | } 17 | 18 | static func getAppName(underElement:XCUIElement) -> String{ 19 | return underElement.rootName() 20 | } 21 | 22 | static func getAppPid() -> Int32{ 23 | let application = XCTestWDSession.activeApplication() 24 | let pid = application?.processID 25 | if pid == nil{ 26 | return 0 27 | } 28 | return pid! 29 | } 30 | 31 | static func filterElement(usingText:String, withvalue:String, underElement:XCUIElement) throws -> XCUIElement? { 32 | 33 | return try filterElements(usingText:usingText, withValue:withvalue, underElement:underElement, returnAfterFirstMatch:true)?.first 34 | } 35 | 36 | 37 | // Routing for xpath, class name, name, id 38 | static func filterElements(usingText:String, withValue:String, underElement:XCUIElement, returnAfterFirstMatch:Bool) throws -> [XCUIElement]? { 39 | 40 | let isSearchByIdentifier = (usingText == "name" || usingText == "id" || usingText == "accessibility id") 41 | 42 | if usingText == "xpath" { 43 | return underElement.descendantsMatchingXPathQuery(xpathQuery: withValue, 44 | returnAfterFirstMatch: returnAfterFirstMatch) 45 | } else if usingText == "class name" { 46 | return underElement.descendantsMatchingClassName(className: withValue, 47 | returnAfterFirstMatch: returnAfterFirstMatch) 48 | } else if isSearchByIdentifier { 49 | return underElement.descendantsMatchingIdentifier(accessibilityId: withValue, 50 | returnAfterFirstMatch: returnAfterFirstMatch) 51 | } 52 | 53 | throw XCTestWDRoutingError.noSuchUsingMethod 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Modules/Extensions/XCTestWDMathUtils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDMathUtils.swift 3 | // XCTestWD 4 | // 5 | // Created by zhaoy on 5/5/17. 6 | // Copyright © 2017 XCTestWD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class MathUtils { 12 | 13 | static func adjustDimensionsForApplication(_ actualSize:CGSize , _ orientation:UIDeviceOrientation) -> CGSize { 14 | if (orientation == UIDeviceOrientation.landscapeLeft || orientation == UIDeviceOrientation.landscapeRight) { 15 | /* 16 | There is an XCTest bug that application.frame property returns exchanged dimensions for landscape mode. 17 | This verification is just to make sure the bug is still there (since height is never greater than width in landscape) 18 | and to make it still working properly after XCTest itself starts to respect landscape mode. 19 | */ 20 | if (actualSize.height > actualSize.width) { 21 | return CGSize(width:actualSize.height, height:actualSize.width) 22 | } 23 | } 24 | return actualSize; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Modules/Extensions/XCTestWDXPath.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDXPath.swift 3 | // XCTestWD 4 | // 5 | // Created by zhaoy on 5/5/17. 6 | // Copyright © 2017 XCTestWD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import AEXML 11 | import Fuzi 12 | 13 | internal class XCTestWDXPath { 14 | 15 | //MARK: External API 16 | static let defaultTopDir = "top" 17 | 18 | static func xpathToList(_ root:XCElementSnapshot, _ xpathQuery:String) -> [CGPoint]? { 19 | 20 | var mapping = [String:XCElementSnapshot]() 21 | let xml = generateXMLPresentation(root,nil,nil,defaultTopDir,&mapping)?.xml 22 | if xml == nil 23 | {return nil} 24 | 25 | let tree = try? XMLDocument(string: xml!, encoding:String.Encoding.utf8) 26 | let nodes = tree?.xpath(xpathQuery) 27 | var list = [CGPoint]() 28 | for node in nodes! { 29 | if mapping[node.attr("private_indexPath")!] != nil{ 30 | let x = (node.attr("x")! as NSString).floatValue 31 | let y = (node.attr("y")! as NSString).floatValue 32 | if (x <= 0) && (y <= 0) 33 | {continue} 34 | 35 | let snapshot = mapping[node.attr("private_indexPath")!] 36 | let isvisible = try? snapshot?.isWDVisible() 37 | if isvisible == nil || isvisible! == false 38 | {continue} 39 | 40 | let w = (node.attr("width")! as NSString).floatValue 41 | let h = (node.attr("height")! as NSString).floatValue 42 | let cX = Int(x + w/2) 43 | let cY = Int(y + h/2) 44 | let point = CGPoint(x:cX,y:cY) 45 | if list.contains(point) == false { 46 | list.append(point) 47 | } 48 | } 49 | } 50 | return list 51 | } 52 | 53 | static func findMatchesIn(_ root:XCElementSnapshot, _ xpathQuery:String) -> [XCElementSnapshot]? { 54 | 55 | var mapping = [String:XCElementSnapshot]() 56 | let documentXml = generateXMLPresentation(root, 57 | nil, 58 | nil, 59 | defaultTopDir, 60 | &mapping)?.xml 61 | 62 | if documentXml == nil { 63 | return nil 64 | } 65 | 66 | 67 | let document = try? XMLDocument(string: documentXml!, encoding:String.Encoding.utf8) 68 | let nodes = document?.xpath(xpathQuery) 69 | var results = [XCElementSnapshot]() 70 | for node in nodes! { 71 | if mapping[node.attr("private_indexPath")!] != nil { 72 | results.append(mapping[node.attr("private_indexPath")!]!) 73 | } 74 | } 75 | 76 | return results 77 | } 78 | 79 | //MARK: Internal Utils 80 | static func generateXMLPresentation(_ root:XCElementSnapshot, _ parentElement:AEXMLElement?, _ writingDocument:AEXMLDocument?, _ indexPath:String, _ mapping: inout [String:XCElementSnapshot]) -> AEXMLDocument? { 81 | 82 | let elementName = XCUIElementTypeTransformer.singleton.stringWithElementType(root.elementType) 83 | let currentElement = AEXMLElement(name:elementName) 84 | recordAttributeForElement(root, currentElement, indexPath) 85 | 86 | let document : AEXMLDocument! 87 | if parentElement == nil || writingDocument == nil { 88 | document = AEXMLDocument() 89 | document.addChild(currentElement) 90 | } else { 91 | document = writingDocument! 92 | parentElement?.addChild(currentElement) 93 | } 94 | 95 | var index = 0; 96 | for child in root.children { 97 | let childSnapshot = child as! XCElementSnapshot 98 | let childIndexPath = indexPath.appending(",\(index)") 99 | index += 1 100 | mapping[childIndexPath] = childSnapshot 101 | 102 | _ = generateXMLPresentation(childSnapshot, currentElement, document, childIndexPath, &mapping) 103 | } 104 | 105 | return document 106 | } 107 | 108 | static func recordAttributeForElement(_ snapshot:XCElementSnapshot, _ currentElement:AEXMLElement, _ indexPath:String?) { 109 | 110 | currentElement.attributes["type"] = XCUIElementTypeTransformer.singleton.stringWithElementType(snapshot.elementType) 111 | 112 | if snapshot.wdValue() != nil { 113 | let value = snapshot.wdValue()! 114 | if let str = value as? String { 115 | currentElement.attributes["value"] = str 116 | } else if let bin = value as? Bool { 117 | currentElement.attributes["value"] = bin ? "1":"0"; 118 | } else { 119 | currentElement.attributes["value"] = (value as AnyObject).debugDescription 120 | } 121 | } 122 | 123 | if snapshot.wdName() != nil { 124 | currentElement.attributes["name"] = snapshot.wdName()! 125 | } 126 | 127 | if snapshot.wdLabel() != nil { 128 | currentElement.attributes["label"] = snapshot.wdLabel()! 129 | } 130 | 131 | currentElement.attributes["enabled"] = snapshot.isWDEnabled() ? "true":"false" 132 | 133 | let rect = snapshot.wdRect() 134 | for key in ["x","y","width","height"] { 135 | currentElement.attributes[key] = rect[key]!.description 136 | } 137 | 138 | if indexPath != nil { 139 | currentElement.attributes["private_indexPath"] = indexPath! 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Modules/Utils/XCTestWDApplicationTree.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDApplicationTree.swift 3 | // XCTestWD 4 | // 5 | // Created by zhaoy on 5/5/17. 6 | // Copyright © 2017 XCTestWD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftyJSON 11 | 12 | extension XCUIApplication { 13 | 14 | func mainWindowSnapshot() -> XCElementSnapshot? { 15 | let mainWindows = (self.lastSnapshot() as! XCElementSnapshot).descendantsByFiltering { (snapshot) -> Bool in 16 | return snapshot?.isMainWindow ?? false 17 | } 18 | return mainWindows?.last 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Modules/XCTestWDAlert.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDAlert.swift 3 | // XCTestWD 4 | // 5 | // Created by zhaoy on 27/4/17. 6 | // Copyright © 2017 XCTestWD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | internal class XCTestWDAlert { 12 | 13 | private let application:XCUIApplication! 14 | 15 | init(_ application:XCUIApplication) { 16 | self.application = application 17 | } 18 | 19 | //MARK: Commands 20 | 21 | //TODO: works on XPATH and then works on getting text 22 | internal func text() -> String? { 23 | 24 | let alertElement = self.alertElement() 25 | if alertElement != nil { 26 | return nil 27 | } 28 | 29 | return nil 30 | } 31 | //TODO: works on XPATH and then works on getting this 32 | internal func keys(input: String) -> Bool { 33 | 34 | return false 35 | } 36 | 37 | internal func accept() -> Bool { 38 | 39 | let alertElement = self.alertElement() 40 | let buttons = self.alertElement()?.descendants(matching: XCUIElement.ElementType.button).allElementsBoundByIndex 41 | var defaultButton:XCUIElement? 42 | 43 | if alertElement?.elementType == XCUIElement.ElementType.alert { 44 | defaultButton = (buttons?.last) 45 | } else { 46 | defaultButton = (buttons?.first) 47 | } 48 | 49 | if defaultButton != nil { 50 | defaultButton?.tap() 51 | return true 52 | } 53 | 54 | return false 55 | } 56 | 57 | internal func dismiss() -> Bool { 58 | 59 | let alertElement = self.alertElement() 60 | let buttons = self.alertElement()?.descendants(matching: XCUIElement.ElementType.button).allElementsBoundByIndex 61 | var defaultButton:XCUIElement? 62 | 63 | if alertElement?.elementType == XCUIElement.ElementType.alert { 64 | defaultButton = (buttons?.first) 65 | } else { 66 | defaultButton = (buttons?.last) 67 | } 68 | 69 | if defaultButton != nil { 70 | defaultButton?.tap() 71 | return true 72 | } 73 | 74 | return false 75 | } 76 | 77 | //MARK: Utils 78 | private func alertElement() -> XCUIElement? { 79 | var alert = self.application.alerts.element 80 | // Check default alerts exists 81 | if !(alert.exists) { 82 | alert = self.application.sheets.element 83 | // Check actionsheet exists 84 | if !(alert.exists) { 85 | let sprintboard = XCUIApplication.init(privateWithPath: nil, bundleID: "com.apple.springboard") 86 | alert = (sprintboard?.alerts.element) ?? alert 87 | if !(alert.exists) { 88 | return nil 89 | } 90 | } 91 | } 92 | 93 | alert.resolve() 94 | self.application.query() 95 | self.application.resolve() 96 | return alert 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Modules/XCTestWDErrors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDErrors.swift 3 | // XCTestWD 4 | // 5 | // Created by zhaoy on 11/5/17. 6 | // Copyright © 2017 XCTestWD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum XCTestWDRoutingError: Error { 12 | case noSuchUsingMethod 13 | } 14 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Modules/XCTestWDReponse.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDReponse.swift 3 | // XCTestWD 4 | // 5 | // Created by zhaoy on 24/4/17. 6 | // Copyright © 2017 XCTestWD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftyJSON 11 | import Swifter 12 | 13 | internal class XCTestWDResponse { 14 | 15 | //MARK: Model & Constructor 16 | private var sessionId:String! 17 | private var status:WDStatus! 18 | private var value:JSON? 19 | 20 | private init(_ sessionId:String, _ status:WDStatus, _ value:JSON?) { 21 | self.sessionId = sessionId 22 | self.status = status 23 | self.value = value ?? JSON("") 24 | } 25 | 26 | private func response() -> HttpResponse { 27 | let response : JSON = ["sessionId":self.sessionId, 28 | "status":self.status.rawValue, 29 | "value":self.value as Any] 30 | let rawString = response.rawString(options:[])?.replacingOccurrences(of: "\n", with: "") 31 | return rawString != nil ? HttpResponse.ok(.text(rawString!)) : HttpResponse.ok(.text("{}")) 32 | } 33 | 34 | //MARK: Utils 35 | static func response(session:XCTestWDSession?, value:JSON?) -> HttpResponse { 36 | return XCTestWDResponse(session?.identifier ?? "", WDStatus.Success, value ?? JSON("{}")).response() 37 | } 38 | 39 | static func response(session:XCTestWDSession? ,error:WDStatus) -> HttpResponse { 40 | return XCTestWDResponse(session?.identifier ?? "", error, nil).response() 41 | } 42 | 43 | //MARK: Element Response 44 | static func responseWithCacheElement(_ element:XCUIElement, _ elementCache:XCTestWDElementCache) -> HttpResponse { 45 | let elementUUID = elementCache.storeElement(element) 46 | return getResponseFromDictionary(dictionaryWithElement(element, elementUUID, false)) 47 | } 48 | 49 | static func responsWithCacheElements(_ elements:[XCUIElement], _ elementCache:XCTestWDElementCache) -> HttpResponse { 50 | var response = [[String:String]]() 51 | for element in elements { 52 | let elementUUID = elementCache.storeElement(element) 53 | response.append(dictionaryWithElement(element, elementUUID, false)) 54 | } 55 | return XCTestWDResponse.response(session: nil, value: JSON(response)) 56 | } 57 | 58 | // ------------ Internal Method --------- 59 | private static func dictionaryWithElement(_ element:XCUIElement, _ elementUUID:String, _ compact:Bool) -> [String:String] { 60 | var dictionary = [String:String](); 61 | dictionary["ELEMENT"] = elementUUID 62 | 63 | if compact == false { 64 | dictionary["label"] = element.wdLabel() 65 | dictionary["type"] = element.wdType() 66 | } 67 | 68 | return dictionary 69 | } 70 | 71 | private static func getResponseFromDictionary(_ dictionary:[String:String]) -> HttpResponse { 72 | return XCTestWDResponse.response(session:nil, value:JSON(dictionary)) 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Modules/XCTestWDSession.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDSession.swift 3 | // XCTestWD 4 | // 5 | // Created by zhaoy on 23/4/17. 6 | // Copyright © 2017 XCTestWD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | import SwiftyJSON 12 | import CocoaLumberjackSwift 13 | 14 | //MARK: Session & Cache for XCUIElement 15 | internal class XCTestWDElementCache 16 | { 17 | 18 | private var cache = [String: XCUIElement]() 19 | 20 | // Returns UUID of the stored element 21 | func storeElement(_ element:XCUIElement) -> String { 22 | let uuid = UUID.init().uuidString 23 | cache[uuid] = element 24 | return uuid 25 | } 26 | 27 | // Returns cached element 28 | func elementForUUID(_ uuid:String?) -> XCUIElement? { 29 | if uuid == nil { 30 | return nil 31 | } 32 | return cache[uuid!] 33 | } 34 | } 35 | 36 | public class XCTestWDSession { 37 | 38 | var identifier: String! 39 | private var _application: XCUIApplication! 40 | var application: XCUIApplication! { 41 | get { 42 | // Add protection for application resolve. only when application status active cam execute this 43 | if _application.accessibilityActivate() == true { 44 | resolve() 45 | } 46 | return _application 47 | } 48 | set { 49 | _application = newValue 50 | } 51 | } 52 | 53 | static func sessionWithApplication(_ application: XCUIApplication) -> XCTestWDSession { 54 | 55 | let session = XCTestWDSession() 56 | session.application = application 57 | session.identifier = UUID.init().uuidString 58 | 59 | return session 60 | } 61 | 62 | static func activeApplication() -> XCUIApplication? 63 | { 64 | return XCTestWDApplication.activeApplication() 65 | } 66 | 67 | func resolve() { 68 | self._application.query() 69 | self._application.resolve() 70 | } 71 | } 72 | 73 | //MARK: Multi-Session Control 74 | public class XCTestWDSessionManager { 75 | 76 | public static let singleton = XCTestWDSessionManager() 77 | static let commonCache: XCTestWDElementCache = XCTestWDElementCache() 78 | 79 | private var sessionMapping = [String: XCTestWDSession]() 80 | var defaultSession:XCTestWDSession? 81 | 82 | func mountSession(_ session: XCTestWDSession) { 83 | sessionMapping[session.identifier] = session 84 | } 85 | 86 | func querySession(_ identifier:String) -> XCTestWDSession? { 87 | return sessionMapping[identifier] 88 | } 89 | 90 | func checkDefaultSession() -> XCTestWDSession { 91 | if self.defaultSession == nil || self.defaultSession?.application.state != XCUIApplication.State.runningForeground { 92 | DDLogDebug("\(XCTestWDDebugInfo.DebugLogPrefix) current application not active, reloading active application") 93 | sleep(3) 94 | let application = XCTestWDSession.activeApplication() 95 | self.defaultSession = XCTestWDSession.sessionWithApplication(application!) 96 | self.defaultSession?.resolve() 97 | } 98 | 99 | return self.defaultSession! 100 | } 101 | 102 | func queryAll() -> [String:XCTestWDSession] { 103 | return sessionMapping 104 | } 105 | 106 | public func clearAll() { 107 | sessionMapping.removeAll() 108 | } 109 | 110 | func deleteSession(_ sessionId:String) { 111 | sessionMapping.removeValue(forKey: sessionId) 112 | NotificationCenter.default.post(name: NSNotification.Name(XCTestWDSessionShutDown), object: nil) 113 | } 114 | } 115 | 116 | //MARK: Extension 117 | extension HttpRequest { 118 | var session: XCTestWDSession? { 119 | get { 120 | if self.params["sessionId"] != nil && XCTestWDSessionManager.singleton.querySession(self.params["sessionId"]!) != nil { 121 | return XCTestWDSessionManager.singleton.querySession(self.params["sessionId"]!) 122 | } else if self.path.contains("/session/") { 123 | let components = self.path.components(separatedBy:"/") 124 | let index = components.index(of: "session")! 125 | if index >= components.count - 1 { 126 | DDLogDebug("\(XCTestWDDebugInfo.DebugLogPrefix) session can't be at the last component in the whole path") 127 | return nil 128 | } 129 | return XCTestWDSessionManager.singleton.querySession(components[index + 1]) 130 | } else { 131 | DDLogDebug("\(XCTestWDDebugInfo.DebugLogPrefix) no session id in current request") 132 | return nil 133 | } 134 | } 135 | } 136 | 137 | var elementId: String? { 138 | get { 139 | if self.path.contains("/element/") { 140 | let components = self.path.components(separatedBy:"/") 141 | let index = components.index(of: "element")! 142 | if index < components.count - 1 { 143 | return components[index + 1] 144 | } 145 | } 146 | 147 | DDLogDebug("\(XCTestWDDebugInfo.DebugLogPrefix) no element id retrieved from current query") 148 | return nil 149 | } 150 | } 151 | 152 | var jsonBody:JSON { 153 | get { 154 | return (try? JSON(data: NSData(bytes: &self.body, length: self.body.count) as Data)) ?? JSON(parseJSON: "{}") 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Modules/XCTestWDStatus.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDStatus.swift 3 | // XCTestWD 4 | // 5 | // Created by zhaoy on 24/4/17. 6 | // Copyright © 2017 XCTestWD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum WDStatus: Int { 12 | case 13 | Success = 0, 14 | NoSuchElement = 7, 15 | NoSuchFrame = 8, 16 | UnknownCommand = 9, 17 | StaleElementReference = 10, 18 | ElementNotVisible = 11, 19 | InvalidElementState = 12, 20 | UnknownError = 13, 21 | ElementIsNotSelectable = 15, 22 | JavaScriptError = 17, 23 | XPathLookupError = 19, 24 | Timeout = 21, 25 | NoSuchWindow = 23, 26 | InvalidCookieDomain = 24, 27 | UnableToSetCookie = 25, 28 | UnexpectedAlertOpen = 26, 29 | NoAlertOpenError = 27, 30 | ScriptTimeout = 28, 31 | InvalidElementCoordinates = 29, 32 | IMENotAvailable = 30, 33 | IMEEngineActivationFailed = 31, 34 | InvalidSelector = 32, 35 | SessionNotCreatedException = 33, 36 | MoveTargetOutOfBounds = 34 37 | 38 | static func evaluate(_ status:WDStatus) -> String { 39 | switch status { 40 | 41 | case .Success: 42 | return "The command executed successfully" 43 | 44 | case .NoSuchElement: 45 | return "An element could not be located on the page using the given search parameters." 46 | 47 | case .NoSuchFrame: 48 | return "A request to switch to a frame could not be satisfied because the frame could not be found." 49 | 50 | case .UnknownCommand: 51 | return "The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource." 52 | 53 | case .StaleElementReference: 54 | return "An element command failed because the referenced element is no longer attached to the DOM." 55 | 56 | case .ElementNotVisible: 57 | return "An element command could not be completed because the element is not visible on the page." 58 | 59 | case .InvalidElementState: 60 | return "An element command could not be completed because the element is in an invalid state (e.g. attempting to click a disabled element)." 61 | 62 | case .UnknownError: 63 | return "An unknown server-side error occurred while processing the command." 64 | 65 | case .ElementIsNotSelectable: 66 | return "An attempt was made to select an element that cannot be selected." 67 | 68 | case .JavaScriptError: 69 | return "An error occurred while executing user supplied JavaScript." 70 | 71 | case .XPathLookupError: 72 | return "An error occurred while searching for an element by XPath." 73 | 74 | case .Timeout: 75 | return "An operation did not complete before its timeout expired." 76 | 77 | case .NoSuchWindow: 78 | return "A request to switch to a different window could not be satisfied because the window could not be found." 79 | 80 | case .InvalidCookieDomain: 81 | return "An illegal attempt was made to set a cookie under a different domain than the current page." 82 | 83 | case .UnableToSetCookie: 84 | return "A request to set a cookie's value could not be satisfied." 85 | 86 | case .UnexpectedAlertOpen: 87 | return "A modal dialog was open, blocking this operation." 88 | 89 | case .NoAlertOpenError: 90 | return "An attempt was made to operate on a modal dialog when one was not open." 91 | 92 | case .ScriptTimeout: 93 | return "A script did not complete before its timeout expired." 94 | 95 | case .InvalidElementCoordinates: 96 | return "The coordinates provided to an interactions operation are invalid." 97 | 98 | case .IMENotAvailable: 99 | return "IME was not available." 100 | 101 | case .IMEEngineActivationFailed: 102 | return "An IME engine could not be started." 103 | 104 | case .InvalidSelector: 105 | return "Argument was an invalid selector (e.g. XPath/CSS)." 106 | 107 | case .SessionNotCreatedException: 108 | return "Session Not Created Exception" 109 | 110 | case .MoveTargetOutOfBounds: 111 | return "Move Target Out Of Bounds" 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/Modules/XCUIElementTypeTransformer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCUIElementTypeTransformer.swift 3 | // XCTestWD 4 | // 5 | // Created by zhaoy on 29/4/17. 6 | // Copyright © 2017 XCTestWD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class XCUIElementTypeTransformer { 12 | 13 | var elementStringMapping:[UInt:String] 14 | var stringElementMapping:[String:UInt] 15 | 16 | static let singleton = XCUIElementTypeTransformer() 17 | 18 | private init() { 19 | elementStringMapping = [ 20 | 0 : "XCUIElementTypeAny", 21 | 1 : "XCUIElementTypeOther", 22 | 2 : "XCUIElementTypeApplication", 23 | 3 : "XCUIElementTypeGroup", 24 | 4 : "XCUIElementTypeWindow", 25 | 5 : "XCUIElementTypeSheet", 26 | 6 : "XCUIElementTypeDrawer", 27 | 7 : "XCUIElementTypeAlert", 28 | 8 : "XCUIElementTypeDialog", 29 | 9 : "XCUIElementTypeButton", 30 | 10 : "XCUIElementTypeRadioButton", 31 | 11 : "XCUIElementTypeRadioGroup", 32 | 12 : "XCUIElementTypeCheckBox", 33 | 13 : "XCUIElementTypeDisclosureTriangle", 34 | 14 : "XCUIElementTypePopUpButton", 35 | 15 : "XCUIElementTypeComboBox", 36 | 16 : "XCUIElementTypeMenuButton", 37 | 17 : "XCUIElementTypeToolbarButton", 38 | 18 : "XCUIElementTypePopover", 39 | 19 : "XCUIElementTypeKeyboard", 40 | 20 : "XCUIElementTypeKey", 41 | 21 : "XCUIElementTypeNavigationBar", 42 | 22 : "XCUIElementTypeTabBar", 43 | 23 : "XCUIElementTypeTabGroup", 44 | 24 : "XCUIElementTypeToolbar", 45 | 25 : "XCUIElementTypeStatusBar", 46 | 26 : "XCUIElementTypeTable", 47 | 27 : "XCUIElementTypeTableRow", 48 | 28 : "XCUIElementTypeTableColumn", 49 | 29 : "XCUIElementTypeOutline", 50 | 30 : "XCUIElementTypeOutlineRow", 51 | 31 : "XCUIElementTypeBrowser", 52 | 32 : "XCUIElementTypeCollectionView", 53 | 33 : "XCUIElementTypeSlider", 54 | 34 : "XCUIElementTypePageIndicator", 55 | 35 : "XCUIElementTypeProgressIndicator", 56 | 36 : "XCUIElementTypeActivityIndicator", 57 | 37 : "XCUIElementTypeSegmentedControl", 58 | 38 : "XCUIElementTypePicker", 59 | 39 : "XCUIElementTypePickerWheel", 60 | 40 : "XCUIElementTypeSwitch", 61 | 41 : "XCUIElementTypeToggle", 62 | 42 : "XCUIElementTypeLink", 63 | 43 : "XCUIElementTypeImage", 64 | 44 : "XCUIElementTypeIcon", 65 | 45 : "XCUIElementTypeSearchField", 66 | 46 : "XCUIElementTypeScrollView", 67 | 47 : "XCUIElementTypeScrollBar", 68 | 48 : "XCUIElementTypeStaticText", 69 | 49 : "XCUIElementTypeTextField", 70 | 50 : "XCUIElementTypeSecureTextField", 71 | 51 : "XCUIElementTypeDatePicker", 72 | 52 : "XCUIElementTypeTextView", 73 | 53 : "XCUIElementTypeMenu", 74 | 54 : "XCUIElementTypeMenuItem", 75 | 55 : "XCUIElementTypeMenuBar", 76 | 56 : "XCUIElementTypeMenuBarItem", 77 | 57 : "XCUIElementTypeMap", 78 | 58 : "XCUIElementTypeWebView", 79 | 59 : "XCUIElementTypeIncrementArrow", 80 | 60 : "XCUIElementTypeDecrementArrow", 81 | 61 : "XCUIElementTypeTimeline", 82 | 62 : "XCUIElementTypeRatingIndicator", 83 | 63 : "XCUIElementTypeValueIndicator", 84 | 64 : "XCUIElementTypeSplitGroup", 85 | 65 : "XCUIElementTypeSplitter", 86 | 66 : "XCUIElementTypeRelevanceIndicator", 87 | 67 : "XCUIElementTypeColorWell", 88 | 68 : "XCUIElementTypeHelpTag", 89 | 69 : "XCUIElementTypeMatte", 90 | 70 : "XCUIElementTypeDockItem", 91 | 71 : "XCUIElementTypeRuler", 92 | 72 : "XCUIElementTypeRulerMarker", 93 | 73 : "XCUIElementTypeGrid", 94 | 74 : "XCUIElementTypeLevelIndicator", 95 | 75 : "XCUIElementTypeCell", 96 | 76 : "XCUIElementTypeLayoutArea", 97 | 77 : "XCUIElementTypeLayoutItem", 98 | 78 : "XCUIElementTypeHandle", 99 | 79 : "XCUIElementTypeStepper", 100 | 80 : "XCUIElementTypeTab"] 101 | 102 | stringElementMapping = [String:UInt]() 103 | for (key, value) in elementStringMapping { 104 | stringElementMapping[value] = key 105 | } 106 | } 107 | 108 | func elementTypeWithTypeName(_ typeName:String) -> XCUIElement.ElementType { 109 | return XCUIElement.ElementType(rawValue: stringElementMapping[typeName]!)! 110 | } 111 | 112 | func stringWithElementType(_ elementType:XCUIElement.ElementType) -> String { 113 | return elementStringMapping[elementType.rawValue]! 114 | } 115 | 116 | func shortStringWithElementType(_ elementType:XCUIElement.ElementType) -> String { 117 | return stringWithElementType(elementType).replacingOccurrences(of: "XCUIElementType", with: "") 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/XCTestWDController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestCommandHandler.swift 3 | // XCTestWebdriver 4 | // 5 | // Created by zhaoy on 21/4/17. 6 | // Copyright © 2017 XCTestWebdriver. All rights reserved. 7 | // 8 | 9 | import Swifter 10 | 11 | class RequestRoute: Hashable, Equatable { 12 | 13 | internal var path:String! 14 | internal var verb:String! 15 | internal var requiresSession:Bool 16 | 17 | init(_ path:String , _ verb:String = "GET", _ requiresSession:Bool = true) { 18 | self.path = path 19 | self.verb = verb 20 | self.requiresSession = requiresSession 21 | } 22 | 23 | public var hashValue: Int { 24 | get { 25 | return "\(path)_\(verb)_\(requiresSession)".hashValue 26 | } 27 | } 28 | 29 | public static func ==(lhs: RequestRoute, rhs: RequestRoute) -> Bool { 30 | return lhs.path == rhs.path && lhs.verb == rhs.verb && lhs.requiresSession == rhs.requiresSession 31 | } 32 | } 33 | 34 | typealias RoutingCall = ((Swifter.HttpRequest) -> Swifter.HttpResponse) 35 | 36 | internal protocol Controller { 37 | 38 | static func routes() -> [(RequestRoute, RoutingCall)] 39 | 40 | static func shouldRegisterAutomatically() -> Bool 41 | 42 | } 43 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/XCTestWDDispatch.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDDispatch.swift 3 | // XCTestWD 4 | // 5 | // Created by zhaoy on 25/4/17. 6 | // Copyright © 2017 XCTestWD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | 12 | //MARK: synchronous execution on main 13 | func SyncOnMain(_ executionBlock:(()->(HttpResponse))!) -> HttpResponse { 14 | var response: HttpResponse = HttpResponse.internalServerError 15 | DispatchQueue.main.sync { 16 | response = executionBlock() 17 | } 18 | return response 19 | } 20 | 21 | func RouteOnMain(_ routingCall:@escaping RoutingCall) -> RoutingCall { 22 | return { (request: HttpRequest) -> HttpResponse in 23 | var response:HttpResponse = HttpResponse.internalServerError 24 | DispatchQueue.main.sync { 25 | response = routingCall(request) 26 | } 27 | return response 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/XCTestWDFailureProofTestCase.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDFailureProofTestCase.swift 3 | // XCTestWD 4 | // 5 | // Created by SamuelZhaoY on 3/10/18. 6 | // Copyright © 2018 XCTestWD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | 12 | open class XCTestWDFailureProofTest : XCTestCase 13 | { 14 | override open func setUp() { 15 | super.setUp() 16 | continueAfterFailure = true; 17 | internalImplementation = XCTestWDImplementationFailureHoldingProxy.proxy(with: self.internalImplementation) 18 | } 19 | 20 | override open func recordFailure(withDescription description: String, inFile filePath: String, atLine lineNumber: Int, expected: Bool) { 21 | print("catching internal failure: \(description) in file: \(filePath) at line: \(lineNumber)") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/XCTestWDMonkey.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDMonkey.swift 3 | // XCTestWD 4 | // 5 | // Created by zhangzhao on 2017/8/29. 6 | // Copyright © 2017年 FastMonkey. All rights reserved. 7 | 8 | 9 | import Foundation 10 | 11 | public class XCTestWDMonkey { 12 | public init() { 13 | 14 | } 15 | public func startMonkey() -> Int { 16 | 17 | let bundleID = "com.pandatv.test.meizi" 18 | 19 | var app : XCUIApplication! 20 | var session : XCTestWDSession! 21 | let path :String? = nil 22 | app = XCUIApplication.init(privateWithPath: path, bundleID: bundleID)! 23 | app!.launch() 24 | 25 | if app != nil { 26 | session = XCTestWDSession.sessionWithApplication(app!) 27 | XCTestWDSessionManager.singleton.mountSession(session) 28 | try? session.resolve() 29 | } 30 | 31 | if app?.processID == 0 { 32 | return -1 33 | } 34 | 35 | sleep(4) 36 | NSLog("XCTestWDSetup->start fastmonkey<-XCTestWDSetup") 37 | 38 | _ = app.descendants(matching: .any).element(boundBy: 0).frame 39 | let monkey = Monkey(frame: app.frame) 40 | monkey.addDefaultXCTestPrivateActions() 41 | monkey.addXCTestTapAlertAction(interval: 100, application: app) 42 | monkey.addXCTestCheckCurrentApp(interval: 10, application: app) 43 | //monkey.addXCTestAppLogin(interval: 50, application: app) 44 | monkey.monkeyAround() 45 | RunLoop.main.run() 46 | return 0 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Server/XCTestWDServer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWebDriverServer.swift 3 | // XCTestWebdriver 4 | // 5 | // Created by zhaoy on 21/4/17. 6 | // Copyright © 2017 XCTestWebdriver. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Swifter 11 | import CocoaLumberjackSwift 12 | 13 | struct XCTestWDDebugInfo { 14 | static let DebugLogPrefix = "XCTestWD-Debug-Info: \n" 15 | } 16 | 17 | public class XCTestWDServer { 18 | 19 | private let server = HttpServer() 20 | 21 | public init() { 22 | NSLog("initializing wd server") 23 | NSLog("check log dir @:\( NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true) )") 24 | setupLog() 25 | } 26 | 27 | public func startServer() { 28 | do { 29 | try server.start(fetchPort()) 30 | registerRouters() 31 | 32 | NSLog("\(Bundle.main.bundleIdentifier!)") 33 | NSLog("XCTestWDSetup->http://localhost:\(try! server.port())<-XCTestWDSetup") 34 | 35 | RunLoop.main.run() 36 | } catch { 37 | NSLog("Server start error: \(error)") 38 | } 39 | } 40 | 41 | public func stopServer() { 42 | server.stop() 43 | } 44 | 45 | private func setupLog() { 46 | DDLog.add(DDTTYLogger.sharedInstance) 47 | DDLog.add(DDASLLogger.sharedInstance) 48 | 49 | let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true) 50 | let logDir = "\(paths[0])/Logs" 51 | let ddLogFileManager : DDLogFileManagerDefault = DDLogFileManagerDefault.init(logsDirectory: logDir) 52 | let fileLogger: DDFileLogger = DDFileLogger.init(logFileManager: ddLogFileManager) 53 | fileLogger.rollingFrequency = TimeInterval(60*60*24) 54 | fileLogger.logFileManager.maximumNumberOfLogFiles = 7 55 | DDLog.add(fileLogger) 56 | DDLogError("\(XCTestWDDebugInfo.DebugLogPrefix)setup debug log") 57 | } 58 | 59 | private func registerRouters() { 60 | 61 | var controllers = [Controller]() 62 | 63 | controllers.append(XCTestWDAlertController()) 64 | controllers.append(XCTestWDElementController()) 65 | controllers.append(XCTestWDScreenshotController()) 66 | controllers.append(XCTestWDSessionController()) 67 | controllers.append(XCTestWDSourceController()) 68 | controllers.append(XCTestWDTitleController()) 69 | controllers.append(XCTestWDElementController()) 70 | controllers.append(XCTestWDWindowController()) 71 | controllers.append(XCTestWDUrlController()) 72 | 73 | for controller in controllers { 74 | let routes = Swift.type(of: controller).routes() 75 | for i in 0...routes.count - 1 { 76 | let (router, requestHandler) = routes[i] 77 | var routeMethod: HttpServer.MethodRoute? 78 | 79 | switch router.verb { 80 | case "post","POST": 81 | routeMethod = server.POST 82 | break 83 | case "get","GET": 84 | routeMethod = server.GET 85 | break 86 | case "put", "PUT": 87 | routeMethod = server.PUT 88 | break 89 | case "delete", "DELETE": 90 | routeMethod = server.DELETE 91 | break 92 | case "update", "UPDATE": 93 | routeMethod = server.UPDATE 94 | break 95 | default: 96 | routeMethod = nil 97 | break 98 | } 99 | 100 | routeMethod?[router.path] = RouteOnMain(requestHandler) 101 | } 102 | } 103 | } 104 | 105 | private func fetchPort() -> in_port_t { 106 | 107 | let arguments = ProcessInfo.processInfo.arguments 108 | let index = arguments.index(of: "--port") 109 | var startingPort:Int = Int(portNumber()) 110 | if index != nil { 111 | if index! != NSNotFound || index! < arguments.count - 1{ 112 | startingPort = Int(arguments[index!+1])! 113 | } 114 | } 115 | 116 | var (isValid, _) = checkTcpPortForListen(port: in_port_t(startingPort)) 117 | while isValid == false { 118 | startingPort = startingPort + 1 119 | (isValid, _) = checkTcpPortForListen(port: in_port_t(startingPort)) 120 | } 121 | 122 | return in_port_t(startingPort) 123 | } 124 | 125 | //MARK: Check Port is occupied 126 | func checkTcpPortForListen(port: in_port_t) -> (Bool, descr: String){ 127 | 128 | let socketFileDescriptor = socket(AF_INET, SOCK_STREAM, 0) 129 | if socketFileDescriptor == -1 { 130 | return (false, "SocketCreationFailed, \(descriptionOfLastError())") 131 | } 132 | 133 | var addr = sockaddr_in() 134 | addr.sin_len = __uint8_t(MemoryLayout.size) 135 | addr.sin_family = sa_family_t(AF_INET) 136 | addr.sin_port = Int(OSHostByteOrder()) == OSLittleEndian ? _OSSwapInt16(port) : port 137 | addr.sin_addr = in_addr(s_addr: inet_addr("0.0.0.0")) 138 | addr.sin_zero = (0, 0, 0, 0, 0, 0, 0, 0) 139 | var bind_addr = sockaddr() 140 | memcpy(&bind_addr, &addr, Int(MemoryLayout.size)) 141 | 142 | if bind(socketFileDescriptor, &bind_addr, socklen_t(MemoryLayout.size)) == -1 { 143 | let details = descriptionOfLastError() 144 | release(socket: socketFileDescriptor) 145 | return (false, "\(port), BindFailed, \(details)") 146 | } 147 | if listen(socketFileDescriptor, SOMAXCONN ) == -1 { 148 | let details = descriptionOfLastError() 149 | release(socket: socketFileDescriptor) 150 | return (false, "\(port), ListenFailed, \(details)") 151 | } 152 | release(socket: socketFileDescriptor) 153 | return (true, "\(port) is free for use") 154 | } 155 | 156 | func release(socket: Int32) { 157 | _ = Darwin.shutdown(socket, SHUT_RDWR) 158 | close(socket) 159 | } 160 | 161 | func descriptionOfLastError() -> String { 162 | return "Error: \(errno)" 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/XCTestWD.h: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWD.h 3 | // XCTestWD 4 | // 5 | // Created by zhaoy on 22/02/2018. 6 | // Copyright © 2018 XCTestWD. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for XCTestWD. 12 | FOUNDATION_EXPORT double XCTestWDVersionNumber; 13 | 14 | //! Project version string for XCTestWD. 15 | FOUNDATION_EXPORT const unsigned char XCTestWDVersionString[]; 16 | 17 | //! Export debug level 18 | #define LOG_LEVEL_DEF ddLogLevel 19 | 20 | // In this header, you should import all the public headers of your framework using statements like #import 21 | 22 | #import 23 | #import 24 | #import 25 | #import 26 | #import 27 | #import 28 | #import 29 | #import 30 | #import 31 | #import 32 | #import 33 | #import 34 | #import 35 | #import 36 | #import 37 | #import 38 | #import 39 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIFileSharingEnabled 6 | 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/XCTestWDRunner.swift: -------------------------------------------------------------------------------- 1 | // 2 | // testUITests.swift 3 | // testUITests 4 | // 5 | // Created by xdf on 14/04/2017. 6 | // Copyright © 2017 xdf. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import Swifter 11 | import XCTestWD 12 | 13 | public class XCTextWDRunner: XCTestWDFailureProofTest { 14 | var server: XCTestWDServer? 15 | var monkey: XCTestWDMonkey? 16 | override public func setUp() { 17 | super.setUp() 18 | continueAfterFailure = false 19 | XCTestWDSessionManager.singleton.clearAll() 20 | XCUIDevice.shared.press(XCUIDevice.Button.home) 21 | sleep(2) 22 | 23 | NotificationCenter.default.addObserver(self, 24 | selector: #selector(terminate(notification:)), 25 | name: NSNotification.Name(rawValue: "XCTestWDSessionShutDown"), 26 | object: nil) 27 | } 28 | 29 | override public func tearDown() { 30 | super.tearDown() 31 | XCUIDevice.shared.press(XCUIDevice.Button.home) 32 | XCUIDevice.shared.press(XCUIDevice.Button.home) 33 | XCTestWDSessionManager.singleton.clearAll() 34 | } 35 | 36 | func testRunner() { 37 | self.monkey = XCTestWDMonkey() 38 | _ = self.monkey?.startMonkey() 39 | 40 | } 41 | 42 | // func testMultipleApps() { 43 | // 44 | // let settingsApp = XCUIApplication(bundleIdentifier: "com.bytedance.ee.microapp.demo") 45 | // settingsApp.launch() 46 | // sleep(5) 47 | // settingsApp.terminate() 48 | // 49 | // print("lalalalalala:\(settingsApp.state)") 50 | // 51 | // } 52 | 53 | @objc func terminate(notification: NSNotification) { 54 | self.server?.stopServer(); 55 | NSLog("XCTestWDTearDown->Session Reset") 56 | assert(false, "") 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUnitTest/ControllerTests/XCTestWDScreenShotControllerTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDScreenShotControllerTest.swift 3 | // XCTestWDUnitTest 4 | // 5 | // Created by SamuelZhaoY on 6/5/18. 6 | // Copyright © 2018 XCTestWD. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import Nimble 11 | @testable import XCTestWD 12 | @testable import Swifter 13 | 14 | class XCTestWDScreenShotControllerTest: XCTestWDUnitTestBase { 15 | 16 | func testScreenShotRetrieve() { 17 | let request = Swifter.HttpRequest.init() 18 | let response = XCTestWDScreenshotController.getScreenshot(request: request) 19 | let contentJSON = XCTestWDUnitTestBase.getResponseData(response) 20 | expect(contentJSON["status"].int).to(equal(WDStatus.Success.rawValue)) 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUnitTest/ControllerTests/XCTestWDSourceControllerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDSourceControllerTests.swift 3 | // XCTestWDUnitTest 4 | // 5 | // Created by SamuelZhaoY on 6/5/18. 6 | // Copyright © 2018 XCTestWD. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import Nimble 11 | import SwiftyJSON 12 | @testable import XCTestWD 13 | @testable import Swifter 14 | 15 | class XCTestWDSourceControllerTests: XCTestWDUnitTestBase { 16 | 17 | func testSourceRetrieve() { 18 | let request = Swifter.HttpRequest.init() 19 | let session = XCTestWDSessionManager.singleton.checkDefaultSession() 20 | XCTestWDSessionManager.singleton.mountSession(session) 21 | request.params["sessionId"] = session.identifier 22 | 23 | // case 1. test source in home panel, full amount of elements available. 24 | XCUIDevice.shared.press(XCUIDevice.Button.home) 25 | var response = XCTestWDSourceController.source(request: request) 26 | var contentJSON = XCTestWDUnitTestBase.getResponseData(response) 27 | expect(contentJSON["status"].int).to(equal(WDStatus.Success.rawValue)) 28 | 29 | // case 2. test source in web app. 30 | request.body = [UInt8]((try? JSON(["value":"//*[@name=\"Safari\"]","using":"xpath"]).rawData()) ?? Data()) 31 | response = XCTestWDElementController.findElement(request: request) 32 | expect(contentJSON["status"].int).to(equal(WDStatus.Success.rawValue)) 33 | var jsonResponse = XCTestWDUnitTestBase.getResponseData(response) 34 | expect(jsonResponse["value"]["ELEMENT"]).toNot(beNil()) 35 | 36 | // click and enter safari 37 | request.path = "/element/\(jsonResponse["value"]["ELEMENT"])" 38 | response = XCTestWDElementController.click(request: request) 39 | expect(contentJSON["status"].int).to(equal(WDStatus.Success.rawValue)) 40 | 41 | response = XCTestWDSourceController.sourceWithoutSession(request: request) 42 | contentJSON = XCTestWDUnitTestBase.getResponseData(response) 43 | expect(contentJSON["status"].int).to(equal(WDStatus.Success.rawValue)) 44 | 45 | // case 3. test source in native app. 46 | XCUIDevice.shared.press(XCUIDevice.Button.home) 47 | // sliding to first panel 48 | XCUIDevice.shared.press(XCUIDevice.Button.home) 49 | 50 | request.body = [UInt8]((try? JSON(["value":"//*[@name=\"Messages\"]","using":"xpath"]).rawData()) ?? Data()) 51 | response = XCTestWDElementController.findElement(request: request) 52 | expect(contentJSON["status"].int).to(equal(WDStatus.Success.rawValue)) 53 | jsonResponse = XCTestWDUnitTestBase.getResponseData(response) 54 | expect(jsonResponse["value"]["ELEMENT"]).toNot(beNil()) 55 | 56 | // click and enter safari 57 | request.path = "/element/\(jsonResponse["value"]["ELEMENT"])" 58 | response = XCTestWDElementController.click(request: request) 59 | expect(contentJSON["status"].int).to(equal(WDStatus.Success.rawValue)) 60 | 61 | response = XCTestWDSourceController.sourceWithoutSession(request: request) 62 | contentJSON = XCTestWDUnitTestBase.getResponseData(response) 63 | expect(contentJSON["status"].int).to(equal(WDStatus.Success.rawValue)) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUnitTest/ControllerTests/XCTestWDTitleControllerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDTitleControllerTests.swift 3 | // XCTestWDUnitTest 4 | // 5 | // Created by SamuelZhaoY on 2/4/18. 6 | // Copyright © 2018 XCTestWD. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import Nimble 11 | @testable import XCTestWD 12 | @testable import Swifter 13 | 14 | class XCTestWDTitleControllerTests: XCTestWDUnitTestBase { 15 | 16 | func testTitleRetrieve() { 17 | let request = Swifter.HttpRequest.init() 18 | let response = XCTestWDTitleController.title(request: request) 19 | let contentJSON = XCTestWDUnitTestBase.getResponseData(response) 20 | expect(contentJSON["status"].int).to(equal(WDStatus.Success.rawValue)) 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUnitTest/ControllerTests/XCTestWDUrlControllerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDUrlController.swift 3 | // XCTestWDUnitTest 4 | // 5 | // Created by SamuelZhaoY on 2/4/18. 6 | // Copyright © 2018 XCTestWD. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import Nimble 11 | @testable import XCTestWD 12 | @testable import Swifter 13 | 14 | class XCTestWDUrlControllerTests: XCTestWDUnitTestBase { 15 | 16 | func testUrlController() { 17 | let request = Swifter.HttpRequest.init() 18 | let response = XCTestWDUrlController.url(request: request) 19 | response.shouldBeSuccessful() 20 | } 21 | 22 | func testGetUrlController() { 23 | let request = Swifter.HttpRequest.init() 24 | let response = XCTestWDUrlController.getUrl(request: request) 25 | response.shouldBeSuccessful() 26 | } 27 | 28 | func testForwardUrlController() { 29 | let request = Swifter.HttpRequest.init() 30 | let response = XCTestWDUrlController.forward(request: request) 31 | response.shouldBeSuccessful() 32 | } 33 | 34 | func testRefreshUrlController() { 35 | let request = Swifter.HttpRequest.init() 36 | let response = XCTestWDUrlController.refresh(request: request) 37 | response.shouldBeSuccessful() 38 | } 39 | 40 | func testBack() { 41 | let request = Swifter.HttpRequest.init() 42 | let response = XCTestWDUrlController.back(request: request) 43 | let contentJSON = XCTestWDUnitTestBase.getResponseData(response) 44 | expect(contentJSON["status"].int).to(equal(WDStatus.ElementIsNotSelectable.rawValue)) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUnitTest/ControllerTests/XCTestWDWindowControllerTests.swift: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // XCTestWDWindowControllerTests.swift 4 | // XCTestWDUnitTest 5 | // 6 | // Created by SamuelZhaoY on 2/4/18. 7 | // Copyright © 2018 XCTestWD. All rights reserved. 8 | // 9 | 10 | import XCTest 11 | import Nimble 12 | @testable import XCTestWD 13 | @testable import Swifter 14 | 15 | class XCTestWDWindowControllerTests: XCTestWDUnitTestBase { 16 | 17 | func testWindowSize() { 18 | let request = Swifter.HttpRequest.init() 19 | let response = XCTestWDWindowController.getWindowSize(request: request) 20 | response.shouldBeSuccessful() 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUnitTest/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUnitTest/XCTestWDSessionTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDUnitTest.swift 3 | // XCTestWDUnitTest 4 | // 5 | // Created by SamuelZhaoY on 31/3/18. 6 | // Copyright © 2018 XCTestWD. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import Swifter 11 | import Nimble 12 | @testable import XCTestWD 13 | 14 | class XCTestWDSessionTest: XCTestWDUnitTestBase { 15 | 16 | func testApplicationLaunch() { 17 | XCTAssert(self.springApplication != nil, "application should not be nil") 18 | } 19 | 20 | func testFetchSystemApplicaiton() { 21 | let systemApplication = (XCAXClient_iOS.sharedClient() as! XCAXClient_iOS).systemApplication() 22 | let springBoardApplication = XCTestWDApplication.create(byPID: pid_t(((systemApplication as! NSObject).value(forKey: "processIdentifier") as! NSNumber).intValue)) 23 | 24 | XCTAssert(springBoardApplication != nil, "application should not be nil") 25 | } 26 | 27 | func testSessionCreation() { 28 | XCTAssert(self.springApplication?.bundleID == XCTestWDSession.activeApplication()?.bundleID) 29 | 30 | let session = XCTestWDSession.sessionWithApplication(self.springApplication!) 31 | XCTestWDSessionManager.singleton.mountSession(session) 32 | 33 | XCTAssert(XCTestWDSessionManager.singleton.queryAll().keys.count == 1, "key length should be one, containing"); 34 | } 35 | 36 | func testSessionDeletion() { 37 | self.testSessionCreation() 38 | 39 | XCTestWDSessionManager.singleton.clearAll(); 40 | 41 | XCTAssert(XCTestWDSessionManager.singleton.queryAll().keys.count == 0, "key length shoud be zero") 42 | } 43 | 44 | func testSessionIDDeletion() { 45 | let session = XCTestWDSession.sessionWithApplication(self.springApplication!) 46 | XCTestWDSessionManager.singleton.mountSession(session) 47 | 48 | XCTAssert(XCTestWDSessionManager.singleton.queryAll().keys.count == 1, "key length should be one, containing"); 49 | 50 | XCTestWDSessionManager.singleton.deleteSession(session.identifier) 51 | XCTAssert(XCTestWDSessionManager.singleton.queryAll().keys.count == 0, "key length shoud be zero") 52 | } 53 | 54 | func testElementCache() { 55 | let uuid = XCTestWDSessionManager.commonCache.storeElement(self.springApplication!) 56 | expect(XCTestWDSessionManager.commonCache.elementForUUID(uuid)).to(equal(self.springApplication!)) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUnitTest/XCTestWDUnitTestBase.swift: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // XCTestWDUnitTestBase.swift 4 | // XCTestWDUnitTest 5 | // 6 | // Created by SamuelZhaoY on 1/4/18. 7 | // Copyright © 2018 XCTestWD. All rights reserved. 8 | // 9 | 10 | import XCTest 11 | import SwiftyJSON 12 | import Nimble 13 | @testable import XCTestWD 14 | @testable import Swifter 15 | 16 | class XCTestWDUnitTestBase: XCTestCase { 17 | 18 | var springApplication: XCUIApplication? 19 | 20 | override func setUp() { 21 | super.setUp() 22 | continueAfterFailure = false 23 | XCTestWDSessionManager.singleton.clearAll() 24 | self.springApplication = XCTestWDApplication.activeApplication() 25 | XCUIDevice.shared.press(XCUIDevice.Button.home) 26 | sleep(2) 27 | } 28 | 29 | override func tearDown() { 30 | super.tearDown() 31 | XCUIDevice.shared.press(XCUIDevice.Button.home) 32 | XCUIDevice.shared.press(XCUIDevice.Button.home) 33 | XCTestWDSessionManager.singleton.clearAll() 34 | } 35 | 36 | static func getResponseData(_ response: Swifter.HttpResponse) -> JSON { 37 | switch response { 38 | case .ok(let body): 39 | switch body { 40 | case .text(let content): 41 | if let dataFromString = content.data(using: .utf8, allowLossyConversion: false) { 42 | return (try? JSON(data: dataFromString)) ?? JSON.init(stringLiteral: "") 43 | } else { 44 | break 45 | } 46 | case .html( _): 47 | return JSON(["status": 0]) 48 | default: 49 | break 50 | } 51 | default: 52 | break 53 | } 54 | 55 | return JSON.init("") 56 | } 57 | } 58 | 59 | extension HttpResponse { 60 | func shouldBeSuccessful() 61 | { 62 | let jsonContent = XCTestWDUnitTestBase.getResponseData(self) 63 | expect(jsonContent["status"]).to(equal(0)) 64 | expect(self.statusCode()).to(equal(200)) 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/curlTests.sh: -------------------------------------------------------------------------------- 1 | 2 | export JSON_HEADER='-H "Content-Type:application/json"' 3 | export DEVICE_URL='http://127.0.0.1:8001' 4 | 5 | TagHead() { 6 | echo "\n#### $1 ####" 7 | } 8 | 9 | #Session: create session 10 | 11 | TagHead "Create Session" 12 | 13 | curl -X POST $JSON_HEADER \ 14 | -d "{\"desiredCapabilities\":{\"deviceName\":\"iPhone 8\",\"platformName\":\"iOS\", \"bundleId\":\"com.apple.mobilesafari\",\"autoAcceptAlerts\":false}}" \ 15 | $DEVICE_URL/wd/hub/session \ 16 | 17 | ### Read session as input for next stage testing 18 | 19 | echo "\n\ninput the sessionID generated:\n" 20 | read sessionID 21 | 22 | #Session: query sessions 23 | 24 | TagHead "Query Session" 25 | 26 | curl -X GET $JSON_HEADER \ 27 | $DEVICE_URL/wd/hub/sessions \ 28 | 29 | #Session: checkon source 30 | 31 | curl -X POST $JSON_HEADER \ 32 | -d "{\"using\":\"xpath\",\"value\":\"//XCUIElementTypeTextField[1]\"}" \ 33 | $DEVICE_URL/wd/hub/session/$sessionID/elements \ 34 | 35 | echo "\n\ninput the elementID generated:\n" 36 | read elementID 37 | 38 | curl -X POST $JSON_HEADER \ 39 | $DEVICE_URL/wd/hub/session/$sessionID/tap/$elementID \ 40 | 41 | TagHead "Check Source" 42 | 43 | curl -X GET $JSON_HEADER \ 44 | $DEVICE_URL/wd/hub/source \ 45 | 46 | TagHead "Press Home" 47 | 48 | curl -X POST $JSON_HEADER \ 49 | $DEVICE_URL/wd/hub/session/$sessionID/homeScreen \ 50 | 51 | TagHead "Title" 52 | 53 | curl -X GET $JSON_HEADER \ 54 | $DEVICE_URL/wd/hub/session/$sessionID/title \ 55 | 56 | TagHead "Check" 57 | 58 | curl -X GET $JSON_HEADER \ 59 | $DEVICE_URL/wd/hub/session/$sessionID/title \ 60 | 61 | TagHead "Trigger touch event by x & y" 62 | 63 | curl -X POST $JSON_HEADER \ 64 | -d "{\"using\":\"xpath\",\"value\":\"//*[@name="Messages"]\"}" \ 65 | $DEVICE_URL/wd/hub/session/$sessionID/elements \ 66 | 67 | curl -X POST $JSON_HEADER \ 68 | -d "{\"using\":\"predicate string\",\"value\":\"label CONTAINS[c] 'Messages'\"}" \ 69 | $DEVICE_URL/wd/hub/session/$sessionID/elements \ 70 | 71 | echo "\n\ninput the elementID generated:\n" 72 | read elementID 73 | 74 | curl -X POST $JSON_HEADER \ 75 | $DEVICE_URL/wd/hub/session/$sessionID/tap/$elementID \ 76 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/libxml2/libxml2-fuzi.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import 5 | #import 6 | -------------------------------------------------------------------------------- /XCTestWD-master/index.html: -------------------------------------------------------------------------------- 1 | XCTestWD page coming soon 2 | -------------------------------------------------------------------------------- /XCTestWD-master/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = require('./lib/xctest-client'); 4 | -------------------------------------------------------------------------------- /XCTestWD-master/lib/helper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const macacaUtils = require('macaca-utils'); 4 | const childProcess = require('child_process'); 5 | 6 | var _ = macacaUtils.merge({}, macacaUtils); 7 | 8 | _.sleep = function(ms) { 9 | return new Promise(resolve => { 10 | setTimeout(resolve, ms); 11 | }); 12 | }; 13 | 14 | _.retry = function(func, interval, num) { 15 | return new Promise((resolve, reject) => { 16 | func().then(resolve, err => { 17 | if (num > 0 || typeof num === 'undefined') { 18 | _.sleep(interval).then(() => { 19 | resolve(_.retry(func, interval, num - 1)); 20 | }); 21 | } else { 22 | reject(err); 23 | } 24 | }); 25 | }); 26 | }; 27 | 28 | _.waitForCondition = function(func, wait/* ms*/, interval/* ms*/) { 29 | wait = wait || 5000; 30 | interval = interval || 500; 31 | let start = Date.now(); 32 | let end = start + wait; 33 | 34 | const fn = function() { 35 | return new Promise((resolve, reject) => { 36 | const continuation = (res, rej) => { 37 | let now = Date.now(); 38 | 39 | if (now < end) { 40 | res(_.sleep(interval).then(fn)); 41 | } else { 42 | rej(`Wait For Condition timeout ${wait}`); 43 | } 44 | }; 45 | func().then(isOk => { 46 | 47 | if (isOk) { 48 | resolve(); 49 | } else { 50 | continuation(resolve, reject); 51 | } 52 | }).catch(() => { 53 | continuation(resolve, reject); 54 | }); 55 | }); 56 | }; 57 | return fn(); 58 | }; 59 | 60 | _.escapeString = function(str) { 61 | return str 62 | .replace(/[\\]/g, '\\\\') 63 | .replace(/[\/]/g, '\\/') 64 | .replace(/[\b]/g, '\\b') 65 | .replace(/[\f]/g, '\\f') 66 | .replace(/[\n]/g, '\\n') 67 | .replace(/[\r]/g, '\\r') 68 | .replace(/[\t]/g, '\\t') 69 | .replace(/[\"]/g, '\\"') 70 | .replace(/\\'/g, "\\'"); 71 | }; 72 | 73 | _.exec = function(cmd, opts) { 74 | return new Promise((resolve, reject) => { 75 | childProcess.exec(cmd, _.merge({ 76 | maxBuffer: 1024 * 512, 77 | wrapArgs: false 78 | }, opts || {}), (err, stdout) => { 79 | if (err) { 80 | return reject(err); 81 | } 82 | resolve(_.trim(stdout)); 83 | }); 84 | }); 85 | }; 86 | 87 | _.spawn = function() { 88 | var args = Array.prototype.slice.call(arguments); 89 | 90 | return new Promise((resolve, reject) => { 91 | var stdout = ''; 92 | var stderr = ''; 93 | var child = childProcess.spawn.apply(childProcess, args); 94 | 95 | child.on('error', error => { 96 | reject(error); 97 | }); 98 | 99 | child.stdout.on('data', data => { 100 | stdout += data; 101 | }); 102 | 103 | child.stderr.on('data', data => { 104 | stderr += data; 105 | }); 106 | 107 | child.on('close', code => { 108 | var error; 109 | if (code) { 110 | error = new Error(stderr); 111 | error.code = code; 112 | return reject(error); 113 | } 114 | resolve([stdout, stderr]); 115 | }); 116 | }); 117 | }; 118 | 119 | var Defer = function() { 120 | this._resolve = null; 121 | this._reject = null; 122 | this.promise = new Promise((resolve, reject) => { 123 | this._resolve = resolve; 124 | this._reject = reject; 125 | }); 126 | }; 127 | 128 | Defer.prototype.resolve = function(data) { 129 | this._resolve(data); 130 | }; 131 | 132 | Defer.prototype.reject = function(err) { 133 | this._reject(err); 134 | }; 135 | 136 | _.Defer = Defer; 137 | 138 | module.exports = _; 139 | -------------------------------------------------------------------------------- /XCTestWD-master/lib/logger.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var logger = require('xlogger'); 4 | 5 | module.exports = logger.Logger({ 6 | closeFile: true 7 | }); 8 | -------------------------------------------------------------------------------- /XCTestWD-master/lib/proxy.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const request = require('request'); 4 | 5 | const _ = require('./helper'); 6 | const logger = require('./logger'); 7 | 8 | class XCProxy { 9 | constructor(options) { 10 | Object.assign(this, { 11 | scheme: 'http', 12 | proxyHost: '127.0.0.1', 13 | proxyPort: 8001, 14 | urlBase: 'wd/hub', 15 | sessionId: null, 16 | originSessionId: null 17 | }, options); 18 | } 19 | 20 | handleNewUrl(url) { 21 | const sessionReg = /\/session\/([^\/]+)/; 22 | const wdSessionReg = new RegExp(`${this.urlBase}\/session\/([^\/]+)`); 23 | url = `${this.scheme}://${this.proxyHost}:${this.proxyPort}${url}`; 24 | 25 | if (sessionReg.test(url) && this.sessionId) { 26 | this.originSessionId = url.match(sessionReg)[1]; 27 | url = url.replace(wdSessionReg, `${this.urlBase}/session/${this.sessionId}`); 28 | } 29 | return url; 30 | } 31 | 32 | send(url, method, body) { 33 | return new Promise((resolve, reject) => { 34 | method = method.toUpperCase(); 35 | const newUrl = this.handleNewUrl(url); 36 | const retryCount = 10; 37 | const retryInterval = 2000; 38 | 39 | const reqOpts = { 40 | url: newUrl, 41 | method: method, 42 | headers: { 43 | 'Content-type': 'application/json;charset=UTF=8' 44 | }, 45 | resolveWithFullResponse: true 46 | }; 47 | 48 | if (body && (method.toUpperCase() === 'POST' || method.toUpperCase() === 'PUT')) { 49 | if (typeof body !== 'object') { 50 | body = JSON.parse(body); 51 | } 52 | reqOpts.json = body; 53 | } 54 | 55 | logger.debug(`Proxy: ${url}:${method} to ${newUrl}:${method} with body: ${_.truncate(JSON.stringify(body), { 56 | length: 200 57 | })}`); 58 | 59 | _.retry(() => { 60 | return new Promise((_resolve, _reject) => { 61 | request(reqOpts, (error, res, body) => { 62 | if (error) { 63 | logger.debug(`xctest client proxy error with: ${error}`); 64 | return _reject(error); 65 | } 66 | 67 | if (!body) { 68 | logger.debug('xctest client proxy received no data.'); 69 | return _reject('No data received from XCTestWD.'); 70 | } 71 | 72 | if (typeof body !== 'object') { 73 | try { 74 | body = JSON.parse(body); 75 | } catch (e) { 76 | logger.debug(`Fail to parse body: ${e}`); 77 | } 78 | } 79 | 80 | if (body && body.sessionId) { 81 | this.sessionId = body.sessionId; 82 | body.sessionId = this.originSessionId; 83 | } 84 | 85 | logger.debug(`Got response with status ${res.statusCode}: ${_.truncate(JSON.stringify(body), { 86 | length: 200 87 | })}`); 88 | _resolve(body); 89 | }); 90 | 91 | }); 92 | }, retryInterval, retryCount).then(resolve, reject); 93 | }); 94 | } 95 | } 96 | 97 | module.exports = XCProxy; 98 | -------------------------------------------------------------------------------- /XCTestWD-master/lib/xctest-client.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const url = require('url'); 4 | const path = require('path'); 5 | const iOSUtils = require('ios-utils'); 6 | const EventEmitter = require('events'); 7 | const childProcess = require('child_process'); 8 | 9 | const _ = require('./helper'); 10 | const pkg = require('../package'); 11 | const XCProxy = require('./proxy'); 12 | const logger = require('./logger'); 13 | const XCTestWD = require('./xctestwd'); 14 | 15 | const { 16 | detectPort 17 | } = _; 18 | const TEST_URL = pkg.site; 19 | const projectPath = XCTestWD.projectPath; 20 | const SERVER_URL_REG = XCTestWD.SERVER_URL_REG; 21 | const simulatorLogFlag = XCTestWD.simulatorLogFlag; 22 | 23 | class XCTest extends EventEmitter { 24 | constructor(options) { 25 | super(); 26 | this.proxy = null; 27 | this.capabilities = null; 28 | this.sessionId = null; 29 | this.device = null; 30 | this.deviceLogProc = null; 31 | this.runnerProc = null; 32 | this.iproxyProc = null; 33 | Object.assign(this, { 34 | proxyHost: '127.0.0.1', 35 | proxyPort: 8001, 36 | urlBase: 'wd/hub' 37 | }, options || {}); 38 | this.init(); 39 | } 40 | 41 | init() { 42 | this.checkProjectPath(); 43 | process.on('uncaughtException', (e) => { 44 | logger.error(`Uncaught Exception: ${e.stack}`); 45 | this.stop(); 46 | process.exit(1); 47 | }); 48 | process.on('exit', () => { 49 | this.stop(); 50 | }); 51 | } 52 | 53 | checkProjectPath() { 54 | if (_.isExistedDir(projectPath)) { 55 | logger.debug(`project path: ${projectPath}`); 56 | } else { 57 | logger.error('project path not found'); 58 | } 59 | } 60 | 61 | configUrl(str) { 62 | const urlObj = url.parse(str); 63 | this.proxyHost = urlObj.hostname; 64 | this.proxyPort = urlObj.port; 65 | } 66 | 67 | initProxy() { 68 | this.proxy = new XCProxy({ 69 | proxyHost: this.proxyHost, 70 | proxyPort: this.proxyPort, 71 | urlBase: this.urlBase 72 | }); 73 | } 74 | 75 | * startSimLog() { 76 | const logPath = yield this.startBootstrap(); 77 | const logDir = path.resolve(logPath); 78 | return _.retry(() => { 79 | return new Promise((resolve, reject) => { 80 | const logTxtFile = path.join(logDir, '..', 'StandardOutputAndStandardError.txt'); 81 | logger.info(`Read simulator log at: ${logTxtFile}`); 82 | 83 | if (!_.isExistedFile(logTxtFile)) { 84 | return reject(); 85 | } 86 | let args = `-f -n 0 ${logTxtFile}`.split(' '); 87 | var proc = childProcess.spawn('tail', args, {}); 88 | this.deviceLogProc = proc; 89 | 90 | proc.stderr.setEncoding('utf8'); 91 | proc.stdout.setEncoding('utf8'); 92 | 93 | proc.stdout.on('data', data => { 94 | 95 | // avoid logout long data such as bitmap 96 | if (data.length <= 300 && logger.debugMode) { 97 | // logger.debug(data); 98 | } 99 | 100 | let match = SERVER_URL_REG.exec(data); 101 | if (match) { 102 | const url = match[1]; 103 | if (url.startsWith('http://')) { 104 | this.configUrl(url); 105 | resolve(); 106 | } 107 | } 108 | }); 109 | 110 | proc.stderr.on('data', data => { 111 | logger.debug(data); 112 | }); 113 | 114 | proc.stdout.on('error', (err) => { 115 | logger.warn(`simulator log process error with ${err}`); 116 | }); 117 | 118 | proc.on('exit', (code, signal) => { 119 | logger.warn(`simulator log process exit with code: ${code}, signal: ${signal}`); 120 | reject(); 121 | }); 122 | }); 123 | }, 1000, Infinity); 124 | } 125 | 126 | * startDeviceLog() { 127 | yield this.startBootstrap(); 128 | var proc = childProcess.spawn(iOSUtils.devicelog.binPath, [this.device.deviceId], {}); 129 | this.deviceLogProc = proc; 130 | 131 | proc.stderr.setEncoding('utf8'); 132 | proc.stdout.setEncoding('utf8'); 133 | 134 | return new Promise((resolve, reject) => { 135 | proc.stdout.on('data', data => { 136 | 137 | // avoid logout long data such as bitmap 138 | if (data.length <= 300 && logger.debugMode) { 139 | logger.debug(data); 140 | } 141 | 142 | let match = SERVER_URL_REG.exec(data); 143 | if (match) { 144 | const url = match[1]; 145 | if (url.startsWith('http://')) { 146 | this.configUrl(url); 147 | resolve(); 148 | } 149 | } 150 | }); 151 | 152 | proc.stderr.on('data', data => { 153 | logger.debug(data); 154 | }); 155 | 156 | proc.stdout.on('error', (err) => { 157 | logger.warn(`devicelog error with ${err}`); 158 | }); 159 | 160 | proc.on('exit', (code, signal) => { 161 | logger.warn(`devicelog exit with code: ${code}, signal: ${signal}`); 162 | reject(); 163 | }); 164 | }); 165 | } 166 | 167 | * startBootstrap() { 168 | return new Promise((resolve, reject) => { 169 | logger.info(`XCTestWD version: ${XCTestWD.version}`); 170 | 171 | var args = `clean test -project ${XCTestWD.projectPath} -scheme XCTestWDUITests -destination id=${this.device.deviceId} XCTESTWD_PORT=${this.proxyPort}`.split(' '); 172 | var env = _.merge({}, process.env, { 173 | XCTESTWD_PORT: this.proxyPort 174 | }); 175 | 176 | var proc = childProcess.spawn('xcodebuild', args, { 177 | env: env 178 | }); 179 | this.runnerProc = proc; 180 | proc.stderr.setEncoding('utf8'); 181 | proc.stdout.setEncoding('utf8'); 182 | 183 | proc.stdout.on('data', data => { 184 | // logger.debug(data); 185 | }); 186 | 187 | proc.stderr.on('data', data => { 188 | // logger.debug(data); 189 | 190 | if (~data.indexOf(simulatorLogFlag)) { 191 | const list = data.split(simulatorLogFlag); 192 | const res = list[1].trim(); 193 | resolve(res); 194 | } else { 195 | logger.debug(`please check project: ${projectPath}`); 196 | } 197 | }); 198 | 199 | proc.stdout.on('error', (err) => { 200 | logger.warn(`xctest client error with ${err}`); 201 | logger.debug(`please check project: ${projectPath}`); 202 | }); 203 | 204 | proc.on('exit', (code, signal) => { 205 | this.stop(); 206 | logger.warn(`xctest client exit with code: ${code}, signal: ${signal}`); 207 | }); 208 | 209 | }); 210 | } 211 | 212 | * startIproxy() { 213 | let args = [this.proxyPort, this.proxyPort, this.device.deviceId]; 214 | 215 | const IOS_USBMUXD_IPROXY = 'iproxy'; 216 | const binPath = yield _.exec(`which ${IOS_USBMUXD_IPROXY}`); 217 | 218 | var proc = childProcess.spawn(binPath, args); 219 | 220 | this.iproxyProc = proc; 221 | proc.stderr.setEncoding('utf8'); 222 | proc.stdout.setEncoding('utf8'); 223 | 224 | proc.stdout.on('data', () => { 225 | }); 226 | 227 | proc.stderr.on('data', () => { 228 | // logger.debug(data); 229 | }); 230 | 231 | proc.stdout.on('error', (err) => { 232 | logger.warn(`${IOS_USBMUXD_IPROXY} error with ${err}`); 233 | }); 234 | 235 | proc.on('exit', (code, signal) => { 236 | logger.warn(`${IOS_USBMUXD_IPROXY} exit with code: ${code}, signal: ${signal}`); 237 | }); 238 | } 239 | 240 | * start(caps) { 241 | try { 242 | this.proxyPort = yield detectPort(this.proxyPort); 243 | 244 | this.capabilities = caps; 245 | const xcodeVersion = yield iOSUtils.getXcodeVersion(); 246 | 247 | logger.debug(`xcode version: ${xcodeVersion}`); 248 | 249 | var deviceInfo = iOSUtils.getDeviceInfo(this.device.deviceId); 250 | 251 | if (deviceInfo.isRealIOS) { 252 | yield this.startDeviceLog(); 253 | yield this.startIproxy(); 254 | } else { 255 | yield this.startSimLog(); 256 | } 257 | 258 | logger.info(`${pkg.name} start with port: ${this.proxyPort}`); 259 | 260 | this.initProxy(); 261 | 262 | if (caps.desiredCapabilities.browserName === 'Safari') { 263 | var promise = this.proxy.send(`/${this.urlBase}/session`, 'POST', { 264 | desiredCapabilities: { 265 | bundleId: 'com.apple.mobilesafari' 266 | } 267 | }); 268 | return yield Promise.all([this.device.openURL(TEST_URL), promise]); 269 | } else { 270 | return yield this.proxy.send(`/${this.urlBase}/session`, 'POST', caps); 271 | } 272 | } catch (err) { 273 | logger.debug(`Fail to start xctest: ${err}`); 274 | this.stop(); 275 | throw err; 276 | } 277 | } 278 | 279 | stop() { 280 | if (this.deviceLogProc) { 281 | logger.debug(`killing deviceLogProc pid: ${this.deviceLogProc.pid}`); 282 | this.deviceLogProc.kill('SIGKILL'); 283 | this.deviceLogProc = null; 284 | } 285 | if (this.runnerProc) { 286 | logger.debug(`killing runnerProc pid: ${this.runnerProc.pid}`); 287 | this.runnerProc.kill('SIGKILL'); 288 | this.runnerProc = null; 289 | } 290 | 291 | if (this.iproxyProc) { 292 | logger.debug(`killing iproxyProc pid: ${this.iproxyProc.pid}`); 293 | this.iproxyProc.kill('SIGKILL'); 294 | this.iproxyProc = null; 295 | } 296 | } 297 | 298 | sendCommand(url, method, body) { 299 | return this.proxy.send(url, method, body); 300 | } 301 | } 302 | 303 | module.exports = XCTest; 304 | module.exports.XCTestWD = XCTestWD; 305 | -------------------------------------------------------------------------------- /XCTestWD-master/lib/xctestwd.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | 5 | exports.SERVER_URL_REG = /XCTestWDSetup->(.*)<-XCTestWDSetup/; 6 | exports.schemeName = 'XCTestWDUITests'; 7 | exports.projectPath = process.env.XCTESTWD_PATH || path.join(__dirname, '..', 'XCTestWD', 'XCTestWD.xcodeproj'); 8 | exports.version = require('../package').version; 9 | exports.BUNDLE_ID = 'XCTestWD.XCTestWD'; 10 | exports.simulatorLogFlag = 'IDETestOperationsObserverDebug: Writing diagnostic log for test session to:'; 11 | -------------------------------------------------------------------------------- /XCTestWD-master/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xctestwd", 3 | "version": "1.4.5", 4 | "description": "Swift implementation of WebDriver server for iOS that runs on Simulator/iOS devices.", 5 | "keywords": [ 6 | "iOS", 7 | "xctest" 8 | ], 9 | "repository": { 10 | "type": "git", 11 | "url": "git://github.com/macacajs/xctestwd.git" 12 | }, 13 | "main": "index.js", 14 | "dependencies": { 15 | "ios-utils": "~1.0.0", 16 | "macaca-doctor": "^2.0.4", 17 | "macaca-utils": "^1.0.0", 18 | "request": "~2.69.0", 19 | "shelljs": "^0.7.8", 20 | "webdriver-dfn-error-code": "~1.0.1", 21 | "xcode": "^0.8.9", 22 | "xctestwd-frameworks-93": "^1.0.0", 23 | "xctestwd-frameworks-94": "^1.0.1", 24 | "xctestwd-frameworks": "^1.0.0", 25 | "xlogger": "~1.0.0" 26 | }, 27 | "devDependencies": { 28 | "co-mocha": "*", 29 | "eslint": "^4.13.0", 30 | "eslint-plugin-mocha": "^4.11.0", 31 | "git-contributor": "^1.0.7", 32 | "istanbul": "*", 33 | "mocha": "*", 34 | "pre-commit": "*" 35 | }, 36 | "pre-commit": [ 37 | "lint" 38 | ], 39 | "scripts": { 40 | "test": "mocha", 41 | "lint": "eslint . --fix", 42 | "install": "node ./scripts/install.js", 43 | "contributor": "git-contributor" 44 | }, 45 | "site": "https://macacajs.github.io", 46 | "license": "MIT" 47 | } 48 | -------------------------------------------------------------------------------- /XCTestWD-master/scripts/aggregate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | 5 | # Sets the target folders and the final framework product. 6 | PROJECT_NAME=XCTestWD 7 | FRAMEWORK_CONFIG=Release 8 | BUILD_TARGET=XCTestWD 9 | 10 | # Install dir will be the final output to the framework. 11 | # The following line create it in the root folder of the current project. 12 | INSTALL_DIR="$SRCROOT/Frameworks/$BUILD_TARGET.framework" 13 | 14 | # Working dir will be deleted after the framework creation. 15 | WORK_DIR="$SRCROOT/build" 16 | DEVICE_DIR="$WORK_DIR/${FRAMEWORK_CONFIG}-iphoneos/$BUILD_TARGET.framework" 17 | SIMULATOR_DIR="$WORK_DIR/${FRAMEWORK_CONFIG}-iphonesimulator/$BUILD_TARGET.framework" 18 | rm -rf "$WORK_DIR" 19 | 20 | echo "Building device..." 21 | xcodebuild -configuration "$FRAMEWORK_CONFIG" -target "$BUILD_TARGET" -sdk iphoneos -project "$PROJECT_NAME.xcodeproj" > /dev/null 22 | 23 | echo "Building simulator..." 24 | xcodebuild -configuration "$FRAMEWORK_CONFIG" -target "$BUILD_TARGET" -sdk iphonesimulator -project "$PROJECT_NAME.xcodeproj" > /dev/null 25 | 26 | echo "Preparing directory..." 27 | rm -rf "$INSTALL_DIR" 28 | mkdir -p "$INSTALL_DIR/Headers" 29 | mkdir -p "$INSTALL_DIR/Modules/$BUILD_TARGET.swiftmodule" 30 | 31 | # Regulating Framework Deliverables 32 | echo "Migrating System Headers:" 33 | cp "$SIMULATOR_DIR/Headers/"*.h "$INSTALL_DIR/Headers/" 34 | 35 | echo "Mixing Mutli-Architecture Swift Modules:" 36 | cp "$SIMULATOR_DIR/Modules/module.modulemap" "$INSTALL_DIR/Modules/" 37 | cp "$SIMULATOR_DIR/Modules/$BUILD_TARGET.swiftmodule/"* "$INSTALL_DIR/Modules/$BUILD_TARGET.swiftmodule/" 38 | cp "$DEVICE_DIR/Modules/$BUILD_TARGET.swiftmodule/"* "$INSTALL_DIR/Modules/$BUILD_TARGET.swiftmodule/" 39 | cp "$SIMULATOR_DIR/Info.plist" "$INSTALL_DIR/" 40 | 41 | echo "Combine Fat File" 42 | lipo -create "$DEVICE_DIR/$BUILD_TARGET" "$SIMULATOR_DIR/$BUILD_TARGET" -output "${INSTALL_DIR}/${BUILD_TARGET}" 43 | 44 | # Clean Up Intermediate File 45 | # rm -rf "$WORK_DIR" 46 | -------------------------------------------------------------------------------- /XCTestWD-master/scripts/install.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const xcode = require('xcode'); 6 | const _ = require('macaca-utils'); 7 | const shelljs = require('shelljs'); 8 | const hostname = require('os').hostname(); 9 | const doctorIOS = require('macaca-doctor/lib/ios'); 10 | 11 | if (!_.platform.isOSX) { 12 | return; 13 | } 14 | 15 | const DEVELOPMENT_TEAM = process.env.DEVELOPMENT_TEAM_ID || ''; 16 | 17 | const xctestwdFrameworksPrefix = 'xctestwd-frameworks'; 18 | 19 | const update = function(project, schemeName, callback) { 20 | const myConfigKey = project.pbxTargetByName(schemeName).buildConfigurationList; 21 | const buildConfig = project.pbxXCConfigurationList()[myConfigKey]; 22 | const configArray = buildConfig.buildConfigurations; 23 | const keys = configArray.map(item => item.value); 24 | const pbxXCBuildConfigurationSection = project.pbxXCBuildConfigurationSection(); 25 | keys.forEach(key => { 26 | callback(pbxXCBuildConfigurationSection[key].buildSettings); 27 | }); 28 | }; 29 | 30 | const updateInformation = function() { 31 | try { 32 | const schemeName = 'XCTestWDUITests'; 33 | const projectPath = path.join(__dirname, '..', 'XCTestWD', 'XCTestWD.xcodeproj', 'project.pbxproj'); 34 | const myProj = xcode.project(projectPath); 35 | myProj.parseSync(); 36 | 37 | update(myProj, schemeName, function(buildSettings) { 38 | const newBundleId = process.env.BUNDLE_ID || `XCTestWDRunner.XCTestWDRunner.${hostname}`; 39 | buildSettings.PRODUCT_BUNDLE_IDENTIFIER = newBundleId; 40 | if (DEVELOPMENT_TEAM) { 41 | buildSettings.DEVELOPMENT_TEAM = DEVELOPMENT_TEAM; 42 | } 43 | }); 44 | 45 | const projSect = myProj.getFirstProject(); 46 | const myRunnerTargetKey = myProj.findTargetKey(schemeName); 47 | const targetAttributes = projSect.firstProject.attributes.TargetAttributes; 48 | const runnerObj = targetAttributes[myRunnerTargetKey]; 49 | if (DEVELOPMENT_TEAM) { 50 | runnerObj.DevelopmentTeam = DEVELOPMENT_TEAM; 51 | } 52 | 53 | fs.writeFileSync(projectPath, myProj.writeSync()); 54 | 55 | if (DEVELOPMENT_TEAM) { 56 | console.log('Successfully updated Bundle Id and Team Id.'); 57 | } else { 58 | console.log(`Successfully updated Bundle Id, but no Team Id was provided. Please update your team id manually in ${projectPath}, or reinstall the module with DEVELOPMENT_TEAM_ID in environment variable.`); 59 | } 60 | process.exit(0); 61 | } catch (e) { 62 | console.log('Failed to update Bundle Id and Team Id: ', e); 63 | } 64 | }; 65 | 66 | let version = doctorIOS.getXcodeVersion(); 67 | let pkgName = ''; 68 | 69 | if (parseFloat(version) >= parseFloat('10.0')) { 70 | version = ''; 71 | pkgName = xctestwdFrameworksPrefix; 72 | } else if (parseFloat(version) > parseFloat('9.2')) { 73 | version = version.replace(/\./, '').slice(0, 2); 74 | pkgName = `${xctestwdFrameworksPrefix}-${version}`; 75 | } 76 | 77 | const dir = require.resolve(pkgName); 78 | const originDir = path.join(dir, '..', 'Carthage'); 79 | const distDir = path.join(__dirname, '..'); 80 | console.log(`start to mv ${_.chalk.gray(originDir)} ${_.chalk.gray(distDir)}`); 81 | 82 | try { 83 | shelljs.mv('-n', originDir, distDir); 84 | } catch (e) { 85 | console.log(e); 86 | } 87 | 88 | const latestDir = path.join(distDir, 'Carthage'); 89 | 90 | if (_.isExistedDir(latestDir)) { 91 | console.log(_.chalk.cyan(`Carthage is existed: ${latestDir}`)); 92 | } else { 93 | throw _.chalk.red('Carthage is not existed, please reinstall!'); 94 | } 95 | updateInformation(); 96 | -------------------------------------------------------------------------------- /XCTestWD-master/scripts/integration-testing.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | brew install nvm > /dev/null 2>&1 4 | source $(brew --prefix nvm)/nvm.sh 5 | nvm install 8 6 | 7 | npm i macaca-scripts -g 8 | 9 | export XCTESTWD_PATH=`pwd`"/XCTestWD/XCTestWD.xcodeproj" 10 | 11 | echo process env XCTESTWD_PATH set to $XCTESTWD_PATH 12 | 13 | macaca-scripts integration-test-ios 14 | -------------------------------------------------------------------------------- /XCTestWD-master/test/mocha.opts: -------------------------------------------------------------------------------- 1 | --reporter spec 2 | -------------------------------------------------------------------------------- /XCTestWD-master/test/xctest.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const assert = require('assert'); 4 | 5 | const XCTest = require('..'); 6 | 7 | describe('test', function() { 8 | it('should be ok', function() { 9 | assert.ok(XCTest); 10 | }); 11 | }); 12 | --------------------------------------------------------------------------------