Installations
npm install appium-flutter-finder
Developer
truongsinh
Developer Guide
Module System
CommonJS
Min. Node Version
Typescript Support
Yes
Node Version
16.15.1
NPM Version
8.11.0
Statistics
470 Stars
602 Commits
183 Forks
33 Watching
10 Branches
43 Contributors
Updated on 27 Nov 2024
Languages
TypeScript (44.67%)
Ruby (10.36%)
C# (9.49%)
Kotlin (8.44%)
Python (7.34%)
Dart (7.02%)
JavaScript (6.24%)
Java (5.53%)
Objective-C (0.55%)
Shell (0.35%)
Total Downloads
Cumulative downloads
Total Downloads
736,351
Last day
-8.6%
1,528
Compared to previous day
Last week
-8.6%
9,771
Compared to previous week
Last month
5.3%
41,812
Compared to previous month
Last year
90.6%
451,297
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
Appium Flutter Driver
Appium Flutter Driver is a test automation tool for Flutter apps on multiple platforms/OSes. Appium Flutter Driver is part of the Appium mobile test automation tool maintained by the community. Feel free to create PRs to fix issues/improve this driver.
Flutter Driver vs Appium Flutter Driver
Even though Flutter comes with superb integration test support, Flutter Driver, it does not fit some specific use cases, such as
- Writing tests in other languages than Dart
- Running integration test for Flutter app with embedded webview or native view, or existing native app with embedded Flutter view
- Running tests on multiple devices simultaneously
- Running integration tests on device farms that offer Appium support (Please contact the availability for each vendor)
Under the hood, Appium Flutter Driver uses the Dart VM Service Protocol with extension ext.flutter.driver
, similar to Flutter Driver, to control the Flutter app-under-test (AUT).
Appium drivers for Flutter
Appium community currently has two drivers for Flutter environment:
- Appium Flutter driver (this driver)
- Run Flutter commands over websocekt connection against the observaory URL (calls Flutter APIs directly)
- Base APIs are
flutter_driver
Appium Flutter Integration Driver
- Run a server on DartVM as part of the application under test in order to call Flutter APIs via the server
- Base APIs are
integration_test
Appium Flutter Driver or Appium UiAutomator2/XCUITest driver
As a baseline, we recommend using official testing tools and strategy to test Flutter apps as possible in Dart.
If you'd like to test a release app, whcih can be released from app store as-is, Appium UIAutomator2/XCUITest driver is a good choice. Since Flutter 3.19, Flutter apps can expose identifier
for SemanticsProperties
as resource-id
in Android and accessibilityIdentifier
in iOS. They should help to achieve automation against release apps with Appium UIAutomator2/XCUITest as blackbox testing.
- Appium Flutter driver has three contexts to manage the application under test and the device under test. To achieve the
FLUTTER
context, the test package requires testing tools to import. The application under test cannot release as-is.FLUTTER
context sends commands to the Dart VM directly over the observatory URL. This allows you to interact with Flutter elements directly.NATIVE_APP
context is the same as the regular Appium UIAutomator2/XCUITest driverWEBVIEW
context manages the WebView contents over Appium UiAutomator2/XCUITest driver
- (Recommended if possible) Appium UIAutomator2/XCUITest driver directly must be sufficient to achieve automation if the application under test had
semanticLabel
properly. Then, the accessibility mechanism in each OS can expose elements for Appium through OS's accessibility features.- In addition to
semanticLabel
, Flutter 3.19+ may haveidentifier
forSemanticsProperties
(introduced by https://github.com/flutter/flutter/pull/138331). It setsresource-id
andaccessibilityIdentifier
for Android and iOS, then UiAutomator2/XCUITest drivers might also be able to interact with these elements without Appium Flutter Driver."appium:settings[disableIdLocatorAutocompletion]": true
or configuringdisableIdLocatorAutocompletion
via Settings API would be necessary to makeresource-id
idea work without any package name prefix like Android compose.- e.g. https://github.com/flutter/flutter/issues/17988#issuecomment-1867097631
- In addition to
Installation
Appium Flutter Driver version 1.0 and higher require Appium 2.0.
appium driver install --source=npm appium-flutter-driver
As a local:
appium driver install --source local /path/to/appium-flutter-driver/driver
Usage and requirement
If you are unfamiliar with running Appium tests, start with Quickstart Intro first.
Your Flutter application must be compiled in debug
or profile
mode. The dependency must have flutter_driver
package like the below pubspec.yaml
example with enableFlutterDriverExtension
configuration in the main.dart
.
1# pubspec.yaml 2dev_dependencies: 3 flutter_driver: 4 sdk: flutter
This snippet, taken from example directory, is a script written as an appium client with webdriverio
, and assumes you have appium
server (with appium-flutter-driver
installed) running on the same host and default port (4723
). For more info, see example's README.md
Note
This means this driver depends on
flutter_driver
. In the past, the Flutter team announced replacingflutter_driver
withintegration_test
, but according to this ticket, this discussion is still ongoing. So flutter_driver would continue to be maintained for now.
Each client needs each finder module to handle Finders. Appium Flutter Driver communicates with the Dart VM directory in the FLUTTER
context.
Doctor
Since driver version 2.4.0 you can automate the validation for the most of the above requirements as well as various optional ones needed by driver extensions by running the appium driver doctor flutter
server command.
The check runs for Android for UIAutomator2 driver and iOS for XCUITest driver.
SKIP_ANDROID
or SKIP_IOS
environment variable helps to skip these checks.
# skip Android check
SKIP_ANDROID=1 appium driver doctor flutter
# skip iOS check
SKIP_IOS=1 appium driver doctor flutter
Note
- Flutter context does not support page source
- Please use
getRenderTree
command instead
- Please use
- You can send appium-xcuitest-driver/appium-uiautomator2-driver commands in
NATIVE_APP
context scrollUntilVisible
command : An expectation for checking that an element, known to be present on the widget tree, is visible. Using waitFor to wait elementscrollUntilTapable
command : An expectation for checking an element is visible and enabled such that you can click it. Using waitTapable to wait elementdriver.activateApp(appId)
starts the given app and attaches to the observatory URL in theFLUTTER
context. The method may raise an exception if no observaotry URL was found. The typical case is theappId
is already running. Then, the driver will fail to find the observatory URL.getClipboard
andsetClipboard
depend on eachNATIVE_APP
context behavior- Launch via
flutter:launchApp
or 3rd party tool (via instrument service) and attach to the Dart VM for an iOS real device (profile build)- Do not set
app
norbundleId
to start a session without launching apps - Start the app process via 3rd party tools such as go-ios to start the app process with debug mode in the middle of the new session process in 1) the above.
- Then, the appium flutter session establish the WebSocket and proceed the session
- Do not set
- keyboard interaction may not work in Android because of https://github.com/flutter/flutter/issues/15415 that is caused by
flutter_driver
Capabilities
For the Appium Flutter Driver only
Capability | Description | Example Values |
---|---|---|
appium:retryBackoffTime | The interval to find the observetory url from logs. (default 3000ms) | 500 |
appium:maxRetryCount | The count to find the observatory url. (default 10) | 20 |
appium:observatoryWsUri | The URL to attach to the Dart VM. The Appium Flutter Driver finds the WebSocket URL from the device log by default. You can skip the finding the URL process by specifying this capability. Then, this driver attempt to establish a WebSocket connection against the given WebSocket URL. Note that this capability expects the URL is ready for access by outside an appium session. This flutter driver does not do port-forwarding with this capability. You may need to coordinate the port-forwarding as well. | 'ws://127.0.0.1:60992/aaaaaaaaaaa=/ws' |
appium:isolateId | The isolate id to attach to as the initial attempt. A session can change the isolate with flutter:setIsolateId command. The default behavior finds main isolate id and attaches it. | isolates/2978358234363215 , 2978358234363215 |
appium:skipPortForward | Whether skip port forwarding from the flutter driver local to the device under test with observatoryWsUri capability. It helps you to manage the application under test, the observatory URL and the port forwarding configuration. The default is true . | true, false |
appium:remoteAdbHost | The IP/hostname of the remote host ADB is running on. This capability only makes sense for Android platform. Providing it will implicitly override the host for the Observatory URL if the latter is determined from device logs. localhost be default | 192.168.1.20 |
appium:adbPort | The port number ADB server is running on. This capability only makes sense for Android platform. 5037 by default | 9999 |
appium:forwardingPort | The port number that will be used to forward the traffic from the device under test to locahost. Only applicable if skipPortForward is falsy. Not applicable if the test is executed on iOS Simulator. By default, it is the same as in the provided or autodetected Observatory URL. | 9999 |
UIA2/XCUITest driver
Please check each driver's documentation
- https://github.com/appium/appium-uiautomator2-driver
- https://appium.github.io/appium-xcuitest-driver/latest/capabilities/
Context Management
Appium Flutter Driver allows you to send flutter_driver
commands to the Dart VM in the FLUTTER
context, but it does not support native Android/iOS since the Dart VM can handle in the Dart VM contents. NATIVE_APP
context provides you to use the UIA2 driver for Android and the XCUITest driver for iOS automation. WEBVIEW_XXXX
context helps WebView testing over the UIA2/XCUITest driver that is not available via the flutter_driver.
Thus, you need to switch proper contexts, FLUTTER
, NATIVE_APP
or WEBVIEW_XXXX
, to automate a proper application target.
Example
1# webdriverio 2const wdio = require('webdriverio'); 3const assert = require('assert'); 4const { byValueKey } = require('appium-flutter-finder'); 5 6const osSpecificOps = process.env.APPIUM_OS === 'android' ? { 7 'platformName': 'Android', 8 'appium:deviceName': 'Pixel 2', 9 'appium:app': __dirname + '/../apps/app-free-debug.apk', 10}: process.env.APPIUM_OS === 'ios' ? { 11 'platformName': 'iOS', 12 'appium:platformVersion': '12.2', 13 'appium:deviceName': 'iPhone X', 14 'appium:noReset': true, 15 'appium:app': __dirname + '/../apps/Runner.zip', 16} : {}; 17 18const opts = { 19 port: 4723, 20 capabilities: { 21 ...osSpecificOps, 22 'appium:automationName': 'Flutter', 23 'appium:retryBackoffTime': 500 24 } 25}; 26 27(async () => { 28 const counterTextFinder = byValueKey('counter'); 29 const buttonFinder = byValueKey('increment'); 30 31 const driver = await wdio.remote(opts); 32 33 if (process.env.APPIUM_OS === 'android') { 34 await driver.switchContext('NATIVE_APP'); 35 await (await driver.$('~fab')).click(); 36 await driver.switchContext('FLUTTER'); 37 } else { 38 console.log('Switching context to `NATIVE_APP` is currently only applicable to Android demo app.') 39 } 40 41 assert.strictEqual(await driver.getElementText(counterTextFinder), '0'); 42 43 await driver.elementClick(buttonFinder); 44 await driver.touchAction({ 45 action: 'tap', 46 element: { elementId: buttonFinder } 47 }); 48 49 assert.strictEqual(await driver.getElementText(counterTextFinder), '2'); 50 51 driver.deleteSession(); 52})();
Please check example in this repository for more languages.
Several ways to start an application
You have a couple of methods to start the application under test by establishing the Dart VM connection as below:
- Start with
app
in the capabilities- The most standard method. You may need to start a new session with
app
capability. Then, appium-flutter-driver will start the app, and establish a connection with the Dart VM immediately.
- The most standard method. You may need to start a new session with
- Start with
activate_app
: for users who want to start the application under test in the middle of a session- Start a session without
app
capability - Install the application under test via
driver.install_app
ormobile:installApp
command - Activate the app via
driver.activate_app
ormobile:activateApp
command- Then, appium-flutter-driver establish a connection with the Dart VM
- Start a session without
- Launch the app outside the driver: for users who want to manage the application under test by yourselves
- Start a session without
app
capability - Install the application under test via
driver.install_app
ormobile:installApp
command etc - Calls
flutter:connectObservatoryWsUrl
command to keep finding an observatory URL to the Dart VM - (at the same time) Launch the application under test via outside the appium-flutter-driver
- Once
flutter:connectObservatoryWsUrl
identify the observatory URL, the command will establish a connection to the Dart VM
- Start a session without
- Launch the app with
flutter:launchApp
for iOS and attach to the Dart VM: for users whom application under test do not print the observatory url via regular launch/activate app method- Start a session without
app
capability - Install the application under test via
driver.install_app
ormobile:installApp
command etc - Calls
flutter:launchApp
command to start an iOS app via instrument servicedriver.execute_script 'flutter:launchApp', 'com.example.bundleId', {arguments: ['arg1'], environment: {ENV1: 'env'}}
is example usage- This launching method is the same as the above 3rd party method, but does the same thing only via the appium flutter driver.
- Start a session without
Please make sure the target app process stops before starting the target app with the above.
Changelog
Commands for NATIVE_APP/WEBVIEW context
Please check each driver's documentation
- https://github.com/appium/appium-uiautomator2-driver
- https://appium.github.io/appium-xcuitest-driver/latest
Commands for FLUTTER context
Legend:
Icon | Description |
---|---|
:white_check_mark: | integrated to CI |
:ok: | manual tested without CI |
:warning: | available without manual tested |
:x: | unavailable |
Finders
Flutter Driver API | Status | WebDriver example |
---|---|---|
ancestor | :ok: | |
bySemanticsLabel | :ok: | |
byTooltip | :ok: | byTooltip('Increment') |
byType | :ok: | byType('TextField') |
byValueKey | :ok: | byValueKey('counter') |
descendant | :ok: | |
pageBack | :ok: | pageBack() |
text | :ok: | byText('foo') |
Commands
The below WebDriver example is by webdriverio.
flutter:
prefix commands are mobile:
command in appium for Android and iOS.
Please replace them properly with your client.
Flutter API | Status | WebDriver example (JavaScript, webdriverio) | Scope |
---|---|---|---|
FlutterDriver.connectedTo | :ok: | wdio.remote(opts) | Session |
checkHealth | :ok: | driver.execute('flutter:checkHealth') | Session |
clearTextbox | :ok: | driver.elementClear(find.byType('TextField')) | Session |
clearTimeline | :ok: | driver.execute('flutter:clearTimeline') | Session |
enterText | :ok: | driver.elementSendKeys(find.byType('TextField'), 'I can enter text') (no focus required) driver.elementClick(find.byType('TextField')); driver.execute('flutter:enterText', 'I can enter text') (focus required by tap/click first) | Session |
forceGC | :ok: | driver.execute('flutter:forceGC') | Session |
getBottomLeft | :ok: | driver.execute('flutter:getBottomLeft', buttonFinder) | Widget |
getBottomRight | :ok: | driver.execute('flutter:getBottomRight', buttonFinder) | Widget |
getCenter | :ok: | driver.execute('flutter:getCenter', buttonFinder) | Widget |
getRenderObjectDiagnostics | :ok: | driver.execute('flutter:getRenderObjectDiagnostics', counterTextFinder, { includeProperties: true, subtreeDepth: 2 }) | Widget |
getWidgetDiagnostics | :ok: (v2.8.0+) | driver.execute('flutter:getWidgetDiagnostics', counterTextFinder, { includeProperties: true, subtreeDepth: 2 }) | Widget |
getRenderTree | :ok: | driver.execute('flutter: getRenderTree') | Session |
getSemanticsId | :ok: | driver.execute('flutter:getSemanticsId', counterTextFinder) | Widget |
getText | :ok: | driver.getElementText(counterTextFinder) | Widget |
getTopLeft | :ok: | driver.execute('flutter:getTopLeft', buttonFinder) | Widget |
getTopRight | :ok: | driver.execute('flutter:getTopRight', buttonFinder) | Widget |
getVmFlags | :x: | Session | |
requestData | :ok: | driver.execute('flutter:requestData', json.dumps({"deepLink": "myapp://item/id1"})) | Session |
runUnsynchronized | :x: | Session | |
setFrameSync | :ok: | driver.execute('flutter:setFrameSync', bool , durationMilliseconds) | Session |
screenshot | :ok: | driver.takeScreenshot() | Session |
screenshot | :ok: | driver.saveScreenshot('a.png') | Session |
scroll | :ok: | driver.execute('flutter:scroll', find.byType('ListView'), {dx: 50, dy: -100, durationMilliseconds: 200, frequency: 30}) | Widget |
scrollIntoView | :ok: | driver.execute('flutter:scrollIntoView', find.byType('TextField'), {alignment: 0.1}) driver.execute('flutter:scrollIntoView', find.byType('TextField'), {alignment: 0.1, timeout: 30000}) | Widget |
scrollUntilVisible | :ok: | driver.execute('flutter:scrollUntilVisible', find.byType('ListView'), {item:find.byType('TextField'), dxScroll: 90, dyScroll: -400}); , driver.execute('flutter:scrollUntilVisible', find.byType('ListView'), {item:find.byType('TextField'), dxScroll: 90, dyScroll: -400, waitTimeoutMilliseconds: 20000}); | Widget |
scrollUntilTapable | :ok: | driver.execute('flutter:scrollUntilTapable', find.byType('ListView'), {item:find.byType('TextField'), dxScroll: 90, dyScroll: -400}); , driver.execute('flutter:scrollUntilTapable', find.byType('ListView'), {item:find.byType('TextField'), dxScroll: 90, dyScroll: -400, waitTimeoutMilliseconds: 20000}); | Widget |
setSemantics | :x: | Session | |
setTextEntryEmulation | :ok: | driver.execute('flutter:setTextEntryEmulation', false) | Session |
startTracing | :x: | Session | |
stopTracingAndDownloadTimeline | :x: | Session | |
tap | :ok: | driver.elementClick(buttonFinder) | Widget |
tap | :ok: | driver.touchAction({action: 'tap', element: {elementId: buttonFinder}}) | Widget |
tap | :ok: | driver.execute('flutter:clickElement', buttonFinder, {timeout:5000}) | Widget |
traceAction | :x: | Session | |
waitFor | :ok: | driver.execute('flutter:waitFor', buttonFinder, 100) | Widget |
waitForAbsent | :ok: | driver.execute('flutter:waitForAbsent', buttonFinder) | Widget |
waitForTappable | :ok: | driver.execute('flutter:waitForTappable', buttonFinder) | Widget |
waitUntilNoTransientCallbacks | :x: | Widget | |
- | :ok: | driver.execute('flutter:getVMInfo') | System |
- | :ok: | driver.execute('flutter:setIsolateId', 'isolates/2978358234363215') | System |
- | :ok: | driver.execute('flutter:getIsolate', 'isolates/2978358234363215') or driver.execute('flutter:getIsolate') | System |
:question: | :ok: | driver.execute('flutter:longTap', find.byValueKey('increment'), {durationMilliseconds: 10000, frequency: 30}) | Widget |
:question: | :ok: | driver.execute('flutter:waitForFirstFrame') | Widget |
- | :ok: | (Ruby) driver.execute_script 'flutter:connectObservatoryWsUrl' | Flutter Driver |
- | :ok: | (Ruby) driver.execute_script 'flutter:launchApp', 'bundleId', {arguments: ['arg1'], environment: {ENV1: 'env'}} | Flutter Driver |
dragAndDropWithCommandExtension | :ok: | (Python) driver.execute_script('flutter:dragAndDropWithCommandExtension', payload) | Command Extension |
NOTE
flutter:launchApp
launches an app via instrument service.mobile:activateApp
anddriver.activate_app
are via XCTest API. They are a bit different.
isolate
handling
Change the flutter engine attache to
- Get available isolate ids
id
key in the value ofisolates
byflutter:getVMInfo
- Set the id via
setIsolateId
1# ruby 2info = driver.execute_script 'flutter:getVMInfo' 3# Change the target engine to "info['isolates'][0]['id']" 4driver.execute_script 'flutter:setIsolateId', info['isolates'][0]['id']
Check current isolate, or a particular isolate
- Get available isolates
driver.execute('flutter:getVMInfo').isolates
(JS)
- Get a particular isolate or current isolate
- Current isolate:
driver.execute('flutter:getIsolate')
(JS) - Particular isolate:
driver.execute('flutter:getIsolate', 'isolates/2978358234363215')
(JS)
- Current isolate:
Commands across contexts
These Appium commands can work across context
deleteSession
setContext
getCurrentContext
getContexts
activateApp('appId')
/mobile:activateApp
mobile:activateApp
hasskipAttachObservatoryUrl
key to not try to attach to an observatory url. e.g.driver.execute_script 'mobile:activateApp', {skipAttachObservatoryUrl: true, appId: 'com.android.chrome'}
terminateApp('appId')
/mobile:terminateApp
installApp(appPath, options)
getClipboard
setClipboard
Command Extension (Flutter Driver)
This is a command extension for Flutter Driver, utilizing the CommandExtension-class within ext.flutter.driver
Available commands:
dragAndDropWithCommandExtension
– performs a drag-and-drop action on the screen by specifying the start and end coordinates and the action duration.
How to use
Copy the extended_commands.dart file to the lib
folder of your Flutter project.
The entry point must include the List<CommandExtension>?
commands argument in either main.dart
or test_main.dart
to properly handle the command extension.
1import 'extended_commands.dart'; 2 3 4void main() { 5 enableFlutterDriverExtension( 6 commands: [DragCommandExtension()]); 7 runApp(const MyApp()); 8}
Simple example using dragAndDropWithCommandExtension
command in Python
1# python 2coord_item_1 = driver.execute_script("flutter:getCenter", item_1) 3coord_item_2 = driver.execute_script("flutter:getCenter", item_2) 4start_x = coord_item_1["dx"] 5start_y = coord_item_1["dy"] 6end_y = coord_item_2["dy"] 7 8payload = { 9 "startX": start_x, 10 "startY": start_y, 11 "endX": "0", 12 "endY": end_y, 13 "duration": "15000" # minimum 15000ms needed to drag n drop 14} 15 16driver.execute_script("flutter:dragAndDropWithCommandExtension", payload)
For debugging or testing in other programming languages, you can use the APK available in this repository or build an IPA.
Troubleshooting
- Input texts https://github.com/appium/appium-flutter-driver/issues/417
- Looks hanging in
click
https://github.com/appium/appium-flutter-driver/issues/181#issuecomment-1323684510flutter:setFrameSync
may help
flutter:waitFor
would help to handle "an element does not exist/is not enabled" behavior. exmaple issue- Appium Inspector does not work with FLUTTER context
TODO?
- switching context between Flutter and AndroidView
- switching context between Flutter and UiKitView
- Web:
FLUTTER_WEB
context? - macOS: with https://github.com/appium/appium-mac2-driver
- Windws?
- Linux?
Release appium-flutter-driver
$ cd driver
$ sh release.sh
$ npm version <major|minor|patch>
# update changelog
$ git commit -am 'chore: bump version'
$ git tag <version number> # e.g. git tag v0.0.32
$ git push origin v0.0.32
$ git push origin main
$ npm publish
Java implementation
No vulnerabilities found.
Reason
5 commit(s) and 11 issue activity found in the last 90 days -- score normalized to 10
Reason
no dangerous workflow patterns detected
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: MIT License: LICENSE:0
Reason
packaging workflow detected
Details
- Info: Project packages its releases by way of GitHub Actions.: .github/workflows/publish.yml:28
Reason
0 existing vulnerabilities detected
Reason
binaries present in source code
Details
- Warn: binary detected: finder/kotlin/gradle/wrapper/gradle-wrapper.jar:1
Reason
security policy file detected
Details
- Info: security policy file detected: github.com/appium/.github/SECURITY.md:1
- Info: Found linked content: github.com/appium/.github/SECURITY.md:1
- Warn: One or no descriptive hints of disclosure, vulnerability, and/or timelines in security policy
- Info: Found text in security policy: github.com/appium/.github/SECURITY.md:1
Reason
SAST tool is not run on all commits -- score normalized to 6
Details
- Warn: 8 commits out of 12 are checked with a SAST tool
Reason
Found 4/28 approved changesets -- score normalized to 1
Reason
detected GitHub workflow tokens with excessive permissions
Details
- Warn: no topLevel permission defined: .github/workflows/dotnet.yml:1
- Warn: no topLevel permission defined: .github/workflows/driver-function.yml:1
- Info: topLevel 'contents' permission set to 'read': .github/workflows/finder-kotlin.yml:15
- Warn: no topLevel permission defined: .github/workflows/finder-node.js.yml:1
- Warn: no topLevel permission defined: .github/workflows/finder-python.yml:1
- Warn: no topLevel permission defined: .github/workflows/finder-ruby.yml:1
- Warn: no topLevel permission defined: .github/workflows/nodejs.yml:1
- Warn: no topLevel permission defined: .github/workflows/publish.yml:1
- Info: no jobLevel write permissions found
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
Project has not signed or included provenance with any releases.
Details
- Warn: release artifact kotlin-finder-0.0.3 not signed: https://api.github.com/repos/appium/appium-flutter-driver/releases/19424460
- Warn: release artifact v0.0.4 not signed: https://api.github.com/repos/appium/appium-flutter-driver/releases/18803803
- Warn: release artifact kotlin-finder-0.0.2 not signed: https://api.github.com/repos/appium/appium-flutter-driver/releases/19393515
- Warn: release artifact kotlin-finder-0.0.3 does not have provenance: https://api.github.com/repos/appium/appium-flutter-driver/releases/19424460
- Warn: release artifact v0.0.4 does not have provenance: https://api.github.com/repos/appium/appium-flutter-driver/releases/18803803
- Warn: release artifact kotlin-finder-0.0.2 does not have provenance: https://api.github.com/repos/appium/appium-flutter-driver/releases/19393515
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/dotnet.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/dotnet.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/dotnet.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/dotnet.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/driver-function.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/driver-function.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/driver-function.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/driver-function.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/driver-function.yml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/driver-function.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/driver-function.yml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/driver-function.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/driver-function.yml:56: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/driver-function.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/driver-function.yml:68: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/driver-function.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/driver-function.yml:81: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/driver-function.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/driver-function.yml:83: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/driver-function.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/driver-function.yml:89: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/driver-function.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/driver-function.yml:108: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/driver-function.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/driver-function.yml:117: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/driver-function.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/driver-function.yml:128: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/driver-function.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/driver-function.yml:136: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/driver-function.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/driver-function.yml:153: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/driver-function.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/finder-kotlin.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/finder-kotlin.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/finder-kotlin.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/finder-kotlin.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/finder-node.js.yml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/finder-node.js.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/finder-node.js.yml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/finder-node.js.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/finder-python.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/finder-python.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/finder-python.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/finder-python.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/finder-ruby.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/finder-ruby.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/finder-ruby.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/finder-ruby.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:40: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/nodejs.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/nodejs.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/publish.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/publish.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/publish.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/appium/appium-flutter-driver/publish.yml/main?enable=pin
- Warn: npmCommand not pinned by hash: driver/release.sh:6
- Warn: npmCommand not pinned by hash: driver/release.sh:12
- Warn: nugetCommand not pinned by hash: .github/workflows/dotnet.yml:30: pin your dependecies by either enabling central package management (https://learn.microsoft.com/nuget/consume-packages/Central-Package-Management) or using a lockfile (https://learn.microsoft.com/nuget/consume-packages/package-references-in-project-files#locking-dependencies)
- Warn: npmCommand not pinned by hash: .github/workflows/driver-function.yml:49
- Warn: npmCommand not pinned by hash: .github/workflows/driver-function.yml:50
- Warn: npmCommand not pinned by hash: .github/workflows/driver-function.yml:95
- Warn: npmCommand not pinned by hash: .github/workflows/driver-function.yml:96
- Warn: npmCommand not pinned by hash: .github/workflows/finder-node.js.yml:45
- Warn: pipCommand not pinned by hash: .github/workflows/finder-python.yml:31
- Warn: pipCommand not pinned by hash: .github/workflows/finder-python.yml:32
- Warn: npmCommand not pinned by hash: .github/workflows/nodejs.yml:46
- Warn: npmCommand not pinned by hash: .github/workflows/publish.yml:24
- Warn: npmCommand not pinned by hash: .github/workflows/publish.yml:40
- Warn: npmCommand not pinned by hash: .github/workflows/publish.yml:49
- Info: 0 out of 23 GitHub-owned GitHubAction dependencies pinned
- Info: 0 out of 7 third-party GitHubAction dependencies pinned
- Info: 0 out of 11 npmCommand dependencies pinned
- Info: 0 out of 1 nugetCommand dependencies pinned
- Info: 0 out of 2 pipCommand dependencies pinned
Score
5.6
/10
Last Scanned on 2024-11-18
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More