Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add appLocale capability #280

Merged
merged 3 commits into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ appium:skipAppKill | Whether to skip the termination of the application under te
appium:prerun | An object containing either `script` or `command` key. The value of each key must be a valid AppleScript script or command to be executed prior to the Mac2Driver session startup. See [AppleScript commands execution](#applescript-commands-execution) for more details. Example: `{command: 'do shell script "echo hello"'}`
appium:postrun | An object containing either `script` or `command` key. The value of each key must be a valid AppleScript script or command to be executed after Mac2Driver session is stopped. See [AppleScript commands execution](#applescript-commands-execution) for more details.
appium:noReset | Whether to restart the app whose bundle identifier was passed to capabilities as `bundleId` value if it was already running on the session startup (`false`, the default value) or just pick it up without changing the app state (`true`). Note that neither of `arguments` or `environment` capabilities will take effect if the app did not restart.
appium:appPath | The path to the application to automate, for example `/Applications/MyAppName.app`. This is an optional capability, but it requires `bundleId` to be present. If `bundleId` is empty, `appPath` will be ignored. If the path is invalid or application is damaged/incomplete then an error will be thrown on session startup. This capability could be usefull when you have multiple builds of the same application with the same bundleId on your machine (for example one production build in /Applications/ and several dev builds). If you provide bundleId only, the operating system could open any of these builds. By providing `appPath` you have a guarantee that the specified .app will be launched, rather than a random one.
appium:appPath | The path to the application to automate, for example `/Applications/MyAppName.app`. This is an optional capability, but it requires `bundleId` to be present. If `bundleId` is empty, `appPath` will be ignored. If the path is invalid or application is damaged/incomplete then an error will be thrown on session startup. This capability could be useful when you have multiple builds of the same application with the same bundleId on your machine (for example one production build in /Applications/ and several dev builds). If you provide bundleId only, the operating system could open any of these builds. By providing `appPath` you have a guarantee that the specified .app will be launched, rather than a random one.
appium:appLocale | A dictionary with the following possible entries: `locale` (application locale name, for example `uk_UA`), `language` (application language name, for example `de`), `useMetricUnits` (whether to use metric units for the app, if `false` then imperial units are used), `measurementUnits` (the name of measurement units to use in the app, for example `Inches`). This capability only changes the locale for the app under test, it does not modify the system locale. You can achieve the same effect by providing custom values to reserved app command line arguments like `-AppleLanguages` or `-AppleLocale` using the `appium:arguments` capability. Example: use `appLocale = {locale: "de", language: "de_DE"}` to start the app in German language (if no German resources are defined in the destination app bundle then the app is started with the default locale, usually en_US).


## Element Attributes
Expand Down
35 changes: 34 additions & 1 deletion WebDriverAgentMac/WebDriverAgentLib/Commands/FBSessionCommands.m
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,14 @@ + (NSArray *)routes
if (noReset && app.state > XCUIApplicationStateNotRunning) {
[app activate];
} else {
app.launchArguments = (NSArray<NSString *> *)requirements[AM_APP_ARGUMENTS_CAPABILITY] ?: @[];
NSMutableArray<NSString *> *launchArguments = [NSMutableArray new];
if (nil != requirements[AM_APP_ARGUMENTS_CAPABILITY]) {
[launchArguments addObjectsFromArray:(NSArray<NSString *> *)requirements[AM_APP_ARGUMENTS_CAPABILITY]];
}
if (nil != requirements[AM_APP_LOCALE_CAPABILITY]) {
[launchArguments addObjectsFromArray:[self appArgumentsForLocale:requirements[AM_APP_LOCALE_CAPABILITY]]];
}
app.launchArguments = [launchArguments copy];
app.launchEnvironment = (NSDictionary <NSString *, NSString *> *)requirements[AM_APP_ENVIRONMENT_CAPABILITY] ?: @{};
[app launch];
if (app.state <= XCUIApplicationStateNotRunning) {
Expand Down Expand Up @@ -234,4 +241,30 @@ + (NSDictionary *)currentCapabilities
};
}

+ (NSArray<NSString *> *)appArgumentsForLocale:(NSDictionary<NSString *, NSString *> *)appLocale
{
// https://developer.apple.com/forums/thread/678634
NSMutableArray<NSString *> *result = [NSMutableArray new];
if (nil != appLocale[@"language"]) {
[result addObject:@"-AppleLanguages"];
[result addObject:[NSString stringWithFormat:@"(%@)", appLocale[@"language"]]];
}
if (nil != appLocale[@"locale"]) {
[result addObject:@"-AppleLocale"];
[result addObject:[NSString stringWithFormat:@"%@", appLocale[@"locale"]]];
}
if (nil != appLocale[@"useMetricUnits"]) {
[result addObject:@"-AppleMetricUnits"];
[result addObject:[NSString stringWithFormat:@"<%@/>", appLocale[@"useMetricUnits"] ? @"true" : @"false"]];
}
if (nil != appLocale[@"measurementUnits"]) {
[result addObject:@"-AppleMeasurementUnits"];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe, not sure how to test that though...

Copy link
Contributor Author

@mykola-mokhnach mykola-mokhnach Feb 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feel free to add it if you know how

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like AppleTemperatureUnit works for ios as well. processArguments/arguments is sufficient tho

[result addObject:[NSString stringWithFormat:@"%@", appLocale[@"measurementUnits"]]];
}
if (result.count > 0) {
[FBLogger logFmt:@"appLocale %@ has been parsed to the following command line arguments: %@", appLocale, result];
}
return [result copy];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ extern NSString* const AM_APP_ENVIRONMENT_CAPABILITY;
extern NSString* const AM_SKIP_APP_KILL_CAPABILITY;
extern NSString* const AM_NO_RESET_CAPABILITY;
extern NSString* const AM_APP_PATH_CAPABILITY;
extern NSString* const AM_APP_LOCALE_CAPABILITY;

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@
NSString* const AM_SKIP_APP_KILL_CAPABILITY = @"skipAppKill";
NSString* const AM_NO_RESET_CAPABILITY = @"noReset";
NSString* const AM_APP_PATH_CAPABILITY = @"appPath";
NSString* const AM_APP_LOCALE_CAPABILITY = @"appLocale";
5 changes: 4 additions & 1 deletion lib/desired-caps.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ const desiredCapConstraints = {
},
appPath: {
isString: true
}
},
appLocale: {
isObject: true
},
};

export { desiredCapConstraints };
Loading