├── .gitignore ├── README.md ├── Version.txt ├── XCTestWD-master ├── .gitignore ├── .jshintignore ├── .jshintrc ├── .npmignore ├── .travis.yml ├── CONTRIBUTING.md ├── Cartfile ├── LICENSE ├── Makefile ├── README.md ├── XCTestWD │ ├── XCTestWD.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ ├── XCTestWD.xcscheme │ │ │ └── XCTestWDUITests.xcscheme │ ├── XCTestWD │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── ViewController.swift │ ├── XCTestWDUITests │ │ ├── Info.plist │ │ ├── PrivateHeaders │ │ │ ├── CDStructures.h │ │ │ ├── XCAXClient_iOS.h │ │ │ ├── XCAccessibilityElement.h │ │ │ ├── XCDebugLogDelegate-Protocol.h │ │ │ ├── XCElementSnapshot.h │ │ │ ├── XCRuntimeUtils.h │ │ │ ├── XCRuntimeUtils.m │ │ │ ├── XCTRunnerDaemonSession.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 │ │ │ ├── XCTestWDApplication.h │ │ │ ├── XCTestWDApplication.m │ │ │ ├── XCUIApplication.h │ │ │ ├── XCUICoordinate.h │ │ │ ├── XCUIElement.h │ │ │ └── XCUIElementQuery.h │ │ ├── XCTestWDRunner.swift │ │ ├── XCTestWDUITests-Bridging-Header.h │ │ └── server │ │ │ ├── XCTestWDController.swift │ │ │ ├── XCTestWDDispatch.swift │ │ │ ├── XCTestWDMonkey.swift │ │ │ ├── XCTestWDServer.swift │ │ │ ├── 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 │ │ │ └── models │ │ │ ├── XCTestWDAlert.swift │ │ │ ├── XCTestWDErrors.swift │ │ │ ├── XCTestWDReponse.swift │ │ │ ├── XCTestWDSession.swift │ │ │ ├── XCTestWDStatus.swift │ │ │ ├── XCTestWDXPath.swift │ │ │ ├── XCUIElementTypeTransformer.swift │ │ │ ├── extensions │ │ │ ├── XCTestWDAccessibility.swift │ │ │ └── XCTestWDApplicationTree.swift │ │ │ └── utils │ │ │ ├── XCTestWDFindElementUtils.swift │ │ │ └── XCTestWDMathUtils.swift │ ├── curlTests.sh │ └── libxml2 │ │ ├── libxml2-fuzi.h │ │ └── module.modulemap ├── index.js ├── lib │ ├── helper.js │ ├── logger.js │ ├── proxy.js │ ├── xctest-client.js │ └── xctestwd.js ├── package.json ├── scripts │ └── install.js └── test │ ├── mocha.opt │ └── xctest.test.js ├── Xml2Html.class ├── Xml2Html.java ├── app.xsl ├── config └── appinfo.txt ├── monitor_working.sh ├── start_monkey.sh └── summary.sh /.gitignore: -------------------------------------------------------------------------------- 1 | output/ 2 | tmp*/ 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AutoMonkey4I 2 | 3 | 4 | AutoMonkey4I是一个基于FastMonkey开发的IOS App自动化测试工具. 5 | 6 | FastMonkey 在XCTestWD基础上实现一个server路由,外部命令可引导启动app 并执行monkey,无需插桩、每秒可产生4-5个action 7 | 8 | ### 简要说明:
9 | 1. 支持参数化传入**测试时间、测试次数、测试端口及UDID**启动测试 10 | 2. 应用信息及登录名密码配置,config/appinfo.txt 11 | 3. 支持收集**系统日志(Systemlog)**、**崩溃日志(Crashlog)**、**事件操作日志(Eventlog)** 12 | 4. 支持自动**生成测试报告** 13 | 5. 支持多台设备同时测试及测试设备信息收集 14 | 6. FastMonkey框架添加登录功能及长时返回 15 | 7. 启用监控,FastMonkey中WD进程挂掉,自动重启并继续测试 16 | 17 |
18 | ### 系统要求: 19 | **MacOS High Sierra 版本10.13** 20 | 21 | **Xcode 9.0及以上** 22 | 23 | **IOS 9.0 及以上** 24 | 25 |
26 | ### 依赖及配置: 27 | Homebrew、zsh、JDK、Xcode9、**xcode command line tools、jq , 改进libimobiledevice** 28 |

29 | 1,安装xcode command line tools, 终端输入命令 30 | `xcode-select --install`回车后,按正常软件安装程序安装 31 |

32 | 2,安装jq, `brew install jq` 回车 33 |

34 | 3,**[安装改进版libimobiledevice](http://work.intra.yiguanjinrong.com/gitlab/yiguan-test/AutoMonkey4I/wikis/%E5%AE%89%E8%A3%85libimobiledevice)** 35 | 36 |
37 | ### 使用说明: 38 |
39 | 2,**更新依赖** 40 |

41 | 进入目录`cd xxxxx/AutoMonkey4I/XCTestWD-master` 42 | 43 | 更新第三方库 `carthage update` 44 |

45 | 3,**安装系统证书** 46 |

47 | AutoMonkey4I/Certificates 目录 48 |

49 | 4,**Xcode导入Provisioning Profile** 50 |

51 | 1)进入目录AutoMonkey4I/XCTestWD-master/XCTestWD, 打开XCTestWD.xcodeproj 52 |

53 | 2)Xcode中,XCTestWD->General->Signing,取消勾选Automatically manage signing, 54 | Provisioning Profile选择导入Certificates中 55 |

56 | 3)XCTestWDUITests->General->Signing, 选择同一Provisioning Profile 57 |

58 | 5,**应用信息配置** 59 |

60 | **AutoMonkey4I/config目录下, appinfo.txt** 61 | 62 | **Json数据格式:可支持多app测试**, 应用名、bundleId、用户名、密码。
63 | 如果无需登录,用户及密码设空即可 64 |
65 | `[ 66 | { 67 | "appName": "xxx", 68 | "bundleId": "xxx", 69 | "username": "13500000002", 70 | "password": "aaa123" 71 | }, 72 | { 73 | "appName": “Crasher", 74 | "bundleId": “com.yiguantest.crash", 75 | "username": "", 76 | "password": "" 77 | } 78 | ]` 79 |

80 | 6,**执行命令** 81 |

82 | AutoMonkey4I 主目录, [说明] 83 |

84 | **入口: start_monkey.sh, 四个参数, -u udid、 -p port、-t run_time、-n loop_num** 85 |

86 | **用法:四个参数皆为可选,没有相应参数时,使用默认值** 87 |

88 | 1) `./start_monkey.sh` 89 |

90 | 默认执行: 设备:连接pc的设备列表中的第一台、端口:8001、时间:60分钟、次数: 2 91 |

92 | 2) `./start_monkey.sh -u e55f18280b4f924b7cecca5d180bec93e654f351 -t 120m` 93 |

94 | 默认执行: 设备:指定此udid的设备、时间:120分钟、次数及端口为默认值 95 |
96 | 97 | ### 测试报告: 98 |
99 | **./output下相应时间的文件夹中** 100 |
101 | ***Summary:*** 102 |
103 |
104 | 105 | ### 附加说明 106 |
107 | ***自动登录:***
108 | 在FastMonkey中,实现参数化用户名及密码,间隔进行界面检查如符合登录界面并未登录,自动进行登录原子操作.
109 | 登录界面检查及登录逻辑基于一贯应用实现,如需测试其他应用,则要实现相关逻辑

110 | ***长时返回:***
111 | 在FastMonkey中,实现长时间隔检查,如果停留在同一页面则按返回到应用主界面.
112 | 检查页面及返回操作基于一贯应用实现,如需测试其他应用,则要实现相关逻辑

113 | ***以上两种功能在测试其他应用需单独实现 ,不实现也可以进行测试,只是没有相关功能*** 114 |

