diff --git a/assets/ios-sim-locale b/assets/ios-sim-locale new file mode 100755 index 000000000..525b22bad Binary files /dev/null and b/assets/ios-sim-locale differ diff --git a/docs/caps.md b/docs/caps.md index 16c1609f3..fabaf43d3 100644 --- a/docs/caps.md +++ b/docs/caps.md @@ -28,4 +28,7 @@ Appium server capabilities |Capability|Description|Values| |----|-----------|-------| +|`calendarFormat`| Calendar format to set for the iOS Simulator|e.g. `gregorian`| +|`language`| Language to set for the iOS Simulator|e.g. `fr`| |`launchTimeout`| Amount of time in ms to wait for instruments before assuming it hung and failing the session|e.g. `20000`| +|`locale`| Locale to set for the iOS Simulator|e.g. `fr_CA`| diff --git a/docs/server-args.md b/docs/server-args.md index 161598c2d..d52471bdf 100644 --- a/docs/server-args.md +++ b/docs/server-args.md @@ -33,6 +33,9 @@ All flags are optional, but some are required in conjunction with certain others |`--safari`|false|(IOS-Only) Use the safari app|| |`--force-iphone`|false|(IOS-only) Use the iPhone Simulator no matter what the app wants|| |`--force-ipad`|false|(IOS-only) Use the iPad Simulator no matter what the app wants|| +|`--calendar-format`|null|(IOS-simulator-only) set the ios simulator calendar format (gregorian|buddhist|japanese)|`--calendar-format gregorian`| +|`--language`|null|(IOS-simulator-only) set the ios simulator language|`--language fr`| +|`--locale`|null|(IOS-simulator-only) set the ios simulator locale|`--locale fr_CA`| |`--orientation`|null|(IOS-only) use LANDSCAPE or PORTRAIT to initialize all requests to this orientation|`--orientation LANDSCAPE`| |`--tracetemplate`|null|(IOS-only) .tracetemplate file to use with Instruments|`--tracetemplate /Users/me/Automation.tracetemplate`| |`--nodeconfig`|null|Configuration JSON file to register appium with selenium grid|`--nodeconfig /abs/path/to/nodeconfig.json`| diff --git a/lib/appium.js b/lib/appium.js index aa7af9414..01cea4800 100644 --- a/lib/appium.js +++ b/lib/appium.js @@ -527,6 +527,9 @@ Appium.prototype.initDevice = function() { , launchTimeout: this.desiredCapabilities.launchTimeout , version: this.desiredCapabilities.version , deviceType: this.iosDeviceType + , language: this.desiredCapabilities.language || this.args.language + , locale: this.desiredCapabilities.locale || this.args.locale + , calendarFormat: this.desiredCapabilities.calendarFormat || this.args.calendarFormat , startingOrientation: this.desiredCapabilities.deviceOrientation || this.args.orientation , robotPort: this.args.robotPort , robotAddress: this.args.robotAddress diff --git a/lib/devices/ios/ios.js b/lib/devices/ios/ios.js index 26f7bb202..02d4bc1e9 100644 --- a/lib/devices/ios/ios.js +++ b/lib/devices/ios/ios.js @@ -39,6 +39,9 @@ var IOS = function(args) { this.automationTraceTemplatePath = args.automationTraceTemplatePath; this.removeTraceDir = args.removeTraceDir; this.deviceType = args.deviceType; + this.language = args.language; + this.locale = args.locale; + this.calendarFormat = args.calendarFormat; this.logs = null; this.startingOrientation = args.startingOrientation || "PORTRAIT"; this.curOrientation = this.startingOrientation; @@ -173,6 +176,7 @@ IOS.prototype.start = function(cb, onDie) { this.detectUdid.bind(this), this.parseLocalizableStrings.bind(this), this.setDeviceType.bind(this), + this.setLocale.bind(this), this.startLogCapture.bind(this), this.installToRealDevice.bind(this), this.startInstruments.bind(this), @@ -327,6 +331,30 @@ IOS.prototype.setXcodeVersion = function(cb) { }.bind(this)); }; +IOS.prototype.setLocale = function(cb) { + var msg; + if (this.language || this.locale || this.calendarFormat) { + helpers.getiOSSDKVersion(function(err, sdkVersion) { + if (err) return cb(err); + if (sdkVersion !== null) { + var iosSimLocalePath = path.resolve(__dirname, "../../../build/ios-sim-locale"); + var cmd = iosSimLocalePath + ' -sdk ' + sdkVersion; + logger.info("Changing the iOS Simulator language"); + cmd = (this.language) ? cmd + ' -language ' + this.language : cmd; + cmd = (this.locale) ? cmd + ' -locale ' + this.locale : cmd; + cmd = (this.calendarFormat) ? cmd + ' -calendar ' + this.calendarFormat : cmd; + exec(cmd, { maxBuffer: 524288 }, cb); + } else { + msg = "Could not set locale information because the iOS SDK version could not be detected."; + logger.error(msg); + cb(new Error(msg)); + } + }.bind(this)); + } else { + cb(); + } +}; + IOS.prototype.detectTraceTemplate = function(cb) { var msg; if (!this.automationTraceTemplatePath) { diff --git a/lib/helpers.js b/lib/helpers.js index a878d2175..d636302cb 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -399,3 +399,41 @@ exports.getXcodeVersion = function(cb) { } }); }; + +exports.getiOSSDKVersion = function(cb) { + var msg; + exports.getXcodeFolder(function(err, xcodeFolderPath) { + if (err) return cb(err); + if (xcodeFolderPath !== null) { + var sdkFolderPath = path.resolve(xcodeFolderPath, + "Platforms/iPhoneSimulator.platform/Developer/SDKs"); + if (fs.existsSync(sdkFolderPath)) { + var sdkFolders = fs.readdirSync(sdkFolderPath).sort().reverse(); + if (sdkFolders.length > 0) { + var match = sdkFolders[0].match(/\d\.\d/); + if (match) { + var sdkVersion = match[0]; + cb(null, sdkVersion); + } else { + msg = "Could not determine sdk version number from sdk folder " + sdkFolders[0]; + logger.error(msg); + cb(new Error(msg), null); + } + } else { + msg = "Did not find any SDKs at " + sdkFolderPath; + logger.error(msg); + cb(new Error(msg), null); + } + } else { + msg = "Could not find sdk folder path at " + sdkFolderPath; + logger.error(msg); + cb(new Error(msg), null); + } + } else { + msg = "Could not find the sdk folder path because XCode " + + "could not be found. Try setting the path with xcode-select."; + logger.error(msg); + cb(new Error(msg), null); + } + }.bind(this)); +}; \ No newline at end of file diff --git a/lib/server/parser.js b/lib/server/parser.js index c9711d423..95f30ec4a 100644 --- a/lib/server/parser.js +++ b/lib/server/parser.js @@ -217,6 +217,30 @@ var args = [ , nargs: 0 }], + [['--language'] , { + defaultValue: null + , dest: 'language' + , required: false + , example: "en" + , help: '(IOS-only) language for the iOS simulator' + }], + + [['--locale'] , { + defaultValue: null + , dest: 'locale' + , required: false + , example: "en_US" + , help: '(IOS-only) locale for the iOS simulator' + }], + + [['--calendar-format'] , { + defaultValue: null + , dest: 'calendarFormat' + , required: false + , example: "gregorian" + , help: '(IOS-only) calendar format for the iOS simulator' + }], + [['--orientation'], { defaultValue: null , required: false @@ -300,7 +324,7 @@ var args = [ , dest: 'keyPassword' , required: false , help: '(Android-only) Key password' - }], + }] ]; // Setup all the command line argument parsing diff --git a/reset.sh b/reset.sh index 350822dc9..658f0c906 100755 --- a/reset.sh +++ b/reset.sh @@ -116,6 +116,9 @@ reset_ios() { run_cmd pushd submodules/udidetect run_cmd make run_cmd popd + echo "* Installing ios-sim-locale" + run_cmd rm -f build/ios-sim-locale + run_cmd cp assets/ios-sim-locale build/ios-sim-locale echo "* Moving udidetect into build/udidetect" run_cmd rm -rf build/udidetect run_cmd mkdir build/udidetect