tests(e2e): improve coverage

This commit is contained in:
Lucas Nogueira
2026-09-22 21:54:21 -03:00
parent 684feb2510
commit c8c373b48b
50 changed files with 1893 additions and 183 deletions
@@ -39,7 +39,8 @@ class BatchArgs {
@InvokeArg
class CancelArgs {
lateinit var notifications: List<Int>
// `cancelAll()` sends no list: cancel every pending notification
var notifications: List<Int>? = null
}
@InvokeArg
@@ -152,7 +153,9 @@ class NotificationPlugin(private val activity: Activity): Plugin(activity) {
@Command
fun cancel(invoke: Invoke) {
val args = invoke.parseArgs(CancelArgs::class.java)
manager.cancel(args.notifications)
manager.cancel(
args.notifications ?: notificationStorage.getSavedNotificationIds().mapNotNull { it.toIntOrNull() }
)
invoke.resolve()
}
@@ -192,32 +195,33 @@ class NotificationPlugin(private val activity: Activity): Plugin(activity) {
@SuppressLint("ObsoleteSdkInt")
@Command
fun getActive(invoke: Invoke) {
val notifications = JSArray()
// plain lists and maps: until tauri serializes org.json values natively,
// `resolveObject` turns a `JSArray` into `{ "values": [...] }`
val notifications = mutableListOf<Map<String, Any?>>()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val activeNotifications = notificationManager.activeNotifications
for (activeNotification in activeNotifications) {
val jsNotification = JSObject()
jsNotification.put("id", activeNotification.id)
jsNotification.put("tag", activeNotification.tag)
val jsNotification = mutableMapOf<String, Any?>(
"id" to activeNotification.id,
"tag" to activeNotification.tag
)
val notification = activeNotification.notification
if (notification != null) {
jsNotification.put("title", notification.extras.getCharSequence(android.app.Notification.EXTRA_TITLE))
jsNotification.put("body", notification.extras.getCharSequence(android.app.Notification.EXTRA_TEXT))
jsNotification.put("group", notification.group)
jsNotification.put(
"groupSummary",
jsNotification["title"] = notification.extras.getCharSequence(android.app.Notification.EXTRA_TITLE)?.toString()
jsNotification["body"] = notification.extras.getCharSequence(android.app.Notification.EXTRA_TEXT)?.toString()
jsNotification["group"] = notification.group
jsNotification["groupSummary"] =
0 != notification.flags and android.app.Notification.FLAG_GROUP_SUMMARY
)
val extras = JSObject()
val extras = mutableMapOf<String, String?>()
for (key in notification.extras.keySet()) {
extras.put(key!!, notification.extras.getString(key))
extras[key] = notification.extras.getString(key)
}
jsNotification.put("data", extras)
jsNotification["data"] = extras
}
notifications.put(jsNotification)
notifications.add(jsNotification)
}
}
invoke.resolveObject(notifications)
}
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_NOTIFICATION__=function(i,n){"use strict";var e,t,o;i.ScheduleEvery=void 0,(e=i.ScheduleEvery||(i.ScheduleEvery={})).Year="year",e.Month="month",e.TwoWeeks="twoWeeks",e.Week="week",e.Day="day",e.Hour="hour",e.Minute="minute",e.Second="second";return i.Importance=void 0,(t=i.Importance||(i.Importance={}))[t.None=0]="None",t[t.Min=1]="Min",t[t.Low=2]="Low",t[t.Default=3]="Default",t[t.High=4]="High",i.Visibility=void 0,(o=i.Visibility||(i.Visibility={}))[o.Secret=-1]="Secret",o[o.Private=0]="Private",o[o.Public=1]="Public",i.Schedule=class{static at(i,n=!1,e=!1){return{at:{date:i,repeating:n,allowWhileIdle:e},interval:void 0,every:void 0}}static interval(i,n=!1){return{at:void 0,interval:{interval:i,allowWhileIdle:n},every:void 0}}static every(i,n,e=!1){return{at:void 0,interval:void 0,every:{interval:i,count:n,allowWhileIdle:e}}}},i.active=async function(){return await n.invoke("plugin:notification|get_active")},i.cancel=async function(i){await n.invoke("plugin:notification|cancel",{notifications:i})},i.cancelAll=async function(){await n.invoke("plugin:notification|cancel")},i.channels=async function(){return await n.invoke("plugin:notification|listChannels")},i.createChannel=async function(i){await n.invoke("plugin:notification|create_channel",{...i})},i.isPermissionGranted=async function(){return"default"!==window.Notification.permission?await Promise.resolve("granted"===window.Notification.permission):await n.invoke("plugin:notification|is_permission_granted")},i.onAction=async function(i){return await n.addPluginListener("notification","actionPerformed",i)},i.onNotificationReceived=async function(i){return await n.addPluginListener("notification","notification",i)},i.pending=async function(){return await n.invoke("plugin:notification|get_pending")},i.registerActionTypes=async function(i){await n.invoke("plugin:notification|register_action_types",{types:i})},i.removeActive=async function(i){await n.invoke("plugin:notification|remove_active",{notifications:i})},i.removeAllActive=async function(){await n.invoke("plugin:notification|remove_active")},i.removeChannel=async function(i){await n.invoke("plugin:notification|delete_channel",{id:i})},i.requestPermission=async function(){return await window.Notification.requestPermission()},i.sendNotification=function(i){"string"==typeof i?new window.Notification(i):new window.Notification(i.title,i)},i}({},window.__TAURI__.core);Object.defineProperty(window.__TAURI__,"notification",{value:__TAURI_PLUGIN_NOTIFICATION__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_NOTIFICATION__=function(i,n){"use strict";var e,t,o;i.ScheduleEvery=void 0,(e=i.ScheduleEvery||(i.ScheduleEvery={})).Year="year",e.Month="month",e.TwoWeeks="twoWeeks",e.Week="week",e.Day="day",e.Hour="hour",e.Minute="minute",e.Second="second";return i.Importance=void 0,(t=i.Importance||(i.Importance={}))[t.None=0]="None",t[t.Min=1]="Min",t[t.Low=2]="Low",t[t.Default=3]="Default",t[t.High=4]="High",i.Visibility=void 0,(o=i.Visibility||(i.Visibility={}))[o.Secret=-1]="Secret",o[o.Private=0]="Private",o[o.Public=1]="Public",i.Schedule=class{static at(i,n=!1,e=!1){return{at:{date:i,repeating:n,allowWhileIdle:e},interval:void 0,every:void 0}}static interval(i,n=!1){return{at:void 0,interval:{interval:i,allowWhileIdle:n},every:void 0}}static every(i,n,e=!1){return{at:void 0,interval:void 0,every:{interval:i,count:n,allowWhileIdle:e}}}},i.active=async function(){return await n.invoke("plugin:notification|get_active")},i.cancel=async function(i){await n.invoke("plugin:notification|cancel",{notifications:i})},i.cancelAll=async function(){await n.invoke("plugin:notification|cancel")},i.channels=async function(){return await n.invoke("plugin:notification|list_channels")},i.createChannel=async function(i){await n.invoke("plugin:notification|create_channel",{...i})},i.isPermissionGranted=async function(){return"default"!==window.Notification.permission?await Promise.resolve("granted"===window.Notification.permission):await n.invoke("plugin:notification|is_permission_granted")},i.onAction=async function(i){return await n.addPluginListener("notification","actionPerformed",i)},i.onNotificationReceived=async function(i){return await n.addPluginListener("notification","notification",i)},i.pending=async function(){return await n.invoke("plugin:notification|get_pending")},i.registerActionTypes=async function(i){await n.invoke("plugin:notification|register_action_types",{types:i})},i.removeActive=async function(i){await n.invoke("plugin:notification|remove_active",{notifications:i})},i.removeAllActive=async function(){await n.invoke("plugin:notification|remove_active")},i.removeChannel=async function(i){await n.invoke("plugin:notification|delete_channel",{id:i})},i.requestPermission=async function(){return await window.Notification.requestPermission()},i.sendNotification=function(i){"string"==typeof i?new window.Notification(i):new window.Notification(i.title,i)},i}({},window.__TAURI__.core);Object.defineProperty(window.__TAURI__,"notification",{value:__TAURI_PLUGIN_NOTIFICATION__})}
+1
View File
@@ -8,6 +8,7 @@ const COMMANDS: &[&str] = &[
"is_permission_granted",
"register_action_types",
"register_listener",
"remove_listener",
"cancel",
"get_pending",
"remove_active",
+1 -1
View File
@@ -879,7 +879,7 @@ async function removeChannel(id: string): Promise<void> {
* @since 2.0.0
*/
async function channels(): Promise<Channel[]> {
return await invoke('plugin:notification|listChannels')
return await invoke('plugin:notification|list_channels')
}
/**
@@ -120,7 +120,8 @@ func showNotification(invoke: Invoke, notification: Notification)
}
struct CancelArgs: Decodable {
let notifications: [Int]
// `cancelAll()` sends no list: cancel every pending notification
let notifications: [Int]?
}
struct Action: Decodable {
@@ -216,9 +217,13 @@ class NotificationPlugin: Plugin {
@objc func cancel(_ invoke: Invoke) throws {
let args = try invoke.parseArgs(CancelArgs.self)
UNUserNotificationCenter.current().removePendingNotificationRequests(
withIdentifiers: args.notifications.map { String($0) }
)
if let notifications = args.notifications {
UNUserNotificationCenter.current().removePendingNotificationRequests(
withIdentifiers: notifications.map { String($0) }
)
} else {
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
}
invoke.resolve()
}
@@ -0,0 +1,13 @@
# Automatically generated - DO NOT EDIT!
"$schema" = "../../schemas/schema.json"
[[permission]]
identifier = "allow-remove-listener"
description = "Enables the remove_listener command without any pre-configured scope."
commands.allow = ["remove_listener"]
[[permission]]
identifier = "deny-remove-listener"
description = "Denies the remove_listener command without any pre-configured scope."
commands.deny = ["remove_listener"]
@@ -14,6 +14,7 @@ It allows all notification related features.
- `allow-notify`
- `allow-register-action-types`
- `allow-register-listener`
- `allow-remove-listener`
- `allow-cancel`
- `allow-get-pending`
- `allow-remove-active`
@@ -402,6 +403,32 @@ Denies the remove_active command without any pre-configured scope.
<tr>
<td>
`notification:allow-remove-listener`
</td>
<td>
Enables the remove_listener command without any pre-configured scope.
</td>
</tr>
<tr>
<td>
`notification:deny-remove-listener`
</td>
<td>
Denies the remove_listener command without any pre-configured scope.
</td>
</tr>
<tr>
<td>
`notification:allow-request-permission`
</td>
@@ -16,6 +16,7 @@ permissions = [
"allow-notify",
"allow-register-action-types",
"allow-register-listener",
"allow-remove-listener",
"allow-cancel",
"allow-get-pending",
"allow-remove-active",
@@ -462,6 +462,18 @@
"const": "deny-remove-active",
"markdownDescription": "Denies the remove_active command without any pre-configured scope."
},
{
"description": "Enables the remove_listener command without any pre-configured scope.",
"type": "string",
"const": "allow-remove-listener",
"markdownDescription": "Enables the remove_listener command without any pre-configured scope."
},
{
"description": "Denies the remove_listener command without any pre-configured scope.",
"type": "string",
"const": "deny-remove-listener",
"markdownDescription": "Denies the remove_listener command without any pre-configured scope."
},
{
"description": "Enables the request_permission command without any pre-configured scope.",
"type": "string",
@@ -487,10 +499,10 @@
"markdownDescription": "Denies the show command without any pre-configured scope."
},
{
"description": "This permission set configures which\nnotification features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all notification related features.\n\n\n#### This default permission set includes:\n\n- `allow-is-permission-granted`\n- `allow-request-permission`\n- `allow-notify`\n- `allow-register-action-types`\n- `allow-register-listener`\n- `allow-cancel`\n- `allow-get-pending`\n- `allow-remove-active`\n- `allow-get-active`\n- `allow-check-permissions`\n- `allow-show`\n- `allow-batch`\n- `allow-list-channels`\n- `allow-delete-channel`\n- `allow-create-channel`\n- `allow-permission-state`",
"description": "This permission set configures which\nnotification features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all notification related features.\n\n\n#### This default permission set includes:\n\n- `allow-is-permission-granted`\n- `allow-request-permission`\n- `allow-notify`\n- `allow-register-action-types`\n- `allow-register-listener`\n- `allow-remove-listener`\n- `allow-cancel`\n- `allow-get-pending`\n- `allow-remove-active`\n- `allow-get-active`\n- `allow-check-permissions`\n- `allow-show`\n- `allow-batch`\n- `allow-list-channels`\n- `allow-delete-channel`\n- `allow-create-channel`\n- `allow-permission-state`",
"type": "string",
"const": "default",
"markdownDescription": "This permission set configures which\nnotification features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all notification related features.\n\n\n#### This default permission set includes:\n\n- `allow-is-permission-granted`\n- `allow-request-permission`\n- `allow-notify`\n- `allow-register-action-types`\n- `allow-register-listener`\n- `allow-cancel`\n- `allow-get-pending`\n- `allow-remove-active`\n- `allow-get-active`\n- `allow-check-permissions`\n- `allow-show`\n- `allow-batch`\n- `allow-list-channels`\n- `allow-delete-channel`\n- `allow-create-channel`\n- `allow-permission-state`"
"markdownDescription": "This permission set configures which\nnotification features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all notification related features.\n\n\n#### This default permission set includes:\n\n- `allow-is-permission-granted`\n- `allow-request-permission`\n- `allow-notify`\n- `allow-register-action-types`\n- `allow-register-listener`\n- `allow-remove-listener`\n- `allow-cancel`\n- `allow-get-pending`\n- `allow-remove-active`\n- `allow-get-active`\n- `allow-check-permissions`\n- `allow-show`\n- `allow-batch`\n- `allow-list-channels`\n- `allow-delete-channel`\n- `allow-create-channel`\n- `allow-permission-state`"
}
]
}
+2
View File
@@ -287,6 +287,8 @@ mod imp {
use std::path::PathBuf;
pub fn reveal_items_in_dir(paths: &[PathBuf]) -> crate::Result<()> {
// these AppKit calls are only `unsafe` before objc2-app-kit 0.3.2
#[allow(unused_unsafe)]
unsafe {
let mut urls = Vec::new();