115 | 116 | ### 相关参考 117 |
118 | **[Homebrew:http://www.jianshu.com/p/d229ac7fe77d](http://www.jianshu.com/p/d229ac7fe77d)**
119 | **[zsh:http://www.jianshu.com/p/ae378aa725cf](http://www.jianshu.com/p/ae378aa725cf)**
120 | **[FastMonkey: https://github.com/zhangzhao4444/Fastmonkey](https://github.com/zhangzhao4444/Fastmonkey)**
121 | **[libimobiledevice: https://testerhome.com/topics/8069](https://testerhome.com/topics/8069)**
122 | **[jq:http://blog.sina.com.cn/s/blog_56ae1d580102xv7d.html](http://blog.sina.com.cn/s/blog_56ae1d580102xv7d.html)**
123 | **[xcodebuild:https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/xcodebuild.1.html](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/xcodebuild.1.html)**
124 | **[IOS签名证书:http://www.jianshu.com/p/9d9e3699515e](http://www.jianshu.com/p/9d9e3699515e)**
125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /Version.txt: -------------------------------------------------------------------------------- 1 | Version:1.0.20171027 2 | -------------------------------------------------------------------------------- /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 "glock45/swifter" == 1.3.3 2 | github "SwiftyJSON/SwiftyJSON" 3 | github "cezheng/Fuzi" ~> 1.0.0 4 | github "tadija/AEXML" 5 | -------------------------------------------------------------------------------- /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 | git_version = $$(git branch 2>/dev/null | sed -e '/^[^*]/d'-e's/* \(.*\)/\1/') 2 | npm_bin= $$(npm bin) 3 | 4 | all: install 5 | carthage: 6 | carthage update --platform iOS 7 | build: carthage 8 | xcodebuild -project ./XCTestWD/XCTestWD.xcodeproj -sdk iphonesimulator 9 | install: 10 | @npm install 11 | test: 12 | @node --harmony \ 13 | ${npm_bin}/istanbul cover ${npm_bin}/_mocha \ 14 | -- \ 15 | --timeout 100000 \ 16 | --require co-mocha 17 | travis: install carthage 18 | @NODE_ENV=test $(BIN) $(FLAGS) \ 19 | ./node_modules/.bin/istanbul cover \ 20 | ./node_modules/.bin/_mocha \ 21 | --report lcovonly \ 22 | -- -u exports \ 23 | $(REQUIRED) \ 24 | $(TESTS) \ 25 | --bail 26 | jshint: 27 | @${npm_bin}/jshint . 28 | .PHONY: test 29 | -------------------------------------------------------------------------------- /XCTestWD-master/README.md: -------------------------------------------------------------------------------- 1 | # XCTestWD 2 | 3 | [![NPM version][npm-image]][npm-url] 4 | [![build status][travis-image]][travis-url] 5 | [![Test coverage][coveralls-image]][coveralls-url] 6 | [![node version][node-image]][node-url] 7 | [![npm download][download-image]][download-url] 8 | 9 | [npm-image]: https://img.shields.io/npm/v/xctestwd.svg?style=flat-square 10 | [npm-url]: https://npmjs.org/package/xctestwd 11 | [travis-image]: https://img.shields.io/travis/macacajs/XCTestWD.svg?style=flat-square 12 | [travis-url]: https://travis-ci.org/macacajs/XCTestWD 13 | [coveralls-image]: https://img.shields.io/coveralls/macacajs/XCTestWD.svg?style=flat-square 14 | [coveralls-url]: https://coveralls.io/r/macacajs/XCTestWD?branch=master 15 | [node-image]: https://img.shields.io/badge/node.js-%3E=_6-green.svg?style=flat-square 16 | [node-url]: http://nodejs.org/download/ 17 | [download-image]: https://img.shields.io/npm/dm/xctestwd.svg?style=flat-square 18 | [download-url]: https://npmjs.org/package/xctestwd 19 | 20 | > A Swift implementation of WebDriver server for iOS that runs on Simulator/iOS devices. 21 | 22 | ## 1. Requirements 23 | 24 | - XCode version 8.3.0 and above. 25 | - iOS version 9.0 and above. 26 | 27 | ## 2. Starting XCTestWD 28 | 29 | 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` 30 | 31 | ### 2.1. Using Xcode 32 | 33 | Download the project and open the XCode project, checkout the scheme `XCTestWDUITests` and run the test case `XCTextWDRunner` 34 | 35 | ### 2.2. Using XcodeBuild 36 | 37 | Open the terminal, go to the directory where contains `XCTestWD.xcodeproj` file and execute the following command: 38 | 39 | ``` bash 40 | # 41 | #Change the port number to override the default port 42 | # 43 | $ xcodebuild -project XCTestWD.xcodeproj \ 44 | -scheme XCTestWDUITests \ 45 | -destination 'platform=iOS Simulator,name=iPhone 6' \ 46 | XCTESTWD_PORT=8001 \ 47 | clean test 48 | ``` 49 | 50 | To execute for iOS device, run the following command: 51 | 52 | ``` bash 53 | # 54 | #Change the port number to override the default port 55 | #Specify the device name 56 | # 57 | $ xcodebuild -project XCTestWD.xcodeproj \ 58 | -scheme XCTestWDUITests \ 59 | -destination 'platform=iOS,name=(your device name)' \ 60 | XCTESTWD_PORT=8001 \ 61 | clean test 62 | ``` 63 | 64 | 65 | ## 3. Element Types 66 | 67 | 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) 68 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD.xcodeproj/xcshareddata/xcschemes/XCTestWD.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 34 | 40 | 41 | 42 | 43 | 44 | 50 | 51 | 52 | 53 | 54 | 55 | 66 | 68 | 74 | 75 | 76 | 77 | 78 | 79 | 85 | 87 | 93 | 94 | 95 | 96 | 98 | 99 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD.xcodeproj/xcshareddata/xcschemes/XCTestWDUITests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 34 | 40 | 41 | 42 | 43 | 44 | 50 | 51 | 52 | 53 | 54 | 55 | 66 | 67 | 73 | 74 | 75 | 76 | 77 | 78 | 84 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // XCTestWD 4 | // 5 | // Created by xdf on 22/04/2017. 6 | // Copyright © 2017 XCTestWD. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWD/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // XCTestWD 4 | // 5 | // Created by xdf on 22/04/2017. 6 | // Copyright © 2017 XCTestWD. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/PrivateHeaders/XCAccessibilityElement.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 | @interface XCAccessibilityElement : NSObject 10 | { 11 | NSString *_context; 12 | id _payload; 13 | int _processIdentifier; 14 | struct __AXUIElement *_axElement; 15 | unsigned long long _elementType; 16 | } 17 | @property(readonly) id payload; // @synthesize payload=_payload; 18 | @property(readonly) int processIdentifier; // @synthesize processIdentifier=_processIdentifier; 19 | @property(readonly) const struct __AXUIElement *AXUIElement; // @synthesize AXUIElement=_axElement; 20 | @property(readonly, getter=isNative) BOOL native; 21 | 22 | + (id)elementWithAXUIElement:(struct __AXUIElement *)arg1; 23 | + (id)elementWithProcessIdentifier:(int)arg1; 24 | + (id)deviceElement; 25 | + (id)mockElementWithProcessIdentifier:(int)arg1 payload:(id)arg2; 26 | + (id)mockElementWithProcessIdentifier:(int)arg1; 27 | 28 | - (id)initWithMockProcessIdentifier:(int)arg1 payload:(id)arg2; 29 | - (id)initWithAXUIElement:(struct __AXUIElement *)arg1; 30 | - (id)init; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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 | 12 | #include 13 | #import 14 | 15 | NSArray *FBClassesThatConformsToProtocol(Protocol *protocol) 16 | { 17 | Class *classes = NULL; 18 | NSMutableArray *collection = [NSMutableArray array]; 19 | int numClasses = objc_getClassList(NULL, 0); 20 | if (numClasses == 0 ) { 21 | return @[]; 22 | } 23 | 24 | classes = (__unsafe_unretained Class*)malloc(sizeof(Class) * numClasses); 25 | numClasses = objc_getClassList(classes, numClasses); 26 | for (int index = 0; index < numClasses; index++) { 27 | Class aClass = classes[index]; 28 | if (class_conformsToProtocol(aClass, protocol)) { 29 | [collection addObject:aClass]; 30 | } 31 | } 32 | 33 | free(classes); 34 | return collection.copy; 35 | } 36 | 37 | void *FBRetrieveSymbolFromBinary(const char *binary, const char *name) 38 | { 39 | void *handle = dlopen(binary, RTLD_LAZY); 40 | NSCAssert(handle, @"%s could not be opened", binary); 41 | void *pointer = dlsym(handle, name); 42 | NSCAssert(pointer, @"%s could not be located", name); 43 | return pointer; 44 | } 45 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/PrivateHeaders/XCTestWDApplication.h: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDApplication.h 3 | // XCTestWDUITests 4 | // 5 | // 6 | 7 | #import 8 | #import "XCUIApplication.h" 9 | 10 | @interface XCTestWDApplication: NSObject 11 | 12 | +(XCUIApplication*)activeApplication; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/PrivateHeaders/XCTestWDApplication.m: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDApplication.h 3 | // XCTestWDUITests 4 | // 5 | // 6 | 7 | #import "XCTestWDApplication.h" 8 | #import "XCUIApplication.h" 9 | #import "XCAXClient_iOS.h" 10 | 11 | @implementation XCTestWDApplication 12 | 13 | +(XCUIApplication*)activeApplication 14 | { 15 | id activeApplicationElement = ((NSArray*)[[XCAXClient_iOS sharedClient] activeApplications]).lastObject; 16 | if(!activeApplicationElement){ 17 | activeApplicationElement = ((XCAXClient_iOS*)[XCAXClient_iOS sharedClient]).systemApplication; 18 | } 19 | XCUIApplication* application = [XCTestWDApplication createByPID:[[activeApplicationElement valueForKey:@"processIdentifier"] intValue]]; 20 | [application query]; 21 | return application; 22 | } 23 | 24 | +(XCUIApplication*)createByPID:(pid_t)pid 25 | { 26 | if([XCUIApplication respondsToSelector:@selector(appWithPID:)]){ 27 | return [XCUIApplication appWithPID:pid]; 28 | } 29 | return [XCUIApplication applicationWithPID:pid]; 30 | } 31 | 32 | @end 33 | 34 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/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; 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/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/XCTestWDRunner.swift: -------------------------------------------------------------------------------- 1 | // 2 | // testUITests.swift 3 | // testUITests 4 | // 5 | // fixed by zhangzhao on 29/08/2017. 6 | // 7 | 8 | import XCTest 9 | import Swifter 10 | 11 | 12 | class XCTextWDRunner: XCTestCase { 13 | var serverMode = true 14 | var server: XCTestWDServer? 15 | var monkey: XCTestWDMonkey? 16 | override func setUp() { 17 | super.setUp() 18 | continueAfterFailure = false 19 | NotificationCenter.default.addObserver(self, 20 | selector: #selector(terminate(notification:)), 21 | name: NSNotification.Name(rawValue: XCTestWDSessionShutDown), 22 | object: nil) 23 | } 24 | 25 | override func tearDown() { 26 | super.tearDown() 27 | } 28 | 29 | func testRunner() { 30 | if serverMode { 31 | self.server = XCTestWDServer() 32 | self.server?.startServer() 33 | }else{ 34 | self.monkey = XCTestWDMonkey() 35 | _ = self.monkey?.startMonkey() 36 | } 37 | } 38 | 39 | @objc func terminate(notification: NSNotification){ 40 | if serverMode { 41 | self.server?.stopServer() 42 | } 43 | NSLog("XCTestWDTearDown->Session Reset") 44 | assert(false, "") 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/XCTestWDUITests-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // XCTestWDUITests-Bridge-Header.h 3 | // XCTestWD 4 | // 5 | // Created by xdf on 23/04/2017. 6 | // Copyright © 2017 XCTestWD. All rights reserved. 7 | // 8 | 9 | #import "CDStructures.h" 10 | #import "XCUIElementQuery.h" 11 | #import "XCUIElement.h" 12 | #import "XCElementSnapshot.h" 13 | #import "XCAXClient_iOS.h" 14 | #import "XCUIApplication.h" 15 | #import "XCAccessibilityElement.h" 16 | #import "XCTestPrivateSymbols.h" 17 | #import "XCUICoordinate.h" 18 | #import "XCTestDriver.h" 19 | #import "XCTestDaemonsProxy.h" 20 | #import "XCTRunnerDaemonSession.h" 21 | #import 22 | #import "XCTestWDApplication.h" 23 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/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/XCTestWDUITests/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 | 26 | response = routingCall(request) 27 | } 28 | return response 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/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 | 13 | func startMonkey() -> Int { 14 | 15 | let bundleID = "com.PandaTV.Live-iPhone" 16 | //let bundleID = "com.pandatv.test.meizi" 17 | 18 | var app : XCUIApplication! 19 | var session : XCTestWDSession! 20 | let path :String? = nil 21 | app = XCUIApplication.init(privateWithPath: path, bundleID: bundleID)! 22 | app!.launch() 23 | 24 | if app != nil { 25 | session = XCTestWDSession.sessionWithApplication(app!) 26 | XCTestWDSessionManager.singleton.mountSession(session) 27 | try? session.resolve() 28 | } 29 | 30 | if app?.processID == 0 { 31 | return -1 32 | } 33 | 34 | sleep(4) 35 | NSLog("XCTestWDSetup->start fastmonkey<-XCTestWDSetup") 36 | 37 | _ = app.descendants(matching: .any).element(boundBy: 0).frame 38 | let monkey = Monkey(frame: app.frame) 39 | monkey.addDefaultXCTestPrivateActions() 40 | monkey.addXCTestTapAlertAction(interval: 100, application: app) 41 | monkey.addXCTestCheckCurrentApp(interval: 10, application: app) 42 | //monkey.addXCTestAppLogin(interval: 50, application: app) 43 | monkey.monkeyAround() 44 | RunLoop.main.run() 45 | return 0 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/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 | 12 | public class XCTestWDServer { 13 | 14 | private let server = HttpServer() 15 | 16 | internal func startServer() { 17 | do { 18 | try server.start(fetchPort()) 19 | registerRouters() 20 | 21 | NSLog("\(Bundle.main.bundleIdentifier!)") 22 | 23 | 24 | NSLog("XCTestWDSetup->http://localhost:\(try! server.port())<-XCTestWDSetup") 25 | RunLoop.main.run() 26 | } catch { 27 | print("Server start error: \(error)") 28 | } 29 | } 30 | 31 | internal func stopServer() { 32 | server.stop() 33 | } 34 | 35 | private func registerRouters() { 36 | 37 | var controllers = [Controller]() 38 | 39 | controllers.append(XCTestWDActionsController()) 40 | controllers.append(XCTestWDAlertController()) 41 | controllers.append(XCTestWDContextController()) 42 | controllers.append(XCTestWDElementController()) 43 | controllers.append(XCTestWDExecuteController()) 44 | controllers.append(XCTestWDKeysController()) 45 | controllers.append(XCTestWDScreenshotController()) 46 | controllers.append(XCTestWDSessionController()) 47 | controllers.append(XCTestWDSourceController()) 48 | controllers.append(XCTestWDStatusController()) 49 | controllers.append(XCTestWDTimeoutController()) 50 | controllers.append(XCTestWDTitleController()) 51 | controllers.append(XCTestWDElementController()) 52 | controllers.append(XCTestWDWindowController()) 53 | controllers.append(XCTestWDUrlController()) 54 | controllers.append(XCTestWDMonkeyController()) 55 | 56 | for controller in controllers { 57 | let routes = type(of: controller).routes() 58 | for i in 0...routes.count - 1 { 59 | let (router, requestHandler) = routes[i] 60 | var routeMethod: HttpServer.MethodRoute? 61 | 62 | switch router.verb { 63 | case "post","POST": 64 | routeMethod = server.POST 65 | break 66 | case "get","GET": 67 | routeMethod = server.GET 68 | break 69 | case "put", "PUT": 70 | routeMethod = server.PUT 71 | break 72 | case "delete", "DELETE": 73 | routeMethod = server.DELETE 74 | break 75 | case "update", "UPDATE": 76 | routeMethod = server.UPDATE 77 | break 78 | default: 79 | routeMethod = nil 80 | break 81 | } 82 | 83 | routeMethod?[router.path] = RouteOnMain(requestHandler) 84 | } 85 | } 86 | } 87 | 88 | private func fetchPort() -> in_port_t { 89 | 90 | let arguments = ProcessInfo.processInfo.arguments 91 | let index = arguments.index(of: "--port") 92 | var startingPort:Int = Int(portNumber()) 93 | if index != nil { 94 | if index! != NSNotFound || index! < arguments.count - 1{ 95 | startingPort = Int(arguments[index!+1])! 96 | } 97 | } 98 | 99 | var (isValid, _) = checkTcpPortForListen(port: in_port_t(startingPort)) 100 | while isValid == false { 101 | startingPort = startingPort + 1 102 | (isValid, _) = checkTcpPortForListen(port: in_port_t(startingPort)) 103 | } 104 | 105 | return in_port_t(startingPort) 106 | } 107 | 108 | //MARK: Check Port is occupied 109 | func checkTcpPortForListen(port: in_port_t) -> (Bool, descr: String){ 110 | 111 | let socketFileDescriptor = socket(AF_INET, SOCK_STREAM, 0) 112 | if socketFileDescriptor == -1 { 113 | return (false, "SocketCreationFailed, \(descriptionOfLastError())") 114 | } 115 | 116 | var addr = sockaddr_in() 117 | addr.sin_len = __uint8_t(MemoryLayout.size) 118 | addr.sin_family = sa_family_t(AF_INET) 119 | addr.sin_port = Int(OSHostByteOrder()) == OSLittleEndian ? _OSSwapInt16(port) : port 120 | addr.sin_addr = in_addr(s_addr: inet_addr("0.0.0.0")) 121 | 122 | addr.sin_zero = (0, 0, 0, 0, 0, 0, 0, 0) 123 | var bind_addr = sockaddr() 124 | memcpy(&bind_addr, &addr, Int(MemoryLayout.size)) 125 | 126 | if bind(socketFileDescriptor, &bind_addr, socklen_t(MemoryLayout.size)) == -1 { 127 | let details = descriptionOfLastError() 128 | release(socket: socketFileDescriptor) 129 | return (false, "\(port), BindFailed, \(details)") 130 | } 131 | if listen(socketFileDescriptor, SOMAXCONN ) == -1 { 132 | let details = descriptionOfLastError() 133 | release(socket: socketFileDescriptor) 134 | return (false, "\(port), ListenFailed, \(details)") 135 | } 136 | release(socket: socketFileDescriptor) 137 | return (true, "\(port) is free for use") 138 | } 139 | 140 | func release(socket: Int32) { 141 | _ = Darwin.shutdown(socket, SHUT_RDWR) 142 | close(socket) 143 | } 144 | 145 | func descriptionOfLastError() -> String { 146 | return "Error: \(errno)" 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/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 = UInt(self!.r.randomUInt32() % UInt32(buttons.count)) 51 | let button = buttons.element(boundBy: index) 52 | button.tap() 53 | let useStr="Button tap \(String(describing: button))" 54 | NSLog("XCTestMonkey:%@",useStr) 55 | return 56 | } 57 | }else{ 58 | application.activate() 59 | self!.sleep(5) 60 | self?.pid = Int(XCTestWDFindElementUtils.getAppPid()) 61 | let useStr="app kack to foreground)" 62 | NSLog("XCTestMonkey:%@",useStr) 63 | return 64 | } 65 | } 66 | } 67 | 68 | /** 69 | Add an action that checks current app, at a fixed interval, 70 | if app is not running , so launch app 71 | */ 72 | 73 | public func addXCTestCheckCurrentApp(interval:Int, application:XCUIApplication) { 74 | addCheck(interval:interval){ [weak self] in 75 | //let work = DispatchWorkItem(qos:.userInteractive){ 76 | /** too slow **/ 77 | //application._waitForQuiescence() 78 | // let isRunning = application.running 79 | // let current = Int(XCTestWDFindElementUtils.getAppPid()) 80 | // if current != self?.pid || !isRunning{ 81 | // application.launch() 82 | // self?.sleep(5) 83 | // self?.pid = Int(XCTestWDFindElementUtils.getAppPid()) 84 | // } 85 | //} 86 | //DispatchQueue.main.async(execute:work) 87 | let work = DispatchWorkItem(qos:.userInteractive){ 88 | if (application.state != XCUIApplication.State.runningForeground){ 89 | application.activate() 90 | self?.sleep(5) 91 | self?.pid = Int(XCTestWDFindElementUtils.getAppPid()) 92 | let useStr="app back to foreground)" 93 | NSLog("XCTestMonkey:%@",useStr) 94 | } 95 | } 96 | DispatchQueue.main.async(execute:work) 97 | } 98 | } 99 | 100 | /** 101 | display current page to assist resolve problem 102 | */ 103 | 104 | public func addXCTestCurrentPage(interval:Int, application:XCUIApplication){ 105 | addAction(interval: interval){ 106 | do{ 107 | let session = try XCTestWDSessionManager.singleton.checkDefaultSessionthrow() 108 | let root = session.application 109 | if root != nil{ 110 | let usage = "class name" 111 | let tag = "XCUIElementTypeNavigationBar" 112 | let element = try? XCTestWDFindElementUtils.filterElement(usingText: usage, withvalue: tag, underElement: root!) 113 | if let element = element { 114 | if element != nil { 115 | NSLog("XCTestMonkey:current page is \(String(describing: element?.rootName()))") 116 | } 117 | } 118 | } 119 | }catch{ 120 | return 121 | } 122 | } 123 | } 124 | 125 | /** 126 | Add an action that check ui , at a fixed interval, 127 | if find the same ui then back to main ui 128 | */ 129 | 130 | public func addXCTestAppMain(interval:Int, application:XCUIApplication) { 131 | addAction(interval:interval){ [weak self] in 132 | do{ 133 | let session = try XCTestWDSessionManager.singleton.checkDefaultSessionthrow() 134 | let root = session.application 135 | if root != nil{ 136 | let usage = "class name" 137 | let tag = "XCUIElementTypeNavigationBar" 138 | let element = try? XCTestWDFindElementUtils.filterElement(usingText: usage, withvalue: tag, underElement: root!) 139 | if let element = element { 140 | if element != nil { 141 | NSLog("XCTestMonkey:ui at \(String(describing: element?.rootName()))") 142 | if self?.preElement == nil{ 143 | NSLog("XCTestMonkey:ui at first time \(String(describing: element?.rootName()))") 144 | self?.preElement=(String(describing: element?.rootName())) 145 | return 146 | }else if self?.preElement == (String(describing:element?.rootName())){ 147 | NSLog("XCTestMonkey:ui at second time\(String(describing: element?.rootName()))") 148 | let back = element?.children(matching:.button) 149 | let rect = back?.firstMatch.wdFrame() 150 | if let rect = rect { 151 | NSLog("XCTestMonkey:ui at 3333 \(String(describing: element?.rootName()))") 152 | var loop = 1 153 | while loop<4 { 154 | let numberOfTaps: UInt = 1 155 | let locations: [CGPoint] 156 | locations = [self!.randomPoint(inRect: rect)] 157 | let semaphore = DispatchSemaphore(value: 0) 158 | self!.sharedXCEventGenerator.tapAtTouchLocations(locations, numberOfTaps: numberOfTaps, orientation: orientationValue) { 159 | semaphore.signal() 160 | } 161 | let useStr="Bact to Main screen Tap \(String(describing: locations))" 162 | NSLog("XCTestMonkey:%@",useStr) 163 | semaphore.wait() 164 | usleep(500000) 165 | loop = loop + 1 166 | } 167 | } 168 | return 169 | }else{ 170 | NSLog("XCTestMonkey:ui at nothing \(String(describing: element?.rootName()))<-XCTestWDSetup") 171 | self?.preElement=(String(describing: element?.rootName())) 172 | return 173 | } 174 | }else{ 175 | return 176 | } 177 | } 178 | } 179 | }catch{ 180 | return 181 | } 182 | } 183 | } 184 | 185 | public func addXCTestPasswordAction(interval:Int, application:XCUIApplication){ 186 | addAction(interval:interval){ [weak self] in 187 | do{ 188 | let session = try XCTestWDSessionManager.singleton.checkDefaultSessionthrow() 189 | let root = session.application 190 | if root != nil{ 191 | let usage = "xpath" 192 | let tag = "//XCUIElementTypeImage[@name='eg_password']" 193 | let element = try? XCTestWDFindElementUtils.filterElement(usingText: usage, withvalue: tag, underElement: root!) 194 | if let element = element { 195 | if element != nil { 196 | self?.addXCTestPasswordAction(application: application) 197 | }else{ 198 | return 199 | } 200 | } 201 | } 202 | }catch{ 203 | return 204 | } 205 | } 206 | } 207 | 208 | /** 209 | Add an action that check login keypoint, at a fixed interval, 210 | if find key point, take login event 211 | */ 212 | 213 | public func addXCTestAppLogin(interval:Int, application:XCUIApplication,username:String,password:String) { 214 | addAction(interval:interval){ [weak self] in 215 | do{ 216 | let session = try XCTestWDSessionManager.singleton.checkDefaultSessionthrow() 217 | let root = session.application 218 | if root != nil{ 219 | let usage = "xpath" 220 | let tag = "//XCUIElementTypeStaticText[@name='记住用户名']" 221 | let element = try? XCTestWDFindElementUtils.filterElement(usingText: usage, withvalue: tag, underElement: root!) 222 | if let element = element { 223 | if element != nil { 224 | self?.addXCTestLoginAction(application: application,username:username,password:password) 225 | } 226 | else{ 227 | return 228 | } 229 | } 230 | } 231 | }catch{ 232 | return 233 | } 234 | } 235 | } 236 | } 237 | 238 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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 | 13 | internal class XCTestWDAlertController: Controller { 14 | 15 | //MARK: Controller - Protocol 16 | static func routes() -> [(RequestRoute, RoutingCall)] { 17 | return [(RequestRoute("/wd/hub/session/:sessionId/accept_alert", "post"), acceptAlert), 18 | (RequestRoute("/wd/hub/session/:sessionId/dismiss_alert", "post"), dismissAlert), 19 | (RequestRoute("/wd/hub/session/:sessionId/alert_text", "get"), alertText), 20 | (RequestRoute("/wd/hub/session/:sessionId/alert_text", "post"), alertKeys)] 21 | } 22 | 23 | static func shouldRegisterAutomatically() -> Bool { 24 | return false 25 | } 26 | 27 | //MARK: Routing Logic Specification 28 | internal static func acceptAlert(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 29 | if request.session == nil { 30 | return XCTestWDResponse.response(session: nil, error: WDStatus.SessionNotCreatedException) 31 | } else { 32 | let alert = XCTestWDAlert(request.session!.application) 33 | if alert.accept() { 34 | return XCTestWDResponse.response(session: request.session!, value: nil) 35 | 36 | } else { 37 | return XCTestWDResponse.response(session: request.session!, error: WDStatus.NoAlertOpenError) 38 | } 39 | } 40 | } 41 | 42 | internal static func dismissAlert(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 43 | if request.session == nil { 44 | return XCTestWDResponse.response(session: nil, error: WDStatus.SessionNotCreatedException) 45 | } else { 46 | let alert = XCTestWDAlert(request.session!.application) 47 | if alert.dismiss() { 48 | return XCTestWDResponse.response(session: request.session!, value: nil) 49 | } else { 50 | return XCTestWDResponse.response(session: request.session!, error: WDStatus.NoAlertOpenError) 51 | } 52 | } 53 | } 54 | 55 | internal static func alertText(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 56 | if request.session == nil { 57 | return XCTestWDResponse.response(session: nil, error: WDStatus.SessionNotCreatedException) 58 | } else { 59 | let alert = XCTestWDAlert(request.session!.application) 60 | let text = alert.text() 61 | if text != nil { 62 | return XCTestWDResponse.response(session: request.session!, value: JSON(text!)) 63 | } else { 64 | return XCTestWDResponse.response(session: request.session!, error: WDStatus.NoAlertOpenError) 65 | } 66 | } 67 | } 68 | 69 | internal static func alertKeys(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 70 | if request.session == nil { 71 | return XCTestWDResponse.response(session: nil, error: WDStatus.SessionNotCreatedException) 72 | } else { 73 | let alert = XCTestWDAlert(request.session!.application) 74 | if alert.keys(input: request.params["text"] ?? "") { 75 | return XCTestWDResponse.response(session: request.session!, value: JSON(text!)) 76 | } else { 77 | return XCTestWDResponse.response(session: request.session!, error: WDStatus.NoAlertOpenError) 78 | } 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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 | //MARK: Routing Logic Specification 35 | internal static func swiftmonkey(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 36 | var app : XCUIApplication! 37 | var session : XCTestWDSession! 38 | 39 | let desiredCapabilities = request.jsonBody["desiredCapabilities"].dictionary 40 | let path = desiredCapabilities?["app"]?.string ?? nil 41 | let bundleID = desiredCapabilities?["bundleId"]?.string ?? nil 42 | let username=desiredCapabilities?["username"]?.string ?? nil 43 | let password=desiredCapabilities?["password"]?.string ?? nil 44 | if bundleID == nil { 45 | app = XCTestWDSession.activeApplication() 46 | } else { 47 | app = XCUIApplication.init(privateWithPath: path, bundleID: bundleID)! 48 | app!.launchArguments = desiredCapabilities?["arguments"]?.arrayObject as! [String]? ?? [String]() 49 | app!.launchEnvironment = desiredCapabilities?["environment"]?.dictionaryObject as! [String : String]? ?? [String:String](); 50 | app!.launch() 51 | } 52 | 53 | if app != nil { 54 | session = XCTestWDSession.sessionWithApplication(app!) 55 | XCTestWDSessionManager.singleton.mountSession(session) 56 | try? session.resolve() 57 | } 58 | 59 | if app?.processID == 0 { 60 | return HttpResponse.internalServerError 61 | } 62 | 63 | sleep(10) 64 | NSLog("XCTestWDSetup->start fastmonkey<-XCTestWDSetup") 65 | 66 | _ = app.descendants(matching: .any).element(boundBy: 0).frame 67 | let monkey = Monkey(frame: app.frame) 68 | monkey.addDefaultXCTestPrivateActions() 69 | monkey.addXCTestTapAlertAction(interval: 100, application: app) 70 | monkey.addXCTestCheckCurrentApp(interval: 10, application: app) 71 | if bundleID == "com.egbank.EGBankP2B-Dev" { 72 | monkey.addXCTestPasswordAction(interval:30, application:app) 73 | } 74 | monkey.addXCTestAppMain(interval: 150, application: app) 75 | monkey.addXCTestCurrentPage(interval: 25, application: app) 76 | if username != nil && password != nil { 77 | monkey.addXCTestAppLogin(interval: 60, application: app,username:username!,password:password!) 78 | } 79 | monkey.monkeyAround() 80 | 81 | return XCTestWDResponse.response(session: session, value: sessionInformation(session)) 82 | } 83 | 84 | //MARK: Response helpers 85 | private static func sessionInformation(_ session:XCTestWDSession) -> JSON { 86 | var result:JSON = ["sessionId":session.identifier] 87 | var capabilities:JSON = ["device": UIDevice.current.userInterfaceIdiom == UIUserInterfaceIdiom.pad ? "ipad" : "iphone"] 88 | capabilities["sdkVersion"] = JSON(UIDevice.current.systemVersion) 89 | capabilities["browserName"] = JSON(session.application.label) 90 | capabilities["CFBundleIdentifier"] = JSON(session.application.bundleID ?? "Null") 91 | result["capabilities"] = capabilities 92 | return result 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/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 data = (XCAXClient_iOS.sharedClient() as! XCAXClient_iOS).screenshotData() 29 | base64String = ((data?.base64EncodedString()))! 30 | return XCTestWDResponse.response(session: request.session, value: JSON(base64String!)) 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/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 | 14 | let XCTestWDSessionShutDown = "XCTestWDSessionShutDown" 15 | 16 | internal class XCTestWDSessionController: Controller { 17 | 18 | //MARK: Controller - Protocol 19 | static func routes() -> [(RequestRoute, RoutingCall)] { 20 | return [(RequestRoute("/wd/hub/session", "post"), createSession), 21 | (RequestRoute("/wd/hub/sessions", "get"), getSessions), 22 | (RequestRoute("/wd/hub/session/:sessionId", "delete"), delSession)] 23 | } 24 | 25 | static func shouldRegisterAutomatically() -> Bool { 26 | return false 27 | } 28 | 29 | //MARK: Routing Logic Specification 30 | internal static func createSession(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 31 | var app : XCUIApplication! 32 | var session : XCTestWDSession! 33 | 34 | let desiredCapabilities = request.jsonBody["desiredCapabilities"].dictionary 35 | let path = desiredCapabilities?["app"]?.string ?? nil 36 | let bundleID = desiredCapabilities?["bundleId"]?.string ?? nil 37 | if bundleID == nil { 38 | app = XCTestWDSession.activeApplication() 39 | } else { 40 | app = XCUIApplication.init(privateWithPath: path, bundleID: bundleID)! 41 | app!.launchArguments = desiredCapabilities?["arguments"]?.arrayObject as! [String]? ?? [String]() 42 | app!.launchEnvironment = desiredCapabilities?["environment"]?.dictionaryObject as! [String : String]? ?? [String:String](); 43 | app!.launch() 44 | } 45 | 46 | if app != nil { 47 | session = XCTestWDSession.sessionWithApplication(app!) 48 | XCTestWDSessionManager.singleton.mountSession(session) 49 | try? session.resolve() 50 | } 51 | 52 | if app?.processID == 0 { 53 | return HttpResponse.internalServerError 54 | } 55 | 56 | return XCTestWDResponse.response(session: session, value: sessionInformation(session)) 57 | } 58 | 59 | internal static func getSessions(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 60 | return XCTestWDResponse.response(session: nil, value: sessionList()) 61 | } 62 | 63 | internal static func delSession(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 64 | return XCTestWDResponse.response(session: nil, value: removeSessionById(request.session?.identifier ?? "")) 65 | } 66 | 67 | //MARK: Response helpers 68 | private static func sessionInformation(_ session:XCTestWDSession) -> JSON { 69 | var result:JSON = ["sessionId":session.identifier] 70 | var capabilities:JSON = ["device": UIDevice.current.userInterfaceIdiom == UIUserInterfaceIdiom.pad ? "ipad" : "iphone"] 71 | capabilities["sdkVersion"] = JSON(UIDevice.current.systemVersion) 72 | capabilities["browserName"] = JSON(session.application.label) 73 | capabilities["CFBundleIdentifier"] = JSON(session.application.bundleID ?? "Null") 74 | result["capabilities"] = capabilities 75 | return result 76 | } 77 | 78 | private static func sessionList() -> JSON { 79 | var raw = [[String:String]]() 80 | let sessionMap = XCTestWDSessionManager.singleton.queryAll() 81 | for (sessionId, _) in sessionMap { 82 | raw.append(["id":sessionId]) 83 | } 84 | return JSON(raw) 85 | } 86 | 87 | private static func removeSessionById(_ sessionId:String) -> JSON { 88 | XCTestWDSessionManager.singleton.deleteSession(sessionId) 89 | return JSON("") 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/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 | //let temp = XCTestWDSessionManager.singleton.checkDefaultSession().application.tree() 38 | return XCTestWDResponse.response(session: request.session, value: JSON(temp!)) 39 | } 40 | 41 | internal static func accessiblitySource(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 42 | let _ = request.session?.application.query() 43 | request.session?.application.resolve() 44 | let temp = request.session?.application.accessibilityTree() 45 | return XCTestWDResponse.response(session: request.session, value: JSON(JSON(temp!).rawString() ?? "")) 46 | } 47 | 48 | internal static func accessiblitySourceWithoutSession(request: Swifter.HttpRequest) -> Swifter.HttpResponse { 49 | let temp = XCTestWDSession.activeApplication()?.accessibilityTree() 50 | //let temp = XCTestWDSessionManager.singleton.checkDefaultSession().application.accessibilityTree() 51 | return XCTestWDResponse.response(session: request.session, value: JSON(temp!)) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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/XCTestWDUITests/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 application = XCTestWDSession.activeApplication() 28 | let frame = application?.wdFrame() 29 | let screenSize = MathUtils.adjustDimensionsForApplication(frame!.size, UIDeviceOrientation.init(rawValue:(application?.interfaceOrientation.rawValue)!)!) 30 | 31 | return XCTestWDResponse.response(session: nil, value: JSON(["width":screenSize.width,"height":screenSize.height])) 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/server/models/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: XCUIElementType.button).allElementsBoundByIndex 41 | var defaultButton:XCUIElement? 42 | 43 | if alertElement?.elementType == XCUIElementType.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: XCUIElementType.button).allElementsBoundByIndex 61 | var defaultButton:XCUIElement? 62 | 63 | if alertElement?.elementType == XCUIElementType.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/XCTestWDUITests/server/models/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/XCTestWDUITests/server/models/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()?.replacingOccurrences(of: "\n", with: "") 31 | return rawString != nil ? HttpResponse.ok(.text(rawString!)) : HttpResponse.internalServerError 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/XCTestWDUITests/server/models/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 | 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 | enum OperationError:Error{ 37 | case Error 38 | } 39 | 40 | 41 | internal class XCTestWDSession { 42 | 43 | var identifier: String! 44 | var cache: XCTestWDElementCache = XCTestWDElementCache() 45 | private var _application: XCUIApplication! 46 | var application: XCUIApplication! { 47 | get { 48 | // Add protection for application resolve. only when application status active cam execute this 49 | if _application.accessibilityActivate() == true { 50 | try? resolve() 51 | } 52 | return _application 53 | 54 | } 55 | set { 56 | _application = newValue 57 | } 58 | } 59 | static func sessionWithApplication(_ application: XCUIApplication) -> XCTestWDSession { 60 | 61 | let session = XCTestWDSession() 62 | session.application = application 63 | session.identifier = UUID.init().uuidString 64 | 65 | return session 66 | } 67 | 68 | static func activeApplication() -> XCUIApplication? 69 | { 70 | //var activeApplicationElement:XCAccessibilityElement? 71 | 72 | //activeApplicationElement = (XCAXClient_iOS.sharedClient() as! XCAXClient_iOS).activeApplications().first 73 | //if activeApplicationElement == nil { 74 | // activeApplicationElement = (XCAXClient_iOS.sharedClient() as! XCAXClient_iOS).systemApplication() as? XCAccessibilityElement 75 | //} 76 | //let application = XCUIApplication.app(withPID: (activeApplicationElement?.processIdentifier)!) 77 | //_ = application?.query() 78 | 79 | //return application 80 | return XCTestWDApplication.activeApplication() 81 | } 82 | 83 | func resolve() throws { 84 | self._application.query() 85 | let pid = self._application.processID 86 | let app = XCTestWDSession.activeApplication() 87 | let currentprocessID = app?.processID 88 | if pid != currentprocessID{ 89 | throw OperationError.Error 90 | } 91 | 92 | self._application?.resolve() 93 | 94 | } 95 | } 96 | 97 | //MARK: Multi-Session Control 98 | internal class XCTestWDSessionManager { 99 | 100 | static let singleton = XCTestWDSessionManager() 101 | 102 | private var sessionMapping = [String: XCTestWDSession]() 103 | private var defaultSession:XCTestWDSession? 104 | 105 | func mountSession(_ session: XCTestWDSession) { 106 | sessionMapping[session.identifier] = session 107 | } 108 | 109 | func querySession(_ identifier:String) -> XCTestWDSession? { 110 | return sessionMapping[identifier] 111 | } 112 | 113 | func checkDefaultSessionthrow() throws -> XCTestWDSession { 114 | //if self.defaultSession == nil || self.defaultSession?.application.accessibilityActivate() == false { 115 | if self.defaultSession == nil || self.defaultSession?.application.state != XCUIApplication.State.runningForeground{ 116 | let application = XCTestWDSession.activeApplication() 117 | self.defaultSession = XCTestWDSession.sessionWithApplication(application!) 118 | } 119 | do{ 120 | try self.defaultSession?.resolve() 121 | }catch{ 122 | throw OperationError.Error 123 | } 124 | 125 | return self.defaultSession! 126 | } 127 | 128 | func checkDefaultSession() -> XCTestWDSession { 129 | // if self.defaultSession == nil || self.defaultSession?.application.accessibilityActivate() == false { 130 | if self.defaultSession == nil || self.defaultSession?.application.state != XCUIApplication.State.runningForeground{ 131 | sleep(2) 132 | let application = XCTestWDSession.activeApplication() 133 | self.defaultSession = XCTestWDSession.sessionWithApplication(application!) 134 | } 135 | 136 | try? self.defaultSession?.resolve() 137 | return self.defaultSession! 138 | } 139 | 140 | func queryAll() -> [String:XCTestWDSession] { 141 | return sessionMapping 142 | } 143 | 144 | func clearAll() { 145 | sessionMapping.removeAll() 146 | } 147 | 148 | func deleteSession(_ sessionId:String) { 149 | sessionMapping[sessionId]?.application.terminate() 150 | sessionMapping.removeValue(forKey: sessionId) 151 | NotificationCenter.default.post(name: NSNotification.Name(XCTestWDSessionShutDown), object: nil) 152 | } 153 | } 154 | 155 | //MARK: Extension 156 | extension HttpRequest { 157 | var session: XCTestWDSession? { 158 | get { 159 | if self.params["sessionId"] != nil && XCTestWDSessionManager.singleton.querySession(self.params["sessionId"]!) != nil { 160 | return XCTestWDSessionManager.singleton.querySession(self.params["sessionId"]!) 161 | } else if self.path.contains("/session/") { 162 | let components = self.path.components(separatedBy:"/") 163 | let index = components.index(of: "session")! 164 | if index >= components.count - 1 { 165 | return nil 166 | } 167 | return XCTestWDSessionManager.singleton.querySession(components[index + 1]) 168 | } else { 169 | return nil 170 | } 171 | } 172 | } 173 | 174 | var elementId: String? { 175 | get { 176 | if self.path.contains("/element/") { 177 | let components = self.path.components(separatedBy:"/") 178 | let index = components.index(of: "element")! 179 | if index < components.count - 1 { 180 | return components[index + 1] 181 | } 182 | } 183 | 184 | return nil 185 | } 186 | } 187 | 188 | var jsonBody:JSON { 189 | get { 190 | return try!JSON(data: NSData(bytes: &self.body, length: self.body.count) as Data) 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/server/models/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/XCTestWDUITests/server/models/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/XCTestWDUITests/server/models/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) -> XCUIElementType { 109 | return XCUIElementType(rawValue: stringElementMapping[typeName]!)! 110 | } 111 | 112 | func stringWithElementType(_ elementType:XCUIElementType) -> String { 113 | return elementStringMapping[elementType.rawValue]! 114 | } 115 | 116 | func shortStringWithElementType(_ elementType:XCUIElementType) -> String { 117 | return stringWithElementType(elementType).replacingOccurrences(of: "XCUIElementType", with: "") 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/XCTestWDUITests/server/models/extensions/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/XCTestWDUITests/server/models/utils/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/XCTestWDUITests/server/models/utils/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 | static func MD5(string: String) -> String { 28 | let messageData = string.data(using:.utf8)! 29 | var digestData = Data(count: Int(CC_MD5_DIGEST_LENGTH)) 30 | 31 | _ = digestData.withUnsafeMutableBytes {digestBytes in 32 | messageData.withUnsafeBytes {messageBytes in 33 | CC_MD5(messageBytes, CC_LONG(messageData.count), digestBytes) 34 | } 35 | } 36 | 37 | return digestData.base64EncodedString() 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /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\":\"CXiPhone\",\"platformName\":\"iOS\", \"bundleId\":\"com.egbank.EGBankP2B-Dev\",\"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 | ##Session: delete session by ID 57 | 58 | #TagHead "Delete Session By ID" 59 | # 60 | #curl -X DELETE $JSON_HEADER \ 61 | #$DEVICE_URL/wd/hub/session/$sessionID \ 62 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/libxml2/libxml2-fuzi.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import 5 | #import 6 | -------------------------------------------------------------------------------- /XCTestWD-master/XCTestWD/libxml2/module.modulemap: -------------------------------------------------------------------------------- 1 | module libxml2 [system] { 2 | link "xml2" 3 | umbrella header "libxml2-fuzi.h" 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /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: ${_.trunc(JSON.stringify(body), 200)}`); 56 | 57 | _.retry(() => { 58 | return new Promise((_resolve, _reject) => { 59 | request(reqOpts, (error, res, body) => { 60 | if (error) { 61 | logger.debug(`xctest client proxy error with: ${error}`); 62 | return _reject(error); 63 | } 64 | 65 | if (!body) { 66 | logger.debug(`xctest client proxy received no data.`); 67 | return _reject('No data received from XCTestWD.'); 68 | } 69 | 70 | if (typeof body !== 'object') { 71 | try { 72 | body = JSON.parse(body); 73 | } catch (e) { 74 | logger.debug(`Fail to parse body: ${e}`); 75 | } 76 | } 77 | 78 | if (body && body.sessionId) { 79 | this.sessionId = body.sessionId; 80 | body.sessionId = this.originSessionId; 81 | } 82 | 83 | logger.debug(`Got response with status ${res.statusCode}: ${_.trunc(JSON.stringify(body), 200)}`); 84 | _resolve(body); 85 | }); 86 | 87 | }); 88 | }, retryInterval, retryCount).then(resolve, reject); 89 | }); 90 | } 91 | } 92 | 93 | module.exports = XCProxy; 94 | -------------------------------------------------------------------------------- /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 detect = require('detect-port'); 7 | const EventEmitter = require('events'); 8 | const childProcess = require('child_process'); 9 | 10 | const _ = require('./helper'); 11 | const pkg = require('../package'); 12 | const XCProxy = require('./proxy'); 13 | const logger = require('./logger'); 14 | const XCTestWD = require('./xctestwd'); 15 | 16 | const TEST_URL = pkg.site; 17 | const projectPath = XCTestWD.projectPath; 18 | const SERVER_URL_REG = XCTestWD.SERVER_URL_REG; 19 | 20 | class XCTest extends EventEmitter { 21 | constructor(options) { 22 | super(); 23 | this.proxy = null; 24 | this.capabilities = null; 25 | this.sessionId = null; 26 | this.device = null; 27 | this.deviceLogProc = null; 28 | this.runnerProc = null; 29 | this.iproxyProc = null; 30 | Object.assign(this, { 31 | proxyHost: '127.0.0.1', 32 | proxyPort: 8001, 33 | urlBase: 'wd/hub' 34 | }, options || {}); 35 | this.init(); 36 | process.on('uncaughtException', (e) => { 37 | logger.debug('Uncaught Exception: ' + e); 38 | this.stop(); 39 | process.exit(1); 40 | }); 41 | process.on('exit', () => { 42 | this.stop(); 43 | }); 44 | } 45 | 46 | init() { 47 | this.checkProjectPath(); 48 | } 49 | 50 | checkProjectPath() { 51 | if (_.isExistedDir(projectPath)) { 52 | logger.debug(`project path: ${projectPath}`); 53 | } else { 54 | logger.error('project path not found'); 55 | } 56 | } 57 | 58 | configUrl(str) { 59 | const urlObj = url.parse(str); 60 | this.proxyHost = urlObj.hostname; 61 | this.proxyPort = urlObj.port; 62 | } 63 | 64 | initProxy() { 65 | this.proxy = new XCProxy({ 66 | proxyHost: this.proxyHost, 67 | proxyPort: this.proxyPort, 68 | urlBase: this.urlBase 69 | }); 70 | } 71 | 72 | *startSimLog() { 73 | this.startBootstrap(); 74 | return _.retry(() => { 75 | return new Promise((resolve, reject) => { 76 | let logDir = path.resolve(this.device.getLogDir(), 'system.log'); 77 | if (!_.isExistedFile(logDir)) { 78 | return reject(); 79 | } 80 | let args =`-f -n 0 ${logDir}`.split(' '); 81 | var proc = childProcess.spawn('tail', args, {}); 82 | this.deviceLogProc = proc; 83 | 84 | proc.stderr.setEncoding('utf8'); 85 | proc.stdout.setEncoding('utf8'); 86 | 87 | proc.stdout.on('data', data => { 88 | //logger.debug(data); 89 | let match = SERVER_URL_REG.exec(data); 90 | if (match) { 91 | const url = match[1]; 92 | if (url.startsWith('http://')) { 93 | this.configUrl(url); 94 | resolve(); 95 | } 96 | } 97 | }); 98 | 99 | proc.stderr.on('data', data => { 100 | logger.debug(data); 101 | }); 102 | 103 | proc.stdout.on('error', (err) => { 104 | logger.warn(`simulator log process error with ${err}`); 105 | }); 106 | 107 | proc.on('exit', (code, signal) => { 108 | logger.warn(`simulator log process exit with code: ${code}, signal: ${signal}`); 109 | reject(); 110 | }); 111 | }); 112 | }, 1000, Infinity); 113 | } 114 | 115 | *startDeviceLog() { 116 | var proc = childProcess.spawn(iOSUtils.devicelog.binPath, [this.device.deviceId], {}); 117 | this.deviceLogProc = proc; 118 | 119 | proc.stderr.setEncoding('utf8'); 120 | proc.stdout.setEncoding('utf8'); 121 | 122 | yield this.startIproxy(); 123 | 124 | return new Promise((resolve, reject) => { 125 | proc.stdout.on('data', data => { 126 | let match = SERVER_URL_REG.exec(data); 127 | if (match) { 128 | const url = match[1]; 129 | if (url.startsWith('http://')) { 130 | resolve(); 131 | } 132 | } 133 | // logger.debug(data); 134 | }); 135 | 136 | proc.stderr.on('data', data => { 137 | logger.debug(data); 138 | }); 139 | 140 | proc.stdout.on('error', (err) => { 141 | logger.warn(`devicelog error with ${err}`); 142 | }); 143 | 144 | proc.on('exit', (code, signal) => { 145 | logger.warn(`devicelog exit with code: ${code}, signal: ${signal}`); 146 | reject(); 147 | }); 148 | this.startBootstrap(); 149 | }); 150 | } 151 | 152 | startBootstrap() { 153 | 154 | logger.info(`XCTestWD version: ${XCTestWD.version}`); 155 | var args = `clean test -project ${XCTestWD.projectPath} -scheme ${XCTestWD.schemeName} -destination id=${this.device.deviceId} XCTESTWD_PORT=${this.proxyPort}`.split(' '); 156 | var env = _.merge({}, process.env, { 157 | XCTESTWD_PORT: this.proxyPort 158 | }); 159 | 160 | var proc = childProcess.spawn('xcodebuild', args, { 161 | env: env 162 | }); 163 | this.runnerProc = proc; 164 | proc.stderr.setEncoding('utf8'); 165 | proc.stdout.setEncoding('utf8'); 166 | 167 | proc.stdout.on('data', data => { 168 | //logger.debug(data); 169 | }); 170 | 171 | proc.stderr.on('data', data => { 172 | logger.debug(data); 173 | logger.debug(`please check project: ${projectPath}`); 174 | }); 175 | 176 | proc.stdout.on('error', (err) => { 177 | logger.warn(`xctest client error with ${err}`); 178 | logger.debug(`please check project: ${projectPath}`); 179 | }); 180 | 181 | proc.on('exit', (code, signal) => { 182 | this.stop(); 183 | logger.warn(`xctest client exit with code: ${code}, signal: ${signal}`); 184 | }); 185 | } 186 | 187 | *startIproxy() { 188 | let args = [this.proxyPort, this.proxyPort, this.device.deviceId]; 189 | 190 | const IOS_USBMUXD_IPROXY = 'iproxy'; 191 | const binPath = yield _.exec(`which ${IOS_USBMUXD_IPROXY}`); 192 | 193 | var proc = childProcess.spawn(binPath, args); 194 | 195 | this.iproxyProc = proc; 196 | proc.stderr.setEncoding('utf8'); 197 | proc.stdout.setEncoding('utf8'); 198 | 199 | proc.stdout.on('data', () => { 200 | }); 201 | 202 | proc.stderr.on('data', () => { 203 | //logger.debug(data); 204 | }); 205 | 206 | proc.stdout.on('error', (err) => { 207 | logger.warn(`${IOS_USBMUXD_IPROXY} error with ${err}`); 208 | }); 209 | 210 | proc.on('exit', (code, signal) => { 211 | logger.warn(`${IOS_USBMUXD_IPROXY} exit with code: ${code}, signal: ${signal}`); 212 | }); 213 | } 214 | 215 | *start(caps) { 216 | try { 217 | this.proxyPort = yield detect(this.proxyPort); 218 | 219 | logger.info(`${pkg.name} start with port: ${this.proxyPort}`); 220 | 221 | this.capabilities = caps; 222 | const xcodeVersion = yield iOSUtils.getXcodeVersion(); 223 | 224 | logger.debug(`xcode version: ${xcodeVersion}`); 225 | 226 | var deviceInfo = iOSUtils.getDeviceInfo(this.device.deviceId); 227 | 228 | if (deviceInfo.isRealIOS) { 229 | yield this.startDeviceLog(); 230 | } else { 231 | yield this.startSimLog(); 232 | } 233 | 234 | this.initProxy(); 235 | 236 | if (caps.desiredCapabilities.browserName === 'Safari') { 237 | var promise = this.proxy.send(`/${this.urlBase}/session`, 'POST', { 238 | desiredCapabilities: { 239 | bundleId: 'com.apple.mobilesafari' 240 | } 241 | }); 242 | return yield Promise.all([this.device.openURL(TEST_URL), promise]); 243 | } else { 244 | return yield this.proxy.send(`/${this.urlBase}/session`, 'POST', caps); 245 | } 246 | } catch (err) { 247 | logger.debug(`Fail to start xctest: ${err}`); 248 | this.stop(); 249 | throw err; 250 | } 251 | } 252 | 253 | stop() { 254 | if (this.deviceLogProc) { 255 | logger.debug(`killing deviceLogProc pid: ${this.deviceLogProc.pid}`); 256 | this.deviceLogProc.kill('SIGKILL'); 257 | this.deviceLogProc = null; 258 | } 259 | if (this.runnerProc) { 260 | logger.debug(`killing runnerProc pid: ${this.runnerProc.pid}`); 261 | this.runnerProc.kill('SIGKILL'); 262 | this.runnerProc = null; 263 | } 264 | 265 | if (this.iproxyProc) { 266 | logger.debug(`killing iproxyProc pid: ${this.iproxyProc.pid}`); 267 | this.iproxyProc.kill('SIGKILL'); 268 | this.iproxyProc = null; 269 | } 270 | } 271 | 272 | sendCommand(url, method, body) { 273 | return this.proxy.send(url, method, body); 274 | } 275 | } 276 | 277 | module.exports = XCTest; 278 | module.exports.XCTestWD = XCTestWD; 279 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /XCTestWD-master/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xctestwd", 3 | "version": "1.1.0", 4 | "description": "A 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 | "detect-port": "^1.1.3", 16 | "ios-utils": "~1.0.0", 17 | "macaca-utils": "~0.1.8", 18 | "request": "~2.69.0", 19 | "webdriver-dfn-error-code": "~1.0.1", 20 | "xcode": "^0.8.9", 21 | "xctestwd": "^1.0.0", 22 | "xlogger": "~1.0.0" 23 | }, 24 | "devDependencies": { 25 | "co-mocha": "*", 26 | "istanbul": "*", 27 | "jshint": "*", 28 | "macaca-utils": "^0.1.8", 29 | "mocha": "*", 30 | "pre-commit": "1.1.1", 31 | "should": "*" 32 | }, 33 | "scripts": { 34 | "test": "make test", 35 | "jshint": "make jshint", 36 | "install": "node ./scripts/install.js" 37 | }, 38 | "site": "https://macacajs.github.io", 39 | "license": "MIT" 40 | } 41 | -------------------------------------------------------------------------------- /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 hostname = require('os').hostname(); 7 | const childProcess = require('child_process'); 8 | 9 | const distDirName = path.join(__dirname, '..'); 10 | const DEVELOPMENT_TEAM = process.env.DEVELOPMENT_TEAM_ID || ''; 11 | 12 | try { 13 | const schemeName = 'XCTestWDUITests'; 14 | const projectPath = path.join(__dirname, '..', 'XCTestWD', 'XCTestWD.xcodeproj/project.pbxproj'); 15 | const myProj = xcode.project(projectPath); 16 | myProj.parseSync(); 17 | 18 | const update = function(schemeName, callback) { 19 | const myConfigKey = myProj.pbxTargetByName(schemeName).buildConfigurationList; 20 | const buildConfig = myProj.pbxXCConfigurationList()[myConfigKey]; 21 | const configArray = buildConfig.buildConfigurations; 22 | const keys = configArray.map(item => item.value); 23 | const pbxXCBuildConfigurationSection = myProj.pbxXCBuildConfigurationSection(); 24 | keys.forEach(key => { 25 | callback(pbxXCBuildConfigurationSection[key].buildSettings); 26 | }); 27 | }; 28 | 29 | update(schemeName, function(buildSettings) { 30 | const newBundleId = process.env.BUNDLE_ID || `XCTestWDRunner.XCTestWDRunner.${hostname}`; 31 | buildSettings.PRODUCT_BUNDLE_IDENTIFIER = newBundleId; 32 | if (DEVELOPMENT_TEAM) { 33 | buildSettings.DEVELOPMENT_TEAM = DEVELOPMENT_TEAM; 34 | } 35 | }); 36 | 37 | const projSect = myProj.getFirstProject(); 38 | const myRunnerTargetKey = myProj.findTargetKey(schemeName); 39 | const targetAttributes = projSect.firstProject.attributes.TargetAttributes; 40 | const runnerObj = targetAttributes[myRunnerTargetKey]; 41 | if (DEVELOPMENT_TEAM) { 42 | runnerObj.DevelopmentTeam = DEVELOPMENT_TEAM; 43 | } 44 | 45 | fs.writeFileSync(projectPath, myProj.writeSync()); 46 | 47 | if (DEVELOPMENT_TEAM) { 48 | console.log('Successfully updated Bundle Id and Team Id.'); 49 | } else { 50 | 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.`); 51 | } 52 | process.exit(0); 53 | } catch (e) { 54 | console.log('Failed to update Bundle Id and Team Id: ', e); 55 | } 56 | -------------------------------------------------------------------------------- /XCTestWD-master/test/mocha.opt: -------------------------------------------------------------------------------- 1 | --require should 2 | --reporter spec 3 | -------------------------------------------------------------------------------- /XCTestWD-master/test/xctest.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('should'); 4 | 5 | var XCTest = require('..'); 6 | 7 | describe('test', function() { 8 | it('should be ok', function() { 9 | XCTest.should.be.ok(); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /Xml2Html.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangzhao4444/AutoMonkey4IOS/e6aad30a3ffe5f88b0117c70b95895974fca5b04/Xml2Html.class -------------------------------------------------------------------------------- /Xml2Html.java: -------------------------------------------------------------------------------- 1 | import java.io.File; 2 | import java.io.PrintStream; 3 | import javax.xml.transform.Result; 4 | import javax.xml.transform.Source; 5 | import javax.xml.transform.Transformer; 6 | import javax.xml.transform.TransformerConfigurationException; 7 | import javax.xml.transform.TransformerException; 8 | import javax.xml.transform.TransformerFactory; 9 | import javax.xml.transform.stream.StreamResult; 10 | import javax.xml.transform.stream.StreamSource; 11 | 12 | public class Xml2Html 13 | { 14 | public static void Transform(String xmlFileName, String xslFileName, String htmlFileName) 15 | { 16 | TransformerFactory tFac; 17 | try 18 | { 19 | tFac = TransformerFactory.newInstance(); 20 | Source xslSource = new StreamSource(xslFileName); 21 | Transformer t = tFac.newTransformer(xslSource); 22 | File xmlFile = new File(xmlFileName); 23 | File htmlFile = new File(htmlFileName); 24 | Source source = new StreamSource(xmlFile); 25 | Result result = new StreamResult(htmlFile); 26 | System.out.println(result.toString()); 27 | t.transform(source, result); 28 | } catch (TransformerConfigurationException e) { 29 | e.printStackTrace(); 30 | } catch (TransformerException e) { 31 | e.printStackTrace(); 32 | } 33 | } 34 | 35 | public static void main(String[] args) 36 | { 37 | String xmlFileName = args[0] +"/summary.xml"; 38 | String xslFileName = args[0] +"/app.xsl"; 39 | String htmlFileName = args[0] +"/summary.html"; 40 | Transform(xmlFileName, xslFileName, htmlFileName); 41 | } 42 | } -------------------------------------------------------------------------------- /app.xsl: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 |

IOS MONKEY TEST SUMMARY

10 |

APPLICATION LEVEL

11 |
12 |

ABSTRACT

13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 26 | 27 | 28 | 29 | 30 | 33 | 36 | 37 | 38 | 39 | 40 |
21 | 22 | 24 | 25 |
31 | 32 | 34 | 35 |
41 |
42 |

RESULTS

43 | 44 | 45 | 46 | 47 | 48 | 51 | 54 | 55 | 56 | 57 | 58 | 61 | 64 | 65 | 66 | 67 | 68 | 71 | 74 | 75 | 76 | 77 | 78 | 81 | 84 | 85 | 86 | 87 | 88 | 91 | 94 | 95 | 96 | 97 | 98 |
49 | 50 | 52 | 53 |
59 | 60 | 62 | 63 |
69 | 70 | 72 | 73 |
79 | 80 | 82 | 83 |
89 | 90 | 92 | 93 |
99 |
100 |

DETAILS

101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 124 | 125 | 126 | 129 | 130 | 131 | 134 | 137 | 140 | 143 | 146 | 149 | 150 | 151 | 154 | 155 | 156 | 159 | 160 | 161 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 174 | 175 | 176 | 179 | 180 | 181 | 184 | 187 | 190 | 193 | 196 | 199 | 200 | 201 | 204 | 205 | 206 | 209 | 210 | 211 | 214 | 215 | 216 | 217 | 218 |
PackageVersionTest DurationCrashTotal Error1st ErrorMTBFResult
121 | 122 | 123 | 127 | 128 | 132 | 133 | 135 | 136 | 138 | 139 | 141 | 142 | 144 | 145 | 147 | 148 | 152 | 153 | 157 | 158 | 162 | 163 |
171 | 172 | 173 | 177 | 178 | 182 | 183 | 185 | 186 | 188 | 189 | 191 | 192 | 194 | 195 | 197 | 198 | 202 | 203 | 207 | 208 | 212 | 213 |
219 | 220 |

FAILED REASON

221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 235 | 238 | 248 | 249 | 250 |
PACKAGETOTAL FAILURESDETAIL INFO
232 | 233 | 234 | 236 | 237 | 239 |
    240 | 241 |
  • 242 | 243 | 244 |
  • 245 |
    246 |
247 |
251 | 252 | 253 |
254 | 255 |
256 | -------------------------------------------------------------------------------- /config/appinfo.txt: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "appName": "PandaTV", 4 | "bundleId": "com.PandaTV.Live-iPhone", 5 | "username": "18611111111", 6 | "password": "1111" 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /monitor_working.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Monitor ios monkey running 3 | #./monitor_working.sh ${DEVICE_NAME} ${DERIVED_DATA_DIR} ${PORT} ${XCTestWD_process} ${curl_cmd} 4 | 5 | DEVICE_NAME=$1 6 | DERIVED_DATA_DIR=$2 7 | PORT=$3 8 | XCTestWD_process=$4 9 | curl_cmd=$5 10 | XCODE_LOG="${DERIVED_DATA_DIR}/temp_xcode.txt" 11 | XCODE_BUILD_SUCESS="XCTestWDUITests-Runner.app: replacing existing signature" 12 | BUILD_NUM=1 13 | 14 | echo $curl_cmd 15 | 16 | while [[ true ]]; do 17 | isrun=`ps aux|grep "${XCTestWD_process}"|grep -v "grep"|grep -v "monitor_working"|awk '{print $2}'` 18 | echo "process: " $isrun 19 | if [ -z "${isrun}" ]; then 20 | echo "Restart XCTestWD" 21 | echo "Clear tmp log" 22 | cp ${XCODE_LOG} temp_xcode.txt 23 | rm -rf $DERIVED_DATA_DIR 24 | mkdir $DERIVED_DATA_DIR 25 | mv temp_xcode.txt ${XCODE_LOG} 26 | xcodebuild -project "./XCTestWD-master/XCTestWD/XCTestWD.xcodeproj" -scheme XCTestWDUITests -destination 'platform=iOS,name='${DEVICE_NAME}'' -derivedDataPath ${DERIVED_DATA_DIR} XCTESTWD_PORT=${PORT} test >> ${XCODE_LOG} & 27 | tail -f ${XCODE_LOG} & 28 | BUILD_NUM=$[$BUILD_NUM+1] 29 | for i in {1..10} 30 | do 31 | sleep 20 32 | isSucess=`grep -c "${XCODE_BUILD_SUCESS}" ${XCODE_LOG}` 33 | if [ ${isSucess} -eq ${BUILD_NUM} ];then 34 | echo "Xcode build sucessed!" 35 | sleep 10 36 | break 1 37 | fi 38 | if [ $i -eq 9 ]; then 39 | echo "Xcode build failed!" 40 | break 2 41 | fi 42 | echo "wait 20 seconds and checking agin!" 43 | done 44 | eval $curl_cmd 45 | else 46 | echo "XCTestWD working well" 47 | fi 48 | sleep 60 49 | done -------------------------------------------------------------------------------- /start_monkey.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | EVENT_TAG="XCTestMonkey" 4 | 5 | TagHead() { 6 | echo "=============== $1 ===============" 7 | } 8 | 9 | CURRENT_DIR=`dirname $0` 10 | INFO_FILE="${CURRENT_DIR}/config/appinfo.txt" 11 | 12 | if [ ! -f "${INFO_FILE}" ]; then 13 | echo "ERROR: must config info file first. file: ${INFO_FILE}" 14 | echo "Content as below:" 15 | echo -e "[\n\t{\n\t\t\"appName\": \"Crasher\",\n\t\t\"bundleId\": \"app.cyan.retriever.xisco\",\n\t\t\"username\": \"\",\n\t\t\"password\": \"\"\n\t}\n]" 16 | exit 1 17 | fi 18 | 19 | UDID= 20 | DEVICE_NAME= 21 | RUN_TIME=60m 22 | LOOP_NUM=2 23 | PORT=8001 24 | 25 | usage() 26 | { 27 | echo "" 28 | echo " AutoMonkey4I is used to perform IOS app monkey test automatically with" 29 | echo " run time, catch log, loop number" 30 | echo "" 31 | echo " Usage: `basename $0`" 32 | echo " `basename $0` -u -p -t -n " 33 | echo " Usage: `basename $0` with options. -u, -t and -n all of them are optional" 34 | echo "" 35 | echo " options:" 36 | echo " -u the ios device's udid" 37 | echo " -p the port forward" 38 | echo " -t the total event count or running time," 39 | echo " 20s means 20 seconds,20m means 20 minutes" 40 | echo " -n the number of loops each application needs to run," 41 | echo " default value is 2" 42 | echo " Sample: $0 -u e55f18280b4f924b7cecca5d180bec93e654f351 -t 20m -n 5" 43 | echo "" 44 | echo " Furthermore, save packages' infomation to config/appinfo.txt." 45 | echo " This script will test it one by one." 46 | } 47 | 48 | if [ $# -eq 0 ]; then 49 | echo "Test with default options" 50 | UDID=`idevice_id -l | awk 'NR==1{print $1}'` 51 | DEVICE_NAME=`ideviceinfo -u ${UDID} -k DeviceName` 52 | fi 53 | 54 | #option_string以冒号开头表示屏蔽脚本的系统提示错误,自己处理错误提示。 55 | #后面接合法的单字母选项,选项后若有冒号,则表示该选项必须接具体的参数 56 | while getopts :ut:n:p:h OPTION 57 | do 58 | case $OPTION in 59 | u) 60 | UDID=$OPTARG 61 | if [ -z "${UDID}" ]; then 62 | usage 63 | exit 1 64 | fi 65 | DEVICE_NAME=`ideviceinfo -u ${UDID} -k DeviceName` 66 | ;; 67 | p) 68 | PORT=$OPTARG 69 | ;; 70 | t) 71 | RUN_TIME=$OPTARG 72 | ;; 73 | n) 74 | LOOP_NUM=$OPTARG 75 | ;; 76 | h) 77 | usage 78 | ;; 79 | esac 80 | done 81 | 82 | if [ -z "${UDID}" ]; then 83 | echo "Test with default udid" 84 | UDID=`idevice_id -l | awk 'NR==1{print $1}'` 85 | DEVICE_NAME=`ideviceinfo -u ${UDID} -k DeviceName` 86 | fi 87 | 88 | valid_udid=`idevice_id -l |grep ${UDID}` 89 | full_udid=`idevice_id -l |grep -o ${UDID}` 90 | 91 | if [ -z "${valid_udid}" ]; then 92 | echo "ERROR: You must input right udid with -u option" 93 | usage 94 | exit 1 95 | fi 96 | 97 | if [ "${valid_udid}" != "${full_udid}" ]; then 98 | echo "ERROR: You must input the full udid string with -u option" 99 | usage 100 | exit 1 101 | fi 102 | 103 | if [ -z `echo ${RUN_TIME} | grep -e '^[0-9]*[sSmM]$'` ]; then 104 | echo " ERROR: invalid monkey running time ${RUN_TIME}!\n" 105 | usage 106 | exit 1 107 | fi 108 | 109 | if [ -z `echo $PORT | grep -e '^[0-9]*$'` ]; then 110 | echo " ERROR: invalid port ${PORT}!\n" 111 | usage 112 | exit 1 113 | fi 114 | 115 | if [ -z `echo ${LOOP_NUM} | grep -e '^[0-9]*$'` ]; then 116 | echo " ERROR: invalid loop number ${LOOP_NUM}!\n" 117 | usage 118 | exit 1 119 | fi 120 | 121 | # convert running time to second. 122 | if [ `echo ${RUN_TIME} | grep -e '^[0-9]*[sS]$'` ]; then 123 | RUN_TIME_IN_SECOND=`echo ${RUN_TIME} | sed -e "s/[sS]$//"` 124 | elif [ `echo ${RUN_TIME} | grep -e '^[0-9]*[mM]$'` ]; then 125 | RUN_TIME_IN_SECOND=`echo ${RUN_TIME} | sed -e "s/[mM]$//"` 126 | RUN_TIME_IN_SECOND=$((RUN_TIME_IN_SECOND*60)) 127 | fi 128 | 129 | echo "RUN_TIME_IN_SECOND=${RUN_TIME_IN_SECOND} LOOP_NUM=${LOOP_NUM} DEVICE_NAME=${DEVICE_NAME} UDID=${UDID}" 130 | 131 | # get apps num 132 | jsons=`cat $INFO_FILE | jq .` 133 | apps_num=`echo $jsons|jq length` 134 | echo $apps_num 135 | 136 | PROJECT_FOLDER="${CURRENT_DIR}/XCTestWD-master/XCTestWD" 137 | DERIVED_DATA_DIR="${CURRENT_DIR}/tmp_${UDID}" 138 | OUTPUT="${CURRENT_DIR}/output" 139 | RESULT_FILE="result.txt" 140 | XCODE_LOG="${DERIVED_DATA_DIR}/temp_xcode.txt" 141 | XCODE_BUILD_SUCESS="XCTestWDUITests-Runner.app: replacing existing signature" 142 | 143 | if [ ! -d "${OUTPUT}" ]; then 144 | mkdir -p ${OUTPUT} 145 | fi 146 | 147 | time_tamp=`date +%Y%m%d%H%M%S` 148 | log_dir="${DEVICE_NAME}_app_${time_tamp}" 149 | log_dir="${OUTPUT}/${log_dir}" 150 | echo $log_dir 151 | if [ ! -d "${log_dir}" ]; then 152 | mkdir -p ${log_dir} 153 | fi 154 | 155 | INDEX=0 156 | 157 | TagHead "Clear Process" 158 | iporxy_process="iproxy $PORT $PORT" 159 | XCTestWD_process="XCTESTWD_PORT=$PORT" 160 | ps aux|grep "${iporxy_process}"|grep -v "grep"|awk '{print $2}'|xargs kill -9 161 | echo "Clear Iproxy process" 162 | ps aux|grep "${XCTestWD_process}"|grep -v "grep"|awk '{print $2}'|xargs kill -9 163 | echo "Clear XCTestWD Process" 164 | 165 | TagHead "Clear phone old crash logs" 166 | mkdir -p ./oldlogs 167 | idevicecrashreport -u ${UDID} -e ./oldlogs 168 | rm -rf ./oldlogs 169 | 170 | TagHead "Iproxy Setup" 171 | iproxy $PORT $PORT $UDID >/dev/null & 172 | echo $PORT, $UDID 173 | sleep 20 174 | 175 | while [ $INDEX -lt $apps_num ] 176 | do 177 | appjson=`echo $jsons |jq ".[${INDEX}]"` 178 | 179 | appName=`echo $appjson | jq .appName | sed 's/"//g'` 180 | bundleId=`echo $appjson | jq .bundleId | sed 's/"//g'` 181 | username=`echo $appjson | jq .username | sed 's/"//g'` 182 | password=`echo $appjson | jq .password | sed 's/"//g'` 183 | 184 | package_dir="${log_dir}/${bundleId}" 185 | if [ ! -d "${package_dir}" ]; then 186 | mkdir -p ${package_dir} 187 | fi 188 | 189 | #找不到指定app,跳出继续执行下一个app 190 | CAN_RUN=`ideviceinstaller -u ${UDID} -l|awk '{print $1}'|grep "${bundleId}"` 191 | if [ -z "${CAN_RUN}" ]; then 192 | echo "\t!!! Error, no such app: ${bundleId}." 193 | echo "\t!!! Monkey aborted, will test next app." 194 | echo "N/A" > ${package_dir}/${RESULT_FILE} 195 | INDEX=$(($INDEX + 1)) 196 | continue 197 | elif [ "${CAN_RUN}" != "${bundleId}" ]; then 198 | echo "\t!!! Error, no such app: ${bundleId}." 199 | echo "\t!!! Monkey aborted, will test next app." 200 | echo "N/A" > ${package_dir}/${RESULT_FILE} 201 | INDEX=$(($INDEX + 1)) 202 | continue 203 | fi 204 | 205 | appVersion=`ideviceinstaller -u ${UDID} -l|grep "${bundleId}"|awk '{print $4}'` 206 | 207 | LOOP=1 208 | 209 | #add start test time 210 | startTime=`date +%s` 211 | echo $startTime 212 | startTime=$(($startTime+50)) 213 | echo $startTime 214 | echo "Time:${startTime}" > ${package_dir}/${RESULT_FILE} 215 | 216 | while [ $LOOP -le $LOOP_NUM ] 217 | do 218 | TagHead "Start the ${appName} app test, test loop $LOOP" 219 | echo "Kill display log Process" 220 | ps aux|grep "tail -f ${XCODE_LOG}"|grep -v "grep"|awk '{print $2}'|xargs kill -9 221 | #if XCTestWD terminaled , restart. 222 | TagHead "Clear tmp log" 223 | rm -rf $DERIVED_DATA_DIR 224 | mkdir $DERIVED_DATA_DIR 225 | TagHead "Start XCTestWD" 226 | xcodebuild -project "${PROJECT_FOLDER}/XCTestWD.xcodeproj" -scheme XCTestWDUITests -destination 'platform=iOS,name='${DEVICE_NAME}'' -derivedDataPath ${DERIVED_DATA_DIR} XCTESTWD_PORT=${PORT} test > ${XCODE_LOG} & 227 | tail -f ${XCODE_LOG} & 228 | for i in {1..10} 229 | do 230 | sleep 20 231 | isSucess=`grep "${XCODE_BUILD_SUCESS}" ${XCODE_LOG}` 232 | if [ -n "${isSucess}" ];then 233 | echo "Xcode build sucessed!" 234 | sleep 10 235 | break 1 236 | fi 237 | if [ $i -eq 9 ]; then 238 | echo "Xcode build failed!" 239 | break 2 240 | fi 241 | echo "wait 20 seconds and checking agin!" 242 | done 243 | 244 | TagHead "Start Monkey" 245 | if [ -z "${username}" -a -z "${password}" ]; then 246 | curl_cmd='curl -X POST -H "Content-Type:application/json" -d "{\"desiredCapabilities\":{\"deviceName\":\"'${DEVICE_NAME}'\",\"platformName\":\"iOS\", \"bundleId\":\"'${bundleId}'\",\"autoAcceptAlerts\":\"false\"}}" http://127.0.0.1:'${PORT}'/wd/hub/monkey &' 247 | else 248 | curl_cmd='curl -X POST -H "Content-Type:application/json" -d "{\"desiredCapabilities\":{\"deviceName\":\"'${DEVICE_NAME}'\",\"platformName\":\"iOS\", \"bundleId\":\"'${bundleId}'\",\"autoAcceptAlerts\":\"false\",\"username\":\"'${username}'\",\"password\":\"'${password}'\"}}" http://127.0.0.1:'${PORT}'/wd/hub/monkey &' 249 | fi 250 | 251 | echo $curl_cmd 252 | eval $curl_cmd 253 | 254 | #catch device sys log 255 | echo "Start catch system log" 256 | idevicesyslog -u ${UDID} -g ${appName} > "${package_dir}/syslog_${LOOP}.txt" & 257 | 258 | #monitor if XCTestWD working 259 | echo "Start monitor process to avoid interrupted" 260 | monitor_cmd='./monitor_working.sh '${DEVICE_NAME}' '${DERIVED_DATA_DIR}' '${PORT}' '${XCTestWD_process}' '\'${curl_cmd}\''' 261 | echo $monitor_cmd 262 | eval $monitor_cmd & 263 | 264 | sleep $(($RUN_TIME_IN_SECOND)) 265 | 266 | TagHead "Stop this test loop" 267 | echo "Fetch crash logs and event logs" 268 | idevicecrashreport -u ${UDID} -e -g ${appName} "${package_dir}/" 269 | grep ${EVENT_TAG} ${XCODE_LOG} > ${package_dir}/event_log_${LOOP}.txt 270 | 271 | echo "Stop system log and event log" 272 | ps aux|grep "idevicesyslog -u ${UDID}"|grep -v "grep"|awk '{print $2}'|xargs kill -9 273 | echo "Kill monitor process" 274 | ps aux|grep "./monitor_working.sh ${DEVICE_NAME} ${DERIVED_DATA_DIR} ${PORT}"|grep -v "grep"|awk '{print $2}'|xargs kill -9 275 | echo "Stop XCTestWD Process" 276 | ps aux|grep "${XCTestWD_process}"|grep -v "grep"|awk '{print $2}'|xargs kill -9 277 | echo "Kill display log Process" 278 | ps aux|grep "tail -f ${XCODE_LOG}"|grep -v "grep"|awk '{print $2}'|xargs kill -9 279 | 280 | TagHead "Clear tmp log" 281 | rm -rf $DERIVED_DATA_DIR 282 | 283 | LOOP=$(($LOOP+1)) 284 | done 285 | 286 | Crash_Num=`ls ${package_dir} | grep ".ips$" | wc -l |awk '{print $1}'` 287 | echo "Version:${appVersion}" >> ${package_dir}/${RESULT_FILE} 288 | echo "Crash:${Crash_Num}" >> ${package_dir}/${RESULT_FILE} 289 | echo "`ls ${package_dir}|grep ".ips"`" >>${package_dir}/${RESULT_FILE} 290 | INDEX=$(($INDEX + 1)) 291 | done 292 | 293 | TagHead "Stop test, stop process" 294 | ps aux|grep "${iporxy_process}"|grep -v "grep"|awk '{print $2}'|xargs kill -9 295 | echo "Stop Iproxy process" 296 | 297 | # summary test result 298 | TagHead "Generate Test Report" 299 | ./summary.sh ${RUN_TIME} ${LOOP_NUM} ${UDID} ${log_dir} 120m 300 | java Xml2Html ${log_dir} 301 | 302 | 303 | 304 | 305 | -------------------------------------------------------------------------------- /summary.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Auto generate summary xml file. 3 | 4 | DATE=`date +%Y/%m/%d` 5 | TEST_TIME=$1 6 | LOOP_NUM=$2 7 | UDID=$3 8 | LOG_DIR=$4 9 | ROOT_PATH=`pwd` 10 | 11 | products_dict='{"iPhone6,1":"iPhone 5S","iPhone6,2":"iPhone 5S","iPhone7,1":"iPhone 6 Plus","iPhone7,2":"iPhone 6","iPhone8,1":"iPhone 6S","iPhone8,2":"iPhone 6S Plus","iPhone9,1":"iPhone7","iPhone9,2":"iPhone7 Plus"}' 12 | 13 | if [ -z $TEST_TIME ] || [ -z $LOOP_NUM ] || [ -z $UDID ] || [ -z $LOG_DIR ]; then 14 | echo "Usage: ./summary.sh [run_time] [loop_num] [udid] [log_dir] [Goal of MTBF]" 15 | exit 16 | fi 17 | 18 | 19 | # $4 should be the goal of MTTF for current M-gate. So if $4 is defined mean this summary is filed for M-gate review. If not, this sheet will be used for general monkey test report. 20 | if [ -z $5 ];then 21 | TAGGET_MTTF="120m" 22 | else 23 | TAGGET_MTTF=$5 24 | fi 25 | 26 | PRODUCT=`ideviceinfo -u ${UDID} -k ProductType | sed 's/\r//g'` 27 | DEVICE=`ideviceinfo -u ${UDID} -k DeviceName | sed 's/\r//g'` 28 | MODEL1=`ideviceinfo -u ${UDID} -k ModelNumber | sed 's/\r//g'` 29 | REGION=`ideviceinfo -u ${UDID} -k RegionInfo | sed 's/\r//g'` 30 | MODEL="${MODEL1}${REGION}" 31 | VERSION=`ideviceinfo -u ${UDID} -k ProductVersion | sed 's/\r//g'` 32 | Value=$(echo $products_dict | jq 'has('\"${PRODUCT}\"')') 33 | 34 | if [ "${Value}" = "true" ]; then 35 | echo "contains the product! ${PRODUCT}" 36 | PRODUCT=`echo $products_dict| jq ''.\"${PRODUCT}\"''| sed 's/"//g'` 37 | echo $PRODUCT 38 | fi 39 | 40 | sheet_type=app.xsl 41 | 42 | echo -e "\n---------------------------------------------------------------------------" 43 | echo "Summarizing: $sheet_type - $LOG_DIR" 44 | 45 | cat > ${LOG_DIR}/summary.xml < 47 | 48 | 49 | 50 | 51 | Product 52 | $PRODUCT 53 | 54 | 55 | Model 56 | $MODEL 57 | 58 | 59 | 60 | DeviceName 61 | $DEVICE 62 | 63 | 64 | Version 65 | $VERSION 66 | 67 | 68 | Udid 69 | $UDID 70 | 71 | 72 | Date 73 | $DATE 74 | 75 | 76 | Goal of MTBF 77 | $TAGGET_MTTF 78 | 79 | HELP 80 | 81 | if [ $sheet_type = "app.xsl" ]; then 82 | cd $LOG_DIR 83 | total_count=0 84 | pass_count=0 85 | fail_count=0 86 | na_count=0 87 | for package in * 88 | do 89 | ACTUAL_TEST_TIME=$TEST_TIME 90 | if [ -f ./${package}/result.txt ]; then 91 | total_count=$(($total_count + 1)) 92 | echo -e "\t" >> ./summary.xml 93 | echo -e "\t\t${package}" >> ./summary.xml 94 | if [ `cat ./${package}/result.txt | awk '{print;exit}' | awk '{print $1}'` = "N/A" ]; then 95 | echo -e "\t\t${version}" >> ./summary.xml 96 | echo -e "\t\tN/A" >> ./summary.xml 97 | echo -e "\t\tN/A" >> ./summary.xml 98 | echo -e "\t\tN/A " >> ./summary.xml 99 | echo -e "\t\tN/A" >> ./summary.xml 100 | echo -e "\t\tN/A" >> ./summary.xml 101 | echo -e "\t" >> ./summary.xml 102 | na_count=$(($na_count + 1)) 103 | else 104 | version=`cat ./${package}/result.txt|grep Version|awk -F ":" '{print $2}'` 105 | echo -e "\t\t${version}" >> ./summary.xml 106 | fc=`cat ./${package}/result.txt|grep Crash|awk -F ":" '{print $2}'` 107 | 108 | #echo "$fc", maybe others in future 109 | total_failure=$(($fc)) 110 | 111 | # convert test time to minute for calculate MTTF 112 | if [ `echo ${ACTUAL_TEST_TIME} | grep -e '^[0-9]*[mM]$'` ]; then 113 | target_min=`echo ${ACTUAL_TEST_TIME} | sed -e "s/[mM]$//"` 114 | elif [ `echo ${ACTUAL_TEST_TIME} | grep -e '^[0-9]*[sS]$'` ]; then 115 | target_min=`echo ${ACTUAL_TEST_TIME} | sed -e "s/[sS]$//"` 116 | target_min=$(($target_min / 60)) 117 | fi 118 | 119 | target_min="$(($target_min * $LOOP_NUM))" 120 | echo $target_min 121 | 122 | TAGGET_MTTF=`echo $TAGGET_MTTF | sed -e "s/[mM]$//"` 123 | 124 | #no issue found: 125 | if [ $total_failure -eq 0 ]; then 126 | mttf="----" 127 | firsterr="----" 128 | mg="pass" 129 | pass_count=$(($pass_count + 1)) 130 | echo "---------------------------------------------------------------------------" 131 | echo "Passed: $package " 132 | # found one or more issue: 133 | else 134 | echo $total_failure, $target_min 135 | mttf_a=$(($target_min / $total_failure)) 136 | mttf_b=$(($target_min % $total_failure * 10 / $total_failure)) 137 | mttf_c=$(($target_min % $total_failure * 10 % $total_failure * 10 / $total_failure)) 138 | mttf="${mttf_a}.${mttf_b}${mttf_c}" 139 | #echo $mttf 140 | 141 | # count 1st error by finding the 1st real failure. 142 | start_time=`cat ./${package}/result.txt|grep Time|awk -F ":" '{print $2}'` 143 | echo ${start_time} 144 | firstfile=`ls ./${package} | sort -k9 |awk 'NR==1{print $1}'` 145 | firsterr_time=`echo ${firstfile} | sed 's/.ips//g' | awk -F "-" NR==1'{print $2$3$4$5}'` 146 | firsterr_second=`date -j -f %Y%m%d%H%M%S ${firsterr_time} +%s` 147 | errat=$(($firsterr_second-$start_time)) 148 | errat_MINUTE=$(($errat / 60)) 149 | errat_SECOND=$(($errat % 60)) 150 | firsterr="${errat_MINUTE}m${errat_SECOND}s" 151 | 152 | echo "---------------------------------------------------------------------------" 153 | echo "$package | First error: $firsterr| Total Failures: $total_failure" 154 | 155 | # compare with goal to pass or fail it. 156 | if [ $mttf_a -gt $TAGGET_MTTF ];then 157 | mg="pass" 158 | pass_count=$(($pass_count + 1)) 159 | elif [ $mttf_a -lt $TAGGET_MTTF ];then 160 | mg="fail" 161 | fail_count=$(($fail_count + 1)) 162 | elif [ $mttf_a -eq $TAGGET_MTTF ];then 163 | if [ $mttf_b != 0 ] || [ $mttf_c != 0 ];then 164 | mg="pass" 165 | pass_count=$(($pass_count + 1)) 166 | else 167 | mg="fail" 168 | fail_count=$(($fail_count + 1)) 169 | fi 170 | fi 171 | fi 172 | 173 | echo -e "\t\t${target_min}m" >> ./summary.xml 174 | echo -e "\t\t$fc" >> ./summary.xml 175 | echo -e "\t\t$firsterr" >> ./summary.xml 176 | echo -e "\t\t$total_failure " >> ./summary.xml 177 | echo -e "\t\t${mttf}m" >> ./summary.xml 178 | echo -e "\t\t$mg" >> ./summary.xml 179 | echo -e "\t" >> ./summary.xml 180 | 181 | # add the info of each failure 182 | if [ $total_failure -ne 0 ];then 183 | echo -e "\t" >> ./summary.xml 184 | echo -e "\t\t$package" >> ./summary.xml 185 | echo -e "\t\t$total_failure" >> ./summary.xml 186 | lerrs=`cat ./${package}/result.txt| grep "[-0-9]*.ips$"` 187 | i=0 188 | while (( i<$fc )) 189 | do 190 | i=$(($i+1)) 191 | error=`echo $lerrs | awk '{print $'$i'}'` 192 | echo "\t\t${error} " >> ./summary.xml 193 | done 194 | echo -e "\t" >> ./summary.xml 195 | fi 196 | fi 197 | fi 198 | done 199 | 200 | # calculate pass rate. 201 | pr_a=$(($pass_count * 100 / $total_count)) 202 | pr_b=$(($pass_count * 100 % $total_count * 10 / $total_count)) 203 | pr_c=$(($pass_count * 100 % $total_count * 10 % $total_count * 10 / $total_count)) 204 | pr="${pr_a}.${pr_b}${pr_c}" 205 | 206 | echo -e "\t" >> ./summary.xml 207 | echo -e "\t\tTOTAL" >> ./summary.xml 208 | echo -e "\t\t$total_count" >> ./summary.xml 209 | echo -e "\t" >> ./summary.xml 210 | echo -e "\t" >> ./summary.xml 211 | echo -e "\t\tPASS" >> ./summary.xml 212 | echo -e "\t\t$pass_count" >> ./summary.xml 213 | echo -e "\t" >> ./summary.xml 214 | echo -e "\t" >> ./summary.xml 215 | echo -e "\t\tFAIL" >> ./summary.xml 216 | echo -e "\t\t$fail_count" >> ./summary.xml 217 | echo -e "\t" >> ./summary.xml 218 | echo -e "\t" >> ./summary.xml 219 | echo -e "\t\tN/A" >> ./summary.xml 220 | echo -e "\t\t$na_count" >> ./summary.xml 221 | echo -e "\t" >> ./summary.xml 222 | echo -e "\t" >> ./summary.xml 223 | echo -e "\t\tPASS RATE" >> ./summary.xml 224 | echo -e "\t\t${pr}%" >> ./summary.xml 225 | echo -e "\t" >> ./summary.xml 226 | echo "" >> ./summary.xml 227 | cp ${ROOT_PATH}/${sheet_type} ./ 228 | fi 229 | 230 | --------------------------------------------------------------------------------