Files
upstream-mirror 9ad64ec987
Some checks failed
integration tests / run-integration-tests (windows-latest) (push) Has been cancelled
Test Rust / test (push) Has been cancelled
test plugins e2e (mobile) / ios (push) Has been cancelled
test plugins e2e / test (map[name:Windows os:windows-latest]) (push) Has been cancelled
test plugins e2e / test (map[name:macOS os:macos-latest]) (push) Has been cancelled
integration tests / run-integration-tests (macos-latest) (push) Has been cancelled
version or publish / version-or-publish (push) Failing after 0s
integration tests / run-integration-tests (ubuntu-22.04) (push) Failing after 0s
Lint JavaScript / eslint (push) Failing after 0s
Sync / sync-to-mirrors (push) Failing after 0s
test plugins e2e (mobile) / android (push) Failing after 0s
test plugins e2e / test (map[name:Linux os:ubuntu-latest]) (push) Failing after 0s
Test Rust / changes (push) Failing after 0s
Lint Rust / changes (push) Failing after 0s
Lint Rust / clippy (push) Has been skipped
Audit Rust / audit-rust (push) Failing after 1s
Audit JavaScript / audit-js (push) Failing after 1s
snapshot of https://github.com/tauri-apps/plugins-workspace.git (v2, 2026-09-23; blobs > 131072B omitted)
2026-09-23 17:17:10 +05:00

235 lines
5.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import { expect } from '@wdio/globals'
import {
tauri,
isMobile,
type CommonPluginApi,
type DesktopPluginApi,
type MobilePluginApi
} from '../helpers/index.js'
/**
* The members each plugin's `api-iife.js` is expected to define on
* `window.__TAURI__.<plugin>`. This is the one place the suite covers the
* plugins whose commands cannot be driven from a WebDriver session (dialog
* blocks on native UI, process terminates the app, the mobile plugins need
* hardware or native UI), and it catches a plugin whose global API script is
* missing from its `build.rs`.
*/
type Surface<T> = { [P in keyof T]: (keyof T[P])[] }
/** Plugins the example registers on every platform. */
const commonSurface: Surface<CommonPluginApi> = {
clipboardManager: [
'writeText',
'readText',
'writeHtml',
'clear',
'readImage',
'writeImage'
],
deepLink: [
'getCurrent',
'register',
'unregister',
'isRegistered',
'onOpenUrl'
],
dialog: ['open', 'save', 'message', 'ask', 'confirm'],
fs: [
'BaseDirectory',
'FileHandle',
'SeekMode',
'create',
'open',
'copyFile',
'mkdir',
'readDir',
'readFile',
'readTextFile',
'readTextFileLines',
'remove',
'rename',
'stat',
'lstat',
'truncate',
'writeFile',
'writeTextFile',
'exists',
'watch',
'watchImmediate',
'size'
],
http: ['fetch'],
log: [
'LogLevel',
'error',
'warn',
'info',
'debug',
'trace',
'attachLogger',
'attachConsole'
],
notification: [
'isPermissionGranted',
'requestPermission',
'sendNotification',
'registerActionTypes',
'pending',
'cancel',
'cancelAll',
'active',
'removeActive',
'removeAllActive',
'createChannel',
'removeChannel',
'channels',
'onNotificationReceived',
'onAction'
],
opener: ['openUrl', 'openPath', 'revealItemInDir'],
os: [
'eol',
'platform',
'family',
'version',
'type',
'arch',
'locale',
'exeExtension',
'hostname'
],
process: ['exit', 'relaunch'],
shell: ['Command', 'Child', 'EventEmitter', 'open'],
// the `Database` class itself
sql: ['load', 'get'],
store: ['load', 'getStore', 'LazyStore', 'Store'],
stronghold: ['Location', 'Client', 'Store', 'Vault', 'Stronghold'],
upload: ['download', 'upload', 'HttpMethod'],
// the `WebSocket` class itself
websocket: ['connect']
}
/** Plugins the example only registers on desktop. */
const desktopSurface: Surface<DesktopPluginApi> = {
autostart: ['enable', 'disable', 'isEnabled'],
cli: ['getMatches'],
globalShortcut: ['register', 'unregister', 'unregisterAll', 'isRegistered'],
positioner: [
'Position',
'moveWindow',
'moveWindowConstrained',
'handleIconState'
],
updater: ['check', 'Update'],
windowState: [
'StateFlags',
'restoreState',
'restoreStateCurrent',
'saveWindowState',
'filename'
]
}
/** Plugins the example only registers on mobile. */
const mobileSurface: Surface<MobilePluginApi> = {
barcodeScanner: [
'Format',
'scan',
'cancel',
'checkPermissions',
'requestPermissions',
'openAppSettings'
],
biometric: ['BiometryType', 'checkStatus', 'authenticate'],
geolocation: [
'watchPosition',
'getCurrentPosition',
'clearWatch',
'checkPermissions',
'requestPermissions'
],
// `ImpactFeedbackStyle` and `NotificationFeedbackType` are type aliases, so
// they are not part of the runtime namespace.
haptics: [
'vibrate',
'impactFeedback',
'notificationFeedback',
'selectionFeedback'
],
nfc: [
'NFCTypeNameFormat',
'TechKind',
'RTD_TEXT',
'RTD_URI',
'record',
'textRecord',
'uriRecord',
'scan',
'write',
'isAvailable'
]
}
const surface = {
...commonSurface,
...(isMobile ? mobileSurface : desktopSurface)
} as Record<string, string[]>
/** The other platform's plugins, which must *not* be in this build. */
const foreign = Object.keys(isMobile ? desktopSurface : mobileSurface)
describe('plugin globals', () => {
it('every plugin this platform registers exposes its API on window.__TAURI__', async () => {
const missing = await tauri(
(api, plugins) =>
plugins.filter((plugin) => {
// eslint-disable-next-line security/detect-object-injection
const global = (api as unknown as Record<string, unknown>)[plugin]
// a module namespace, or the class a default-export-only module (sql, websocket) defines
return typeof global !== 'object' && typeof global !== 'function'
}),
Object.keys(surface)
)
expect(missing).toEqual([])
})
it('the other platform’s plugins are not in the build', async () => {
// Their Rust crates are target-gated in the example's Cargo.toml, so their
// `global_api_script_path` is never injected either.
const present = await tauri(
(api, plugins) =>
plugins.filter(
(plugin) =>
// eslint-disable-next-line security/detect-object-injection
(api as unknown as Record<string, unknown>)[plugin] !== undefined
),
foreign
)
expect(present).toEqual([])
})
for (const [plugin, members] of Object.entries(surface)) {
it(`${plugin} exposes its documented members`, async () => {
const missing = await tauri(
(api, plugin, members) => {
const namespaces = api as unknown as Record<
string,
Record<string, unknown>
>
// eslint-disable-next-line security/detect-object-injection
const namespace = namespaces[plugin]
return members.filter((member) => !(member in namespace))
},
plugin,
members
)
expect(missing).toEqual([])
})
}
})