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 a possibility to simulate push notifications via simctl #1286

Merged
merged 3 commits into from
Mar 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,20 @@ Name | Type | Required | Description | Example
--- | --- | --- | --- | ---
name | string | yes | The name of the button to be pressed. Supported button names for iOS-based devices are (case-insensitive): `home`, `volumeup`, `volumedown`. For tvOS-based devices (case-insensitive): `home`, `up`, `down`, `left`, `right`, `menu`, `playpause`, `select` | home

### mobile: pushNotification

Simulates push notification delivery to Simulator.
Only application remote push notifications are supported. VoIP, Complication, File Provider,
and other types are not supported. Check the output of `xcrun simctl help push`
command for more details.

#### Arguments

Name | Type | Required | Description | Example
--- | --- | --- | --- | ---
bundleId | string | yes | The bundle identifier of the target application | com.apple.Preferences
payload | map | yes | Valid Apple Push Notification values. Read the `Create the JSON Payload` topic of the [official Apple documentation](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification?language=objc) for more details on the payload creation. | `{"aps": {"alert": "This is a simulated notification!", "badge": 3, "sound": "default"} }`
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

@gromanas gromanas Apr 21, 2021

Choose a reason for hiding this comment

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

If I could made a comment, I have already try to use {"aps": {"alert": "This is a simulated notification!", "badge": 3, "sound": "default"} } and i got an error about Simulator Target Bundle using Xcode 12.4. I have change it to {"Simulator Target Bundle": "your.apps.bundleId", "aps": {"alert": { "title": "This is a simulated notification!"}, "badge": 3, "sound": "default"} } and it worked.


### mobile: enrollBiometric

Enrolls biometric authentication on Simulator.
Expand Down
2 changes: 2 additions & 0 deletions lib/commands/execute.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ extensions.executeMobile = async function executeMobile (mobileCommand, opts = {
installXCTestBundle: 'mobileInstallXCTestBundle',
listXCTestBundles: 'mobileListXCTestBundles',
listXCTestsInTestBundle: 'mobileListXCTestsInTestBundle',

pushNotification: 'mobilePushNotification',
};

if (!_.has(commandMap, mobileCommand)) {
Expand Down
4 changes: 3 additions & 1 deletion lib/commands/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import keychainsExtensions from './keychains';
import permissionsExtensions from './permissions';
import appearanceExtensions from './appearance';
import xctestExtensions from './xctest';
import notificationsExtensions from './notifications';

let commands = {};

Expand All @@ -42,7 +43,8 @@ Object.assign(commands, contextCommands, executeExtensions,
lockExtensions, recordScreenExtensions, appManagementExtensions, performanceExtensions,
clipboardExtensions, certificateExtensions, batteryExtensions, cookiesExtensions,
biometricExtensions, keychainsExtensions, permissionsExtensions, deviceInfoExtensions,
activeAppInfoExtensions, recordAudioExtensions, appearanceExtensions, xctestExtensions
activeAppInfoExtensions, recordAudioExtensions, appearanceExtensions, xctestExtensions,
notificationsExtensions,
);

export default commands;
49 changes: 49 additions & 0 deletions lib/commands/notifications.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { errors } from 'appium-base-driver';
import _ from 'lodash';

const extensions = {};

/**
* @typedef {Object} PushNotification
*
* @property {!string} bundleId - The bundle identifier of the target application
* @property {!object} payload - Remote notification payload. Read the `Create the JSON Payload` topic of
* https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification
* for more details on how to create this payload.
*/

/**
* Simulates push notification delivery to Simulator.
* Only application remote push notifications are supported. VoIP, Complication, File Provider,
* and other types are not supported
*
* @since Xcode SDK 11.4
* @param {PushNotification} opts - The object that describes Apple push notification content.
* It must contain a top-level `bundleId` key with a string value matching
* the target application‘s bundle identifier and "payload.aps" key with valid Apple Push Notification values.
* Check the output of `xcrun simctl help push` command for more details.
*/
extensions.mobilePushNotification = async function mobilePushNotification (opts = {}) {
if (!this.isSimulator()) {
throw new Error('This extension only works on Simulator');
Copy link
Member

Choose a reason for hiding this comment

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

👍

}

const { payload, bundleId } = opts;
if (!bundleId) {
throw new errors.InvalidArgumentError(`'bundleId' argument must be a valid bundle identifier string`);
}
if (!_.isPlainObject(payload)) {
throw new errors.InvalidArgumentError(`The 'payload' argument value must be a valid dictionary. ` +
`Got ${JSON.stringify(payload)} instead`);
}
if (!_.isPlainObject(payload.aps)) {
throw new errors.InvalidArgumentError(`The 'payload.aps' value must be a valid dictionary. ` +
`Got ${JSON.stringify(payload.aps)} instead`);
}
return await this.opts.device.pushNotification({
...payload,
'Simulator Target Bundle': bundleId,
});
};

export default extensions;