├── .changeset ├── README.md ├── commit.js └── config.json ├── .gitignore ├── .markdownlint.yaml ├── .npmrc ├── CHANGELOG.md ├── Makefile ├── README.md ├── automation-runtime.js ├── automation-runtime.ts ├── demo.js ├── docs ├── README.md ├── index │ ├── README.md │ ├── classes │ │ ├── AndroidDevice.md │ │ ├── Device.md │ │ ├── Locator.md │ │ ├── Mouse.md │ │ ├── Page.md │ │ ├── Touchscreen.md │ │ └── iOSDevice.md │ ├── functions │ │ ├── collectLines.md │ │ ├── execFile.md │ │ ├── findWebViewContexts.md │ │ ├── mkdir.md │ │ ├── openWebView.md │ │ ├── pipeline.md │ │ ├── readCommandOutput.md │ │ ├── resolveWebViewContext.md │ │ ├── sleep.md │ │ ├── throwError.md │ │ └── writeFile.md │ └── interfaces │ │ ├── AndroidLogOptions.md │ │ ├── AutomationContext.md │ │ ├── AutomationOptions.md │ │ ├── DeviceOptions.md │ │ ├── LocatorOptions.md │ │ ├── ReaderOptions.md │ │ ├── ResolvedContextPath.md │ │ ├── SelectorOptions.md │ │ ├── StartOptions.md │ │ └── iOSLogOptions.md └── test │ ├── README.md │ ├── classes │ └── DeviceWorkerLauncher.md │ ├── functions │ ├── expect.md │ ├── getFixtureTimeout.md │ ├── setFixtureTimeout.md │ └── test.md │ └── interfaces │ ├── DeviceWorkerFixtures.md │ ├── DeviceWorkerLauncherOptions.md │ ├── DeviceWorkerOptions.md │ └── WebAppConfig.md ├── package.json ├── pnpm-lock.yaml ├── src ├── android-device.ts ├── api.ts ├── automation.ts ├── device.ts ├── index.ts ├── ios-device.ts ├── matchers.cts ├── test.ts └── utils.ts ├── tests ├── example.automation.e2e.ts ├── example.playwright.spec.ts ├── playwright.android.ts ├── playwright.config.ts ├── playwright.ios.ts ├── side-by-side.e2e.ts └── testapp │ ├── .gitignore │ ├── README.md │ ├── android │ ├── .gitignore │ ├── app │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── capacitor.build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── androidTest │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── getcapacitor │ │ │ │ └── myapp │ │ │ │ └── ExampleInstrumentedTest.java │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── onslip │ │ │ │ │ └── automation │ │ │ │ │ └── testapp │ │ │ │ │ └── MainActivity.java │ │ │ └── res │ │ │ │ ├── drawable-land-hdpi │ │ │ │ └── splash.png │ │ │ │ ├── drawable-land-mdpi │ │ │ │ └── splash.png │ │ │ │ ├── drawable-land-xhdpi │ │ │ │ └── splash.png │ │ │ │ ├── drawable-land-xxhdpi │ │ │ │ └── splash.png │ │ │ │ ├── drawable-land-xxxhdpi │ │ │ │ └── splash.png │ │ │ │ ├── drawable-port-hdpi │ │ │ │ └── splash.png │ │ │ │ ├── drawable-port-mdpi │ │ │ │ └── splash.png │ │ │ │ ├── drawable-port-xhdpi │ │ │ │ └── splash.png │ │ │ │ ├── drawable-port-xxhdpi │ │ │ │ └── splash.png │ │ │ │ ├── drawable-port-xxxhdpi │ │ │ │ └── splash.png │ │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ │ ├── drawable │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ └── splash.png │ │ │ │ ├── layout │ │ │ │ └── activity_main.xml │ │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── values │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ │ └── xml │ │ │ │ └── file_paths.xml │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── getcapacitor │ │ │ └── myapp │ │ │ └── ExampleUnitTest.java │ ├── build.gradle │ ├── capacitor.settings.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── variables.gradle │ ├── capacitor.config.json │ ├── ios │ ├── .gitignore │ └── App │ │ ├── App.xcodeproj │ │ └── project.pbxproj │ │ ├── App.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── App │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── AppIcon-512@2x.png │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ └── Splash.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── splash-2732x2732-1.png │ │ │ │ ├── splash-2732x2732-2.png │ │ │ │ └── splash-2732x2732.png │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ └── Info.plist │ │ ├── Podfile │ │ └── Podfile.lock │ ├── package.json │ ├── pnpm-lock.yaml │ ├── src │ ├── assets │ │ ├── icon │ │ │ └── favicon.ico │ │ └── imgs │ │ │ └── logo.png │ ├── css │ │ └── style.css │ ├── index.html │ ├── js │ │ └── capacitor-welcome.js │ └── manifest.json │ └── vite.config.ts ├── tsconfig.base.json ├── tsconfig.driver.json ├── tsconfig.json └── tsconfig.runtime.json /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/commit.js: -------------------------------------------------------------------------------- 1 | const { getVersionMessage } = require('@changesets/cli/commit')['default']; 2 | 3 | exports.getAddMessage = (changeset) => changeset.summary; 4 | exports.getVersionMessage = getVersionMessage; 5 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.7.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": "./commit.js", 5 | "fixed": [], 6 | "linked": [], 7 | "access": "restricted", 8 | "baseBranch": "master", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | /.vscode 3 | /build 4 | /inspiration 5 | /node_modules 6 | /test-results/ 7 | -------------------------------------------------------------------------------- /.markdownlint.yaml: -------------------------------------------------------------------------------- 1 | MD013: 2 | line_length: 120 3 | MD014: false 4 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | hoist-pattern[]= 2 | hoist-pattern[]=@jimp/core 3 | public-hoist-pattern[]= 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @onslip/automation 2 | 3 | ## 1.3.0 4 | 5 | ### Minor Changes 6 | 7 | - 166124f: Handle fixture timeouts better and made them configurable. 8 | 9 | ### Patch Changes 10 | 11 | - 13befc4: Found a way to use same assertion names. Let's pretend 1.2.1 never happened. 12 | 13 | ## 1.2.1 14 | 15 | ### Patch Changes 16 | 17 | - 55b36c4: Trying to use the same assertion names as Playwright was a really bad idea. 18 | 19 | ## 1.2.0 20 | 21 | ### Minor Changes 22 | 23 | - 88f9c39: Support Shadow DOM-piercing. All nested XPath expressions should be relative. 24 | - 2e28f23: Added textContent, isChecked, isDisabled, isEnabled, isEditable, isHidden, isVisible to Locator. 25 | - 0e3d02e: Added a timeout parameter to Device.findDevice(). 26 | - aed87d3: Allow arguments to be passed to started app. 27 | - 2da2b00: Added assertions/custom matchers for @playwright/test. 28 | - 883546e: Added resolveWebViewContext convenience function. 29 | 30 | ### Patch Changes 31 | 32 | - 57286e5: Pass device ID to adb/ideviceinstaller when installing/uninstalling apps. 33 | - 19f723e: Default page timeout should be 0 (disabled), like in Playwright. 34 | 35 | ## 1.1.0 36 | 37 | ### Minor Changes 38 | 39 | - 4cca30e: Bumped deps. 40 | 41 | ### Patch Changes 42 | 43 | - 65463c2: @types/chrome-remote-interface should be a regular dependency. 44 | - 2e0f02f: Don't leak on-exit handlers. 45 | 46 | ## 1.0.1 47 | 48 | ### Patch Changes 49 | 50 | - 7be0f9a: Ensure spawned processes (like idevicesyslog) are killed on exit. 51 | - 1fbabf1: iOS 9 (ES5) fixes. 52 | 53 | ## 1.0.0 54 | 55 | ### Major Changes 56 | 57 | - 16a19ed: Removed 'protocol' option since it's not used anyway. 58 | - b6606b0: Device management is now unified into a single API supporting both Android and iOS. 59 | 60 | ## 0.4.0 61 | 62 | ### Minor Changes 63 | 64 | - b4b6364: Added 'historic' logcat option, a better alternative to 'clear'. 65 | - 723f903: Added basic iOS support via ios_webkit_debug_proxy 66 | - b938d1d: Added fill() to input text. 67 | 68 | ## 0.3.0 69 | 70 | ### Minor Changes 71 | 72 | - 8cc5366: Added stopAndroidApplication and executeAndroidShellCommand helpers. 73 | 74 | ### Patch Changes 75 | 76 | - 9ff4353: Wait for DOM before initialization is complete. 77 | - b653813: Prettier debug output. 78 | - c93c858: Bumped deps. 79 | 80 | ## 0.2.0 81 | 82 | ### Minor Changes 83 | 84 | - bc3a9f2: Added Page.evaluate. 85 | - 6ba828f: Support shorthand text selectors. 86 | - f878fab: Added startAndroidActivity to lauch activities. 87 | - 8b6fce0: Added scrollIntoViewIfNeeded. 88 | - 8d24a46: Added evaluate and evaluateAll. 89 | - f150d66: Added partial Page.mouse. 90 | - 66003f5: Added RegExp text selectors. 91 | - 4dd5293: Added has/hasText locator options. 92 | 93 | ### Patch Changes 94 | 95 | - 755be74: Cannot fetch props from unconnected nodes. 96 | - dd95272: Fixed isTarget calculation. 97 | 98 | ## 0.1.0 99 | 100 | ### Minor Changes 101 | 102 | - 25301f4: Initial release. 103 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TESTAPPS := tests/testapp/dist/index.html \ 2 | tests/testapp/android/app/build/outputs/apk/debug/app-debug.apk \ 3 | tests/testapp/ios/App/DerivedData/App/Build/Products/Debug-iphonesimulator/App.app 4 | 5 | help: ## Show all public targets (this command). 6 | @awk -F ':.*## ' '/^[^\t]+:.*## / { printf "\033[1m%-16s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST) 7 | 8 | all: build docs ## Build all artifacts. 9 | 10 | prepare: ## Build and install all dependencies. 11 | pnpm install --frozen-lockfile 12 | pnpm -C tests/testapp install --frozen-lockfile 13 | 14 | build: prepare ## Build package. 15 | pnpm exec tsc --build 16 | 17 | testapps: prepare ## Build test apps. 18 | $(MAKE) $(TESTAPPS) 19 | 20 | $(TESTAPPS): 21 | pnpm -C tests/testapp build 22 | pnpm -C tests/testapp exec cap sync 23 | cd tests/testapp/android && ./gradlew assembleDebug 24 | cd tests/testapp/ios/App && xcodebuild -workspace App.xcworkspace -scheme App -configuration Debug -sdk iphonesimulator -derivedDataPath DerivedData/App 25 | 26 | docs: prepare ## Build API documentation. 27 | rm -rf docs 28 | pnpm exec typedoc --entryPoints src --entryPoints src/test.ts --excludePrivate --excludeProtected --readme none --plugin typedoc-plugin-markdown 29 | 30 | test: build testapps ## Run Playwright tests. 31 | pnpm exec playwright test --config tests 32 | 33 | clean: ## Clean all build artifacts (but not dependencies). 34 | rm -rf build test-results 35 | rm -rf tests/testapp/dist 36 | rm -rf tests/testapp/android/{capacitor-cordova-android-plugins,app/{build,src/main/{assets/{capacitor.{config,plugins}.json,public},res/xml/config.xml}}} 37 | rm -rf tests/testapp/ios/{capacitor-cordova-ios-plugins,App/{build,DerivedData,Pods,App/{capacitor.config.json,config.xml,public}}} 38 | 39 | distclean: clean ## Like clean, but also remove all dependencies. 40 | rm -rf node_modules tests/testapp/node_modules tests/testapp/android/.gradle 41 | 42 | commit: prepare ## Commit a change and create a change-log entry for it. 43 | pnpm exec changeset 44 | 45 | release: pristine prepare ## Bump all package versions and generate changelog. 46 | $(MAKE) docs && git add -A docs 47 | pnpm exec changeset version 48 | pnpm install 49 | git commit --amend --reuse-message=HEAD pnpm-lock.yaml 50 | 51 | publish: pristine clean build ## Publish all new packages to NPM. 52 | pnpm publish --access public 53 | GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=tag.gpgSign GIT_CONFIG_VALUE_0=true pnpm exec changeset tag 54 | 55 | pristine: 56 | @[[ -z "$$(git status --porcelain)" ]] || (git status; false) 57 | 58 | .PHONY: help all prepare build testapps docs test clean distclean commit release publish pristine 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Onslip Automation Library 2 | 3 | *Remote-control any old Android or iOS WebView in a Playwright-inspired way* 4 | 5 | [![npm version](https://badge.fury.io/js/%40onslip%2Fautomation.svg)](https://badge.fury.io/js/%40onslip%2Fautomation) 6 | [![Explore changelog](https://img.shields.io/badge/changelog-explore-brightgreen)](https://changelogs.xyz/@onslip/automation) 7 | 8 | ## What it is 9 | 10 | This is a small Node.js library that helps you to E2E test/automate/remote-control Android and iOS WebViews, including 11 | [Capacitor]- or [Cordova]-based hybrid applications. 12 | 13 | The [Onslip Automation API](docs/index/README.md) is heavily inspired by the [Playwright Library] and the aim is to 14 | provide a small but still very usable subset of that API. We strive to be as API compatible as we can for the subset 15 | that is supported, but since this is a completely separate code base, *full* compatibility can never be guaranteed. 16 | 17 | Now, unlike Playwright's Android support — which requires version 87 or greater of the WebView — this library works with 18 | almost *any* version of the WebView, at least all the way down to the last [Crosswalk] release (which was based on 19 | Chromium 53)[^1]. We use it to automate Crosswalk on Android 4.1 and 6.0 devices, the default system WebView in Android 20 | 8 as well as iOS devices running iOS 12.4 and 15.4. 21 | 22 | Additionally, we now also provide [fixtures and matchers](docs/test/README.md) for [Playwright Test](#playwright-test), 23 | enabling integration/E2E testing of hybrid applications too. 24 | 25 | ## How to use it 26 | 27 | First, add this library as a dependency using your favorite package manager: 28 | 29 | ```sh 30 | $ npm install -D @onslip/automation 31 | $ pnpm add -D @onslip/automation 32 | $ yarn add -D @onslip/automation 33 | ``` 34 | 35 | Second, ensure these dependencies are available: 36 | 37 | * Android support requires the [adb] command to be installed and available in the path. 38 | * iOS support needs [ios_webkit_debug_proxy] to be running and listening on port 9221. The iOS device management support 39 | uses 40 | * [ideviceinstaller] to install/uninstall apps; 41 | * [idevicesyslog] to read device logs; and 42 | * [ios_instruments_client] to start and stop iOS processes. 43 | 44 | The first three iOS dependencies can be installed and activated from *Homebrew* with the following commands. 45 | `ios_instruments_client` must be compiled and copied to the path manually. 46 | 47 | ```sh 48 | $ brew install ios-webkit-debug-proxy libimobiledevice ideviceinstaller 49 | $ ios_webkit_debug_proxy 50 | ``` 51 | 52 | Finally, try this small example—or keep reading to see how to integrate with [Playwright Test](#playwright-test). 53 | 54 | ```js 55 | const { Device, AndroidDevice, findWebViewContexts, openWebView, pipeline } = require('@onslip/automation'); 56 | const { createWriteStream } = require('fs'); 57 | const { Readable } = require('stream'); 58 | 59 | const PROXY_PORT = 8885; 60 | 61 | async function main(prog, deviceId) { 62 | const device = await Device.findDevice(deviceId); 63 | 64 | if (!device) { 65 | const devices = await Device.findDevices(); 66 | throw `Usage: ${prog} ${devices.map((d) => d.id).join('|') || ''}`; 67 | } 68 | 69 | console.log(`Checking for debuggable web view on device ${device}`); 70 | const [ webviewId ] = await device.findWebViews(); 71 | 72 | console.log(`Found web view ${webviewId}; opening proxy port ${PROXY_PORT}`); 73 | const options = await device.bindWebView(webviewId, PROXY_PORT); 74 | 75 | console.log(`Looking for contexts`); 76 | const [ context ] = await findWebViewContexts(options); 77 | 78 | console.info(`Opening CDP connection via port ${options.port} to context ${context.id} <${context.url}>`); 79 | const page = await openWebView({...options, ctxId: context.id }); 80 | 81 | console.info(`Starting automation of ${webviewId} on device ${device}`); 82 | page.setDebug(true); 83 | 84 | try { 85 | const lollipop = parseInt(await device.osVersion()) >= 5; 86 | const logLines = device instanceof AndroidDevice 87 | ? await device.collectLogs({ clear: !lollipop, historic: !lollipop, filterspecs: ['*:D'] }) 88 | : await device.collectLogs(); 89 | 90 | const divs = await page.locator('div').count(); 91 | console.log(`There are ${divs} DIV elements in the web view!`); 92 | 93 | await page.locator('body').screenshot({ path: `${deviceId}.png` }); 94 | console.log(`Saved a screenshot to ${deviceId}.png`); 95 | 96 | await pipeline(Readable.from(await logLines()), createWriteStream(`${deviceId}.log`)); 97 | console.log(`Saved device logs to ${deviceId}.log`); 98 | } finally { 99 | await page.close(); 100 | } 101 | } 102 | 103 | main(...process.argv.slice(1)).catch((err) => (console.error(err), 70)).then(process.exit); 104 | ``` 105 | 106 | ## Playwright Test 107 | 108 | [Playwright Test] (or `@playwright/test`) a testing framework that uses the [Playwright Library] for end-to-end testing 109 | of web sites and web applications. Thanks to the [fixtures and matchers](docs/test/README.md) provided by the Onslip 110 | Automation Library, you can now use Playwright Test to test your hybrid applications as well—on real devices or on 111 | emulators. Just import `test` and `expect` from `@onslip/automation/test` instead of `@playwright/test` and you're good 112 | to go. 113 | 114 | ```ts 115 | import { test, expect } from '@onslip/automation/test'; 116 | 117 | test('has title', async ({ webApp }) => { 118 | // Expect a title "to contain" a substring. 119 | await expect(webApp.locator('title')).toHaveText(/Capacitor/); 120 | }); 121 | 122 | test('get started link', async ({ webApp }) => { 123 | // Expect the "get started" button to link to https://capacitorjs.com. 124 | await expect(webApp.locator('.button', { hasText: 'Read more' })).toHaveAttribute('href', 'https://capacitorjs.com'); 125 | }); 126 | ``` 127 | 128 | Please have a look at [the included demo project](tests/) for an example of how to launch an Android emulator, install a 129 | Capacitor hybrid app, and run tests on it. 130 | 131 | [Capacitor]: https://capacitorjs.com/ 132 | [Cordova]: https://cordova.apache.org/ 133 | [Crosswalk]: https://github.com/crosswalk-project 134 | [Playwright Library]: https://playwright.dev/docs/library 135 | [Playwright Test]: https://playwright.dev/docs/intro 136 | 137 | [adb]: https://developer.android.com/studio/command-line/adb 138 | [ios_webkit_debug_proxy]: https://github.com/google/ios-webkit-debug-proxy 139 | [ideviceinstaller]: https://github.com/libimobiledevice/ideviceinstaller 140 | [idevicesyslog]: https://github.com/libimobiledevice/libimobiledevice 141 | [ios_instruments_client]: https://github.com/troybowman/ios_instruments_client 142 | 143 | [^1]: Using our [fork of Capacitor](https://github.com/Onslip/capacitor-android-v16) together with Crosswalk, it's 144 | possible to run (and now automate or test) hybrid applications even on ancient devices running Android 4.1 from 145 | 2012. 146 | -------------------------------------------------------------------------------- /automation-runtime.js: -------------------------------------------------------------------------------- 1 | build/automation-runtime.js -------------------------------------------------------------------------------- /demo.js: -------------------------------------------------------------------------------- 1 | const { Device, AndroidDevice, findWebViewContexts, openWebView, pipeline } = require('.' /* '@onslip/automation' */); 2 | const { createWriteStream } = require('fs'); 3 | const { Readable } = require('stream'); 4 | 5 | const PROXY_PORT = 8885; 6 | 7 | async function main(prog, deviceId) { 8 | const device = await Device.findDevice(deviceId); 9 | 10 | if (!device) { 11 | const devices = await Device.findDevices(); 12 | throw `Usage: ${prog} ${devices.map((d) => d.id).join('|') || ''}`; 13 | } 14 | 15 | console.log(`Checking for debuggable web view on device ${device}`); 16 | const [ webviewId ] = await device.findWebViews(); 17 | 18 | console.log(`Found web view ${webviewId}; opening proxy port ${PROXY_PORT}`); 19 | const options = await device.bindWebView(webviewId, PROXY_PORT); 20 | 21 | console.log(`Looking for contexts`); 22 | const [ context ] = await findWebViewContexts(options); 23 | 24 | console.info(`Opening CDP connection via port ${options.port} to context ${context.id} <${context.url}>`); 25 | const page = await openWebView({...options, ctxId: context.id }); 26 | 27 | console.info(`Starting automation of ${webviewId} on device ${device}`); 28 | page.setDebug(true); 29 | 30 | try { 31 | const lollipop = parseInt(await device.osVersion()) >= 5; 32 | const logLines = device instanceof AndroidDevice 33 | ? await device.collectLogs({ clear: !lollipop, historic: !lollipop, filterspecs: ['*:D'] }) 34 | : await device.collectLogs(); 35 | 36 | const divs = await page.locator('div').count(); 37 | console.log(`There are ${divs} DIV elements in the web view!`); 38 | 39 | await page.locator('body').screenshot({ path: `${deviceId}.png` }); 40 | console.log(`Saved a screenshot to ${deviceId}.png`); 41 | 42 | await pipeline(Readable.from(await logLines()), createWriteStream(`${deviceId}.log`)); 43 | console.log(`Saved device logs to ${deviceId}.log`); 44 | } finally { 45 | await page.close(); 46 | } 47 | } 48 | 49 | main(...process.argv.slice(1)).catch((err) => (console.error(err), 70)).then(process.exit); 50 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | **@onslip/automation** • **Docs** 2 | 3 | *** 4 | 5 | # @onslip/automation 6 | 7 | ## Modules 8 | 9 | - [index](index/README.md) 10 | - [test](test/README.md) 11 | -------------------------------------------------------------------------------- /docs/index/README.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../README.md) / index 6 | 7 | # index 8 | 9 | ## Index 10 | 11 | ### Classes 12 | 13 | - [AndroidDevice](classes/AndroidDevice.md) 14 | - [Device](classes/Device.md) 15 | - [Locator](classes/Locator.md) 16 | - [Mouse](classes/Mouse.md) 17 | - [Page](classes/Page.md) 18 | - [Touchscreen](classes/Touchscreen.md) 19 | - [iOSDevice](classes/iOSDevice.md) 20 | 21 | ### Interfaces 22 | 23 | - [AndroidLogOptions](interfaces/AndroidLogOptions.md) 24 | - [AutomationContext](interfaces/AutomationContext.md) 25 | - [AutomationOptions](interfaces/AutomationOptions.md) 26 | - [DeviceOptions](interfaces/DeviceOptions.md) 27 | - [LocatorOptions](interfaces/LocatorOptions.md) 28 | - [ReaderOptions](interfaces/ReaderOptions.md) 29 | - [ResolvedContextPath](interfaces/ResolvedContextPath.md) 30 | - [SelectorOptions](interfaces/SelectorOptions.md) 31 | - [StartOptions](interfaces/StartOptions.md) 32 | - [iOSLogOptions](interfaces/iOSLogOptions.md) 33 | 34 | ### Functions 35 | 36 | - [collectLines](functions/collectLines.md) 37 | - [execFile](functions/execFile.md) 38 | - [findWebViewContexts](functions/findWebViewContexts.md) 39 | - [mkdir](functions/mkdir.md) 40 | - [openWebView](functions/openWebView.md) 41 | - [pipeline](functions/pipeline.md) 42 | - [readCommandOutput](functions/readCommandOutput.md) 43 | - [resolveWebViewContext](functions/resolveWebViewContext.md) 44 | - [sleep](functions/sleep.md) 45 | - [throwError](functions/throwError.md) 46 | - [writeFile](functions/writeFile.md) 47 | -------------------------------------------------------------------------------- /docs/index/classes/Device.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / Device 6 | 7 | # Class: `abstract` Device 8 | 9 | This class manages Android and iOS devices and applications. 10 | 11 | ## Extended by 12 | 13 | - [`AndroidDevice`](AndroidDevice.md) 14 | - [`iOSDevice`](iOSDevice.md) 15 | 16 | ## Properties 17 | 18 | ### id 19 | 20 | > **id**: `string` 21 | 22 | #### Defined in 23 | 24 | [src/device.ts:86](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L86) 25 | 26 | *** 27 | 28 | ### type 29 | 30 | > **type**: `"android"` \| `"ios"` 31 | 32 | #### Defined in 33 | 34 | [src/device.ts:86](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L86) 35 | 36 | ## Methods 37 | 38 | ### bindWebView() 39 | 40 | > `abstract` **bindWebView**(`webviewId`, `port`): `Promise`\<[`AutomationOptions`](../interfaces/AutomationOptions.md)\> 41 | 42 | Binds a web view to the specified port on `localhost`. 43 | 44 | For additional information, see the subclass documentation of this method. 45 | 46 | #### Parameters 47 | 48 | • **webviewId**: `string` 49 | 50 | The web view identifier to bind. 51 | 52 | • **port**: `number` 53 | 54 | The port to bind the web view to. 55 | 56 | #### Returns 57 | 58 | `Promise`\<[`AutomationOptions`](../interfaces/AutomationOptions.md)\> 59 | 60 | Options suitable to pass to [findWebViewContexts](../functions/findWebViewContexts.md) or [openWebView](../functions/openWebView.md). 61 | 62 | #### Defined in 63 | 64 | [src/device.ts:180](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L180) 65 | 66 | *** 67 | 68 | ### collectLogs() 69 | 70 | > `abstract` **collectLogs**(`options`?): `Promise`\<() => `Promise`\<`string`[]\>\> 71 | 72 | Begins collecting and buffering logs from the device. When the returned function is called, all lines are 73 | returned as an array. 74 | 75 | By default, this method adds a LF to each collected line, making the array suitable to be dumped to disk as-is. 76 | 77 | #### Parameters 78 | 79 | • **options?**: [`ReaderOptions`](../interfaces/ReaderOptions.md) 80 | 81 | Reader options. For device-specific options, see the subclass method. 82 | 83 | #### Returns 84 | 85 | `Promise`\<() => `Promise`\<`string`[]\>\> 86 | 87 | A function that, when invoked, stops logging and returns all collected lines. 88 | 89 | #### Defined in 90 | 91 | [src/device.ts:160](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L160) 92 | 93 | *** 94 | 95 | ### deviceName() 96 | 97 | > `abstract` **deviceName**(): `Promise`\<`string`\> 98 | 99 | Returns the name of the device. 100 | 101 | #### Returns 102 | 103 | `Promise`\<`string`\> 104 | 105 | The device name. 106 | 107 | #### Defined in 108 | 109 | [src/device.ts:101](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L101) 110 | 111 | *** 112 | 113 | ### findWebViews() 114 | 115 | > `abstract` **findWebViews**(): `Promise`\<`string`[]\> 116 | 117 | Finds all debuggable web views on the device. 118 | 119 | For additional information, see the subclass documentation of this method. 120 | 121 | #### Returns 122 | 123 | `Promise`\<`string`[]\> 124 | 125 | An array of all debuggable web view identifiers. 126 | 127 | #### Defined in 128 | 129 | [src/device.ts:169](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L169) 130 | 131 | *** 132 | 133 | ### install() 134 | 135 | > `abstract` **install**(`archive`, `options`?): `Promise`\<`void`\> 136 | 137 | Installs an application onto the device. 138 | 139 | #### Parameters 140 | 141 | • **archive**: `string` 142 | 143 | The path to the application to install (APK/IPA/directory). 144 | 145 | • **options?**: `string`[] 146 | 147 | Optional installation options, if the subclass supports it. 148 | 149 | #### Returns 150 | 151 | `Promise`\<`void`\> 152 | 153 | #### Defined in 154 | 155 | [src/device.ts:109](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L109) 156 | 157 | *** 158 | 159 | ### osVersion() 160 | 161 | > `abstract` **osVersion**(): `Promise`\<`string`\> 162 | 163 | Returns the Android/iOS version number. 164 | 165 | #### Returns 166 | 167 | `Promise`\<`string`\> 168 | 169 | The version number. 170 | 171 | #### Defined in 172 | 173 | [src/device.ts:94](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L94) 174 | 175 | *** 176 | 177 | ### readLogs() 178 | 179 | #### readLogs(options) 180 | 181 | > `abstract` **readLogs**(`options`?): `AsyncGenerator`\<`string`, `any`, `unknown`\> 182 | 183 | Reads log lines from the device. 184 | 185 | ##### Parameters 186 | 187 | • **options?**: [`ReaderOptions`](../interfaces/ReaderOptions.md) 188 | 189 | Reader options. For device-specific options, see the subclass method. 190 | 191 | ##### Returns 192 | 193 | `AsyncGenerator`\<`string`, `any`, `unknown`\> 194 | 195 | An async iterator generating one line at a time. 196 | 197 | ##### Defined in 198 | 199 | [src/device.ts:139](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L139) 200 | 201 | #### readLogs(options, timeout) 202 | 203 | > `abstract` **readLogs**(`options`?, `timeout`?): `AsyncGenerator`\<`undefined` \| `string`, `any`, `unknown`\> 204 | 205 | Reads log lines from the device, with heartbeats. 206 | 207 | ##### Parameters 208 | 209 | • **options?**: [`ReaderOptions`](../interfaces/ReaderOptions.md) 210 | 211 | Reader options. For device-specific options, see the subclass method. 212 | 213 | • **timeout?**: `number` 214 | 215 | The timeout, in milliseconds. If no lines has been produced within this time, an `undefined` 216 | value is generated instead of a string. 217 | 218 | ##### Returns 219 | 220 | `AsyncGenerator`\<`undefined` \| `string`, `any`, `unknown`\> 221 | 222 | An async iterator generating one line at a time, or `undefined` on timeouts. 223 | 224 | ##### Defined in 225 | 226 | [src/device.ts:149](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L149) 227 | 228 | *** 229 | 230 | ### start() 231 | 232 | > `abstract` **start**(`app`, `options`?): `Promise`\<`void`\> 233 | 234 | Launches an application/activity on the device. 235 | 236 | #### Parameters 237 | 238 | • **app**: `string` 239 | 240 | The package/activity identifier or application bundle identifier to launch. 241 | 242 | • **options?**: [`StartOptions`](../interfaces/StartOptions.md) 243 | 244 | Optional start options. 245 | 246 | #### Returns 247 | 248 | `Promise`\<`void`\> 249 | 250 | #### Defined in 251 | 252 | [src/device.ts:117](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L117) 253 | 254 | *** 255 | 256 | ### stop() 257 | 258 | > `abstract` **stop**(`app`): `Promise`\<`void`\> 259 | 260 | Kills an application on the device. 261 | 262 | #### Parameters 263 | 264 | • **app**: `string` 265 | 266 | The package/activity identifier or application bundle identifier to stop. 267 | 268 | #### Returns 269 | 270 | `Promise`\<`void`\> 271 | 272 | #### Defined in 273 | 274 | [src/device.ts:124](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L124) 275 | 276 | *** 277 | 278 | ### uninstall() 279 | 280 | > `abstract` **uninstall**(`app`): `Promise`\<`void`\> 281 | 282 | Uninstalls an application from the device. 283 | 284 | #### Parameters 285 | 286 | • **app**: `string` 287 | 288 | The package/bundle identifier to uninstall. 289 | 290 | #### Returns 291 | 292 | `Promise`\<`void`\> 293 | 294 | #### Defined in 295 | 296 | [src/device.ts:131](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L131) 297 | 298 | *** 299 | 300 | ### findDevice() 301 | 302 | > `static` **findDevice**(`deviceId`, `options`?, `timeout`?): `Promise`\<`undefined` \| [`Device`](Device.md)\> 303 | 304 | Finds a single device, given a device ID. 305 | 306 | #### Parameters 307 | 308 | • **deviceId**: `string` 309 | 310 | The device ID to find. 311 | 312 | • **options?**: [`DeviceOptions`](../interfaces/DeviceOptions.md) 313 | 314 | Device manager options. 315 | 316 | • **timeout?**: `number` 317 | 318 | If specified, the method will wait for the device to appear this many milliseconds (0 means 319 | forever). 320 | 321 | #### Returns 322 | 323 | `Promise`\<`undefined` \| [`Device`](Device.md)\> 324 | 325 | The device, if found, else `undefined`. 326 | 327 | #### Defined in 328 | 329 | [src/device.ts:56](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L56) 330 | 331 | *** 332 | 333 | ### findDevices() 334 | 335 | > `static` **findDevices**(`options`?): `Promise`\<[`Device`](Device.md)[]\> 336 | 337 | Finds all connected Android and iOS devices. 338 | 339 | #### Parameters 340 | 341 | • **options?**: [`DeviceOptions`](../interfaces/DeviceOptions.md) 342 | 343 | Device manager options. 344 | 345 | #### Returns 346 | 347 | `Promise`\<[`Device`](Device.md)[]\> 348 | 349 | A list of detected devices. 350 | 351 | #### Defined in 352 | 353 | [src/device.ts:76](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L76) 354 | -------------------------------------------------------------------------------- /docs/index/classes/Mouse.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / Mouse 6 | 7 | # Class: Mouse 8 | 9 | ## Methods 10 | 11 | ### click() 12 | 13 | > **click**(`x`, `y`): `Promise`\<`void`\> 14 | 15 | #### Parameters 16 | 17 | • **x**: `number` 18 | 19 | • **y**: `number` 20 | 21 | #### Returns 22 | 23 | `Promise`\<`void`\> 24 | 25 | #### Defined in 26 | 27 | [src/api.ts:215](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L215) 28 | -------------------------------------------------------------------------------- /docs/index/classes/Page.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / Page 6 | 7 | # Class: Page 8 | 9 | The Page object represents the connection to a remote web view. 10 | 11 | ## Properties 12 | 13 | ### mouse 14 | 15 | > `readonly` **mouse**: [`Mouse`](Mouse.md) 16 | 17 | A reference to Mouse instance. 18 | 19 | #### Defined in 20 | 21 | [src/api.ts:145](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L145) 22 | 23 | *** 24 | 25 | ### touchscreen 26 | 27 | > `readonly` **touchscreen**: [`Touchscreen`](Touchscreen.md) 28 | 29 | A reference to Touchscreen instance. 30 | 31 | #### Defined in 32 | 33 | [src/api.ts:148](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L148) 34 | 35 | ## Methods 36 | 37 | ### close() 38 | 39 | > **close**(): `Promise`\<`void`\> 40 | 41 | Closes the connection to the web view and deallocates all held resources. 42 | 43 | #### Returns 44 | 45 | `Promise`\<`void`\> 46 | 47 | #### Defined in 48 | 49 | [src/api.ts:202](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L202) 50 | 51 | *** 52 | 53 | ### evaluate() 54 | 55 | > **evaluate**(`pageFunction`, `arg`?): `Promise`\<`unknown`\> 56 | 57 | Invokes a custom JavaScript function inside the web view context. 58 | 59 | #### Parameters 60 | 61 | • **pageFunction**: `string` \| `Function` 62 | 63 | A function to call inside the web view context. 64 | 65 | • **arg?**: `unknown` 66 | 67 | An optional argument to pass to the function. Must be JSON serializable. 68 | 69 | #### Returns 70 | 71 | `Promise`\<`unknown`\> 72 | 73 | The value returned from the function. Must be JSON serializable. 74 | 75 | #### Defined in 76 | 77 | [src/api.ts:177](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L177) 78 | 79 | *** 80 | 81 | ### locator() 82 | 83 | > **locator**(`selector`, `options`?): [`Locator`](Locator.md) 84 | 85 | Creates and returns a new Locator. 86 | 87 | #### Parameters 88 | 89 | • **selector**: `string` 90 | 91 | The selectors to match. 92 | 93 | • **options?**: [`LocatorOptions`](../interfaces/LocatorOptions.md) 94 | 95 | Additional options. 96 | 97 | #### Returns 98 | 99 | [`Locator`](Locator.md) 100 | 101 | A new Locator. 102 | 103 | #### Defined in 104 | 105 | [src/api.ts:166](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L166) 106 | 107 | *** 108 | 109 | ### setDebug() 110 | 111 | > **setDebug**(`debug`): `void` 112 | 113 | Enables to disables debug output from this library. 114 | 115 | #### Parameters 116 | 117 | • **debug**: `null` \| `boolean` \| `Partial`\<`Console`\> 118 | 119 | Use this `Console` for debugging, or set to `true` to use `console` and `false`/`null` to disable, 120 | 121 | #### Returns 122 | 123 | `void` 124 | 125 | #### Defined in 126 | 127 | [src/api.ts:186](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L186) 128 | 129 | *** 130 | 131 | ### setDefaultTimeout() 132 | 133 | > **setDefaultTimeout**(`timeout`): `void` 134 | 135 | Specifies the default timeout when waiting for Locators to be actionable. 136 | 137 | #### Parameters 138 | 139 | • **timeout**: `number` 140 | 141 | The new default timeout, in milliseconds. 142 | 143 | #### Returns 144 | 145 | `void` 146 | 147 | #### Defined in 148 | 149 | [src/api.ts:195](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L195) 150 | -------------------------------------------------------------------------------- /docs/index/classes/Touchscreen.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / Touchscreen 6 | 7 | # Class: Touchscreen 8 | 9 | ## Methods 10 | 11 | ### tap() 12 | 13 | > **tap**(`x`, `y`): `Promise`\<`void`\> 14 | 15 | #### Parameters 16 | 17 | • **x**: `number` 18 | 19 | • **y**: `number` 20 | 21 | #### Returns 22 | 23 | `Promise`\<`void`\> 24 | 25 | #### Defined in 26 | 27 | [src/api.ts:228](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L228) 28 | -------------------------------------------------------------------------------- /docs/index/functions/collectLines.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / collectLines 6 | 7 | # Function: collectLines() 8 | 9 | > **collectLines**(`stream`): () => `Promise`\<`string`[]\> 10 | 11 | Begins collecting and buffering lines from an async iterator, like the one returned by [readCommandOutput](readCommandOutput.md). 12 | When the returned function is called, all lines are returned as an array. 13 | 14 | ## Parameters 15 | 16 | • **stream** 17 | 18 | A callback that should create the async iterator and stop generating lines when the provided signal 19 | becomes true. 20 | 21 | ## Returns 22 | 23 | `Function` 24 | 25 | A function that, when invoked, stops reading and returns all collected lines as an array. 26 | 27 | ### Returns 28 | 29 | `Promise`\<`string`[]\> 30 | 31 | ## Defined in 32 | 33 | [src/utils.ts:119](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L119) 34 | -------------------------------------------------------------------------------- /docs/index/functions/execFile.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / execFile 6 | 7 | # Function: execFile() 8 | 9 | ## execFile(file) 10 | 11 | > **execFile**(`file`): `PromiseWithChild`\<`object`\> 12 | 13 | ### Parameters 14 | 15 | • **file**: `string` 16 | 17 | ### Returns 18 | 19 | `PromiseWithChild`\<`object`\> 20 | 21 | #### stderr 22 | 23 | > **stderr**: `string` 24 | 25 | #### stdout 26 | 27 | > **stdout**: `string` 28 | 29 | ### Defined in 30 | 31 | [src/utils.ts:7](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L7) 32 | 33 | ## execFile(file, args) 34 | 35 | > **execFile**(`file`, `args`): `PromiseWithChild`\<`object`\> 36 | 37 | ### Parameters 38 | 39 | • **file**: `string` 40 | 41 | • **args**: `undefined` \| `null` \| readonly `string`[] 42 | 43 | ### Returns 44 | 45 | `PromiseWithChild`\<`object`\> 46 | 47 | #### stderr 48 | 49 | > **stderr**: `string` 50 | 51 | #### stdout 52 | 53 | > **stdout**: `string` 54 | 55 | ### Defined in 56 | 57 | [src/utils.ts:7](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L7) 58 | 59 | ## execFile(file, options) 60 | 61 | > **execFile**(`file`, `options`): `PromiseWithChild`\<`object`\> 62 | 63 | ### Parameters 64 | 65 | • **file**: `string` 66 | 67 | • **options**: `ExecFileOptionsWithBufferEncoding` 68 | 69 | ### Returns 70 | 71 | `PromiseWithChild`\<`object`\> 72 | 73 | #### stderr 74 | 75 | > **stderr**: `Buffer` 76 | 77 | #### stdout 78 | 79 | > **stdout**: `Buffer` 80 | 81 | ### Defined in 82 | 83 | [src/utils.ts:7](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L7) 84 | 85 | ## execFile(file, args, options) 86 | 87 | > **execFile**(`file`, `args`, `options`): `PromiseWithChild`\<`object`\> 88 | 89 | ### Parameters 90 | 91 | • **file**: `string` 92 | 93 | • **args**: `undefined` \| `null` \| readonly `string`[] 94 | 95 | • **options**: `ExecFileOptionsWithBufferEncoding` 96 | 97 | ### Returns 98 | 99 | `PromiseWithChild`\<`object`\> 100 | 101 | #### stderr 102 | 103 | > **stderr**: `Buffer` 104 | 105 | #### stdout 106 | 107 | > **stdout**: `Buffer` 108 | 109 | ### Defined in 110 | 111 | [src/utils.ts:7](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L7) 112 | 113 | ## execFile(file, options) 114 | 115 | > **execFile**(`file`, `options`): `PromiseWithChild`\<`object`\> 116 | 117 | ### Parameters 118 | 119 | • **file**: `string` 120 | 121 | • **options**: `ExecFileOptionsWithStringEncoding` 122 | 123 | ### Returns 124 | 125 | `PromiseWithChild`\<`object`\> 126 | 127 | #### stderr 128 | 129 | > **stderr**: `string` 130 | 131 | #### stdout 132 | 133 | > **stdout**: `string` 134 | 135 | ### Defined in 136 | 137 | [src/utils.ts:7](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L7) 138 | 139 | ## execFile(file, args, options) 140 | 141 | > **execFile**(`file`, `args`, `options`): `PromiseWithChild`\<`object`\> 142 | 143 | ### Parameters 144 | 145 | • **file**: `string` 146 | 147 | • **args**: `undefined` \| `null` \| readonly `string`[] 148 | 149 | • **options**: `ExecFileOptionsWithStringEncoding` 150 | 151 | ### Returns 152 | 153 | `PromiseWithChild`\<`object`\> 154 | 155 | #### stderr 156 | 157 | > **stderr**: `string` 158 | 159 | #### stdout 160 | 161 | > **stdout**: `string` 162 | 163 | ### Defined in 164 | 165 | [src/utils.ts:7](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L7) 166 | 167 | ## execFile(file, options) 168 | 169 | > **execFile**(`file`, `options`): `PromiseWithChild`\<`object`\> 170 | 171 | ### Parameters 172 | 173 | • **file**: `string` 174 | 175 | • **options**: `ExecFileOptionsWithOtherEncoding` 176 | 177 | ### Returns 178 | 179 | `PromiseWithChild`\<`object`\> 180 | 181 | #### stderr 182 | 183 | > **stderr**: `string` \| `Buffer` 184 | 185 | #### stdout 186 | 187 | > **stdout**: `string` \| `Buffer` 188 | 189 | ### Defined in 190 | 191 | [src/utils.ts:7](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L7) 192 | 193 | ## execFile(file, args, options) 194 | 195 | > **execFile**(`file`, `args`, `options`): `PromiseWithChild`\<`object`\> 196 | 197 | ### Parameters 198 | 199 | • **file**: `string` 200 | 201 | • **args**: `undefined` \| `null` \| readonly `string`[] 202 | 203 | • **options**: `ExecFileOptionsWithOtherEncoding` 204 | 205 | ### Returns 206 | 207 | `PromiseWithChild`\<`object`\> 208 | 209 | #### stderr 210 | 211 | > **stderr**: `string` \| `Buffer` 212 | 213 | #### stdout 214 | 215 | > **stdout**: `string` \| `Buffer` 216 | 217 | ### Defined in 218 | 219 | [src/utils.ts:7](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L7) 220 | 221 | ## execFile(file, options) 222 | 223 | > **execFile**(`file`, `options`): `PromiseWithChild`\<`object`\> 224 | 225 | ### Parameters 226 | 227 | • **file**: `string` 228 | 229 | • **options**: `ExecFileOptions` 230 | 231 | ### Returns 232 | 233 | `PromiseWithChild`\<`object`\> 234 | 235 | #### stderr 236 | 237 | > **stderr**: `string` 238 | 239 | #### stdout 240 | 241 | > **stdout**: `string` 242 | 243 | ### Defined in 244 | 245 | [src/utils.ts:7](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L7) 246 | 247 | ## execFile(file, args, options) 248 | 249 | > **execFile**(`file`, `args`, `options`): `PromiseWithChild`\<`object`\> 250 | 251 | ### Parameters 252 | 253 | • **file**: `string` 254 | 255 | • **args**: `undefined` \| `null` \| readonly `string`[] 256 | 257 | • **options**: `ExecFileOptions` 258 | 259 | ### Returns 260 | 261 | `PromiseWithChild`\<`object`\> 262 | 263 | #### stderr 264 | 265 | > **stderr**: `string` 266 | 267 | #### stdout 268 | 269 | > **stdout**: `string` 270 | 271 | ### Defined in 272 | 273 | [src/utils.ts:7](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L7) 274 | 275 | ## execFile(file, options) 276 | 277 | > **execFile**(`file`, `options`): `PromiseWithChild`\<`object`\> 278 | 279 | ### Parameters 280 | 281 | • **file**: `string` 282 | 283 | • **options**: `undefined` \| `null` \| `ObjectEncodingOptions` & `ExecFileOptions` 284 | 285 | ### Returns 286 | 287 | `PromiseWithChild`\<`object`\> 288 | 289 | #### stderr 290 | 291 | > **stderr**: `string` \| `Buffer` 292 | 293 | #### stdout 294 | 295 | > **stdout**: `string` \| `Buffer` 296 | 297 | ### Defined in 298 | 299 | [src/utils.ts:7](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L7) 300 | 301 | ## execFile(file, args, options) 302 | 303 | > **execFile**(`file`, `args`, `options`): `PromiseWithChild`\<`object`\> 304 | 305 | ### Parameters 306 | 307 | • **file**: `string` 308 | 309 | • **args**: `undefined` \| `null` \| readonly `string`[] 310 | 311 | • **options**: `undefined` \| `null` \| `ObjectEncodingOptions` & `ExecFileOptions` 312 | 313 | ### Returns 314 | 315 | `PromiseWithChild`\<`object`\> 316 | 317 | #### stderr 318 | 319 | > **stderr**: `string` \| `Buffer` 320 | 321 | #### stdout 322 | 323 | > **stdout**: `string` \| `Buffer` 324 | 325 | ### Defined in 326 | 327 | [src/utils.ts:7](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L7) 328 | -------------------------------------------------------------------------------- /docs/index/functions/findWebViewContexts.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / findWebViewContexts 6 | 7 | # Function: findWebViewContexts() 8 | 9 | > **findWebViewContexts**(`options`): `Promise`\<[`AutomationContext`](../interfaces/AutomationContext.md)[]\> 10 | 11 | Finds and returns a description of all matching web contexts. 12 | 13 | Useful to find out what [AutomationOptions.ctxId](../interfaces/AutomationOptions.md#ctxid) value to specify when calling [openWebView](openWebView.md). 14 | 15 | ## Parameters 16 | 17 | • **options**: [`AutomationOptions`](../interfaces/AutomationOptions.md) 18 | 19 | Where to look for contexts. 20 | 21 | ## Returns 22 | 23 | `Promise`\<[`AutomationContext`](../interfaces/AutomationContext.md)[]\> 24 | 25 | A list of matching contexts. 26 | 27 | ## Defined in 28 | 29 | [src/api.ts:124](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L124) 30 | -------------------------------------------------------------------------------- /docs/index/functions/mkdir.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / mkdir 6 | 7 | # Function: mkdir() 8 | 9 | ## mkdir(path, options) 10 | 11 | > **mkdir**(`path`, `options`): `Promise`\<`string` \| `undefined`\> 12 | 13 | Asynchronous mkdir(2) - create a directory. 14 | 15 | ### Parameters 16 | 17 | • **path**: `PathLike` 18 | 19 | A path to a file. If a URL is provided, it must use the `file:` protocol. 20 | 21 | • **options**: `MakeDirectoryOptions` & `object` 22 | 23 | Either the file mode, or an object optionally specifying the file mode and whether parent folders 24 | should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. 25 | 26 | ### Returns 27 | 28 | `Promise`\<`string` \| `undefined`\> 29 | 30 | ### Defined in 31 | 32 | [src/utils.ts:8](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L8) 33 | 34 | ## mkdir(path, options) 35 | 36 | > **mkdir**(`path`, `options`?): `Promise`\<`void`\> 37 | 38 | Asynchronous mkdir(2) - create a directory. 39 | 40 | ### Parameters 41 | 42 | • **path**: `PathLike` 43 | 44 | A path to a file. If a URL is provided, it must use the `file:` protocol. 45 | 46 | • **options?**: `null` \| `Mode` \| `MakeDirectoryOptions` & `object` 47 | 48 | Either the file mode, or an object optionally specifying the file mode and whether parent folders 49 | should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. 50 | 51 | ### Returns 52 | 53 | `Promise`\<`void`\> 54 | 55 | ### Defined in 56 | 57 | [src/utils.ts:8](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L8) 58 | 59 | ## mkdir(path, options) 60 | 61 | > **mkdir**(`path`, `options`?): `Promise`\<`string` \| `undefined`\> 62 | 63 | Asynchronous mkdir(2) - create a directory. 64 | 65 | ### Parameters 66 | 67 | • **path**: `PathLike` 68 | 69 | A path to a file. If a URL is provided, it must use the `file:` protocol. 70 | 71 | • **options?**: `null` \| `Mode` \| `MakeDirectoryOptions` 72 | 73 | Either the file mode, or an object optionally specifying the file mode and whether parent folders 74 | should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`. 75 | 76 | ### Returns 77 | 78 | `Promise`\<`string` \| `undefined`\> 79 | 80 | ### Defined in 81 | 82 | [src/utils.ts:8](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L8) 83 | -------------------------------------------------------------------------------- /docs/index/functions/openWebView.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / openWebView 6 | 7 | # Function: openWebView() 8 | 9 | > **openWebView**(`options`): `Promise`\<[`Page`](../classes/Page.md)\> 10 | 11 | Connects to a web context and return a Page. 12 | 13 | ## Parameters 14 | 15 | • **options**: [`AutomationOptions`](../interfaces/AutomationOptions.md) 16 | 17 | Specify what context to use. 18 | 19 | ## Returns 20 | 21 | `Promise`\<[`Page`](../classes/Page.md)\> 22 | 23 | A new [Page](../classes/Page.md) object which can be used to interact with the web page. 24 | 25 | ## Defined in 26 | 27 | [src/api.ts:134](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L134) 28 | -------------------------------------------------------------------------------- /docs/index/functions/pipeline.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / pipeline 6 | 7 | # Function: pipeline() 8 | 9 | ## pipeline(source, destination, options) 10 | 11 | > **pipeline**\<`A`, `B`\>(`source`, `destination`, `options`?): `PipelinePromise`\<`B`\> 12 | 13 | ### Type Parameters 14 | 15 | • **A** *extends* `PipelineSource`\<`any`\> 16 | 17 | • **B** *extends* `WritableStream` \| `PipelineDestinationIterableFunction`\<`string` \| `Buffer`\> \| `PipelineDestinationPromiseFunction`\<`string` \| `Buffer`, `any`\> \| `PipelineDestinationIterableFunction`\<`any`\> \| `PipelineDestinationPromiseFunction`\<`any`, `any`\> 18 | 19 | ### Parameters 20 | 21 | • **source**: `A` 22 | 23 | • **destination**: `B` 24 | 25 | • **options?**: `PipelineOptions` 26 | 27 | ### Returns 28 | 29 | `PipelinePromise`\<`B`\> 30 | 31 | ### Defined in 32 | 33 | [src/utils.ts:9](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L9) 34 | 35 | ## pipeline(source, transform1, destination, options) 36 | 37 | > **pipeline**\<`A`, `T1`, `B`\>(`source`, `transform1`, `destination`, `options`?): `PipelinePromise`\<`B`\> 38 | 39 | ### Type Parameters 40 | 41 | • **A** *extends* `PipelineSource`\<`any`\> 42 | 43 | • **T1** *extends* `PipelineTransform`\<`A`, `any`\> 44 | 45 | • **B** *extends* `WritableStream` \| `PipelineDestinationIterableFunction`\<`string` \| `Buffer`\> \| `PipelineDestinationPromiseFunction`\<`string` \| `Buffer`, `any`\> \| `PipelineDestinationIterableFunction`\<`any`\> \| `PipelineDestinationPromiseFunction`\<`any`, `any`\> 46 | 47 | ### Parameters 48 | 49 | • **source**: `A` 50 | 51 | • **transform1**: `T1` 52 | 53 | • **destination**: `B` 54 | 55 | • **options?**: `PipelineOptions` 56 | 57 | ### Returns 58 | 59 | `PipelinePromise`\<`B`\> 60 | 61 | ### Defined in 62 | 63 | [src/utils.ts:9](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L9) 64 | 65 | ## pipeline(source, transform1, transform2, destination, options) 66 | 67 | > **pipeline**\<`A`, `T1`, `T2`, `B`\>(`source`, `transform1`, `transform2`, `destination`, `options`?): `PipelinePromise`\<`B`\> 68 | 69 | ### Type Parameters 70 | 71 | • **A** *extends* `PipelineSource`\<`any`\> 72 | 73 | • **T1** *extends* `PipelineTransform`\<`A`, `any`\> 74 | 75 | • **T2** *extends* `PipelineTransform`\<`T1`, `any`\> 76 | 77 | • **B** *extends* `WritableStream` \| `PipelineDestinationIterableFunction`\<`string` \| `Buffer`\> \| `PipelineDestinationPromiseFunction`\<`string` \| `Buffer`, `any`\> \| `PipelineDestinationIterableFunction`\<`any`\> \| `PipelineDestinationPromiseFunction`\<`any`, `any`\> 78 | 79 | ### Parameters 80 | 81 | • **source**: `A` 82 | 83 | • **transform1**: `T1` 84 | 85 | • **transform2**: `T2` 86 | 87 | • **destination**: `B` 88 | 89 | • **options?**: `PipelineOptions` 90 | 91 | ### Returns 92 | 93 | `PipelinePromise`\<`B`\> 94 | 95 | ### Defined in 96 | 97 | [src/utils.ts:9](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L9) 98 | 99 | ## pipeline(source, transform1, transform2, transform3, destination, options) 100 | 101 | > **pipeline**\<`A`, `T1`, `T2`, `T3`, `B`\>(`source`, `transform1`, `transform2`, `transform3`, `destination`, `options`?): `PipelinePromise`\<`B`\> 102 | 103 | ### Type Parameters 104 | 105 | • **A** *extends* `PipelineSource`\<`any`\> 106 | 107 | • **T1** *extends* `PipelineTransform`\<`A`, `any`\> 108 | 109 | • **T2** *extends* `PipelineTransform`\<`T1`, `any`\> 110 | 111 | • **T3** *extends* `PipelineTransform`\<`T2`, `any`\> 112 | 113 | • **B** *extends* `WritableStream` \| `PipelineDestinationIterableFunction`\<`string` \| `Buffer`\> \| `PipelineDestinationPromiseFunction`\<`string` \| `Buffer`, `any`\> \| `PipelineDestinationIterableFunction`\<`any`\> \| `PipelineDestinationPromiseFunction`\<`any`, `any`\> 114 | 115 | ### Parameters 116 | 117 | • **source**: `A` 118 | 119 | • **transform1**: `T1` 120 | 121 | • **transform2**: `T2` 122 | 123 | • **transform3**: `T3` 124 | 125 | • **destination**: `B` 126 | 127 | • **options?**: `PipelineOptions` 128 | 129 | ### Returns 130 | 131 | `PipelinePromise`\<`B`\> 132 | 133 | ### Defined in 134 | 135 | [src/utils.ts:9](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L9) 136 | 137 | ## pipeline(source, transform1, transform2, transform3, transform4, destination, options) 138 | 139 | > **pipeline**\<`A`, `T1`, `T2`, `T3`, `T4`, `B`\>(`source`, `transform1`, `transform2`, `transform3`, `transform4`, `destination`, `options`?): `PipelinePromise`\<`B`\> 140 | 141 | ### Type Parameters 142 | 143 | • **A** *extends* `PipelineSource`\<`any`\> 144 | 145 | • **T1** *extends* `PipelineTransform`\<`A`, `any`\> 146 | 147 | • **T2** *extends* `PipelineTransform`\<`T1`, `any`\> 148 | 149 | • **T3** *extends* `PipelineTransform`\<`T2`, `any`\> 150 | 151 | • **T4** *extends* `PipelineTransform`\<`T3`, `any`\> 152 | 153 | • **B** *extends* `WritableStream` \| `PipelineDestinationIterableFunction`\<`string` \| `Buffer`\> \| `PipelineDestinationPromiseFunction`\<`string` \| `Buffer`, `any`\> \| `PipelineDestinationIterableFunction`\<`any`\> \| `PipelineDestinationPromiseFunction`\<`any`, `any`\> 154 | 155 | ### Parameters 156 | 157 | • **source**: `A` 158 | 159 | • **transform1**: `T1` 160 | 161 | • **transform2**: `T2` 162 | 163 | • **transform3**: `T3` 164 | 165 | • **transform4**: `T4` 166 | 167 | • **destination**: `B` 168 | 169 | • **options?**: `PipelineOptions` 170 | 171 | ### Returns 172 | 173 | `PipelinePromise`\<`B`\> 174 | 175 | ### Defined in 176 | 177 | [src/utils.ts:9](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L9) 178 | 179 | ## pipeline(streams, options) 180 | 181 | > **pipeline**(`streams`, `options`?): `Promise`\<`void`\> 182 | 183 | ### Parameters 184 | 185 | • **streams**: readonly (`ReadableStream` \| `WritableStream` \| `ReadWriteStream`)[] 186 | 187 | • **options?**: `PipelineOptions` 188 | 189 | ### Returns 190 | 191 | `Promise`\<`void`\> 192 | 193 | ### Defined in 194 | 195 | [src/utils.ts:9](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L9) 196 | 197 | ## pipeline(stream1, stream2, streams) 198 | 199 | > **pipeline**(`stream1`, `stream2`, ...`streams`): `Promise`\<`void`\> 200 | 201 | ### Parameters 202 | 203 | • **stream1**: `ReadableStream` 204 | 205 | • **stream2**: `WritableStream` \| `ReadWriteStream` 206 | 207 | • ...**streams**: (`WritableStream` \| `ReadWriteStream` \| `PipelineOptions`)[] 208 | 209 | ### Returns 210 | 211 | `Promise`\<`void`\> 212 | 213 | ### Defined in 214 | 215 | [src/utils.ts:9](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L9) 216 | -------------------------------------------------------------------------------- /docs/index/functions/readCommandOutput.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / readCommandOutput 6 | 7 | # Function: readCommandOutput() 8 | 9 | ## readCommandOutput(command, args, options) 10 | 11 | > **readCommandOutput**(`command`, `args`, `options`?): `AsyncGenerator`\<`string`\> 12 | 13 | Spawns a command and reads its standard output line by line. 14 | 15 | ### Parameters 16 | 17 | • **command**: `string` 18 | 19 | The command to executed. 20 | 21 | • **args**: `string`[] 22 | 23 | Command arguments. 24 | 25 | • **options?**: [`ReaderOptions`](../interfaces/ReaderOptions.md) 26 | 27 | Reader options. 28 | 29 | ### Returns 30 | 31 | `AsyncGenerator`\<`string`\> 32 | 33 | An async iterator generating one line at a time. 34 | 35 | ### Defined in 36 | 37 | [src/utils.ts:47](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L47) 38 | 39 | ## readCommandOutput(command, args, options, timeout) 40 | 41 | > **readCommandOutput**(`command`, `args`, `options`?, `timeout`?): `AsyncGenerator`\<`string` \| `undefined`\> 42 | 43 | Spawns a command and reads its standard output line by line, with heartbeats. 44 | 45 | ### Parameters 46 | 47 | • **command**: `string` 48 | 49 | The command to executed. 50 | 51 | • **args**: `string`[] 52 | 53 | Command arguments. 54 | 55 | • **options?**: [`ReaderOptions`](../interfaces/ReaderOptions.md) 56 | 57 | Reader options. 58 | 59 | • **timeout?**: `number` 60 | 61 | The timeout, in milliseconds. If no lines has been produced within this time, an `undefined` value is 62 | generated instead of a string. 63 | 64 | ### Returns 65 | 66 | `AsyncGenerator`\<`string` \| `undefined`\> 67 | 68 | An async iterator generating one line at a time, or `undefined` on timeouts. 69 | 70 | ### Defined in 71 | 72 | [src/utils.ts:59](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L59) 73 | -------------------------------------------------------------------------------- /docs/index/functions/resolveWebViewContext.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / resolveWebViewContext 6 | 7 | # Function: resolveWebViewContext() 8 | 9 | > **resolveWebViewContext**(`contextPath`, `port`, `deviceOptions`?, `timeout`?): `Promise`\<[`ResolvedContextPath`](../interfaces/ResolvedContextPath.md)\> 10 | 11 | Binds a device's web view to a local port and then locates one of its contexts, based on a context path. 12 | 13 | The context path is a string that uniquely identifies the device, web view and context, using the following format: 14 | `[/[/]]`. The device ID is is required, but the web view name and context ID are 15 | optional. You may use `$n` to match the n:th web view or context found (starting at 1). 16 | 17 | This is a convenience function that uses [Device.findDevice](../classes/Device.md#finddevice) and [Device.findWebViews](../classes/Device.md#findwebviews) to find a web 18 | view, binds it to a local port with [Device.bindWebView](../classes/Device.md#bindwebview) and then finally calls [findWebViewContexts](findWebViewContexts.md) to 19 | resolve to a web view context. 20 | 21 | ## Parameters 22 | 23 | • **contextPath**: `string` 24 | 25 | Specify what device, web view and context to use. 26 | 27 | • **port**: `number` 28 | 29 | The port to bind the web view to. See [Device.bindWebView](../classes/Device.md#bindwebview). 30 | 31 | • **deviceOptions?**: [`DeviceOptions`](../interfaces/DeviceOptions.md) 32 | 33 | Additional options to pass to [Device.findDevice](../classes/Device.md#finddevice). 34 | 35 | • **timeout?**: `number` 36 | 37 | If specified, the method will wait for the device, web view and context to appear this many 38 | milliseconds (0 means forever). 39 | 40 | ## Returns 41 | 42 | `Promise`\<[`ResolvedContextPath`](../interfaces/ResolvedContextPath.md)\> 43 | 44 | A [ResolvedContextPath](../interfaces/ResolvedContextPath.md) object containing [AutomationOptions](../interfaces/AutomationOptions.md), ready to be passed to 45 | [openWebView](openWebView.md), the web view id and the [Device](../classes/Device.md) on which the web view is running. 46 | 47 | ## Throws 48 | 49 | TypeError If the context path or the port is invalid. 50 | 51 | ## Throws 52 | 53 | Error If the device, web view or context could not be found, or if the context path is ambiguous. 54 | 55 | ## Defined in 56 | 57 | [src/api.ts:61](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L61) 58 | -------------------------------------------------------------------------------- /docs/index/functions/sleep.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / sleep 6 | 7 | # Function: sleep() 8 | 9 | > **sleep**(`timeout`): `Promise`\<`void`\> 10 | 11 | Does nothing for a while. 12 | 13 | ## Parameters 14 | 15 | • **timeout**: `number` 16 | 17 | The sleep duration in milliseconds 18 | 19 | ## Returns 20 | 21 | `Promise`\<`void`\> 22 | 23 | ## Defined in 24 | 25 | [src/utils.ts:27](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L27) 26 | -------------------------------------------------------------------------------- /docs/index/functions/throwError.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / throwError 6 | 7 | # Function: throwError() 8 | 9 | > **throwError**(`error`): `never` 10 | 11 | Throws an error. 12 | 13 | ## Parameters 14 | 15 | • **error**: `Error` 16 | 17 | The error to throw. 18 | 19 | ## Returns 20 | 21 | `never` 22 | 23 | ## Throws 24 | 25 | The provided error. 26 | 27 | ## Defined in 28 | 29 | [src/utils.ts:18](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L18) 30 | -------------------------------------------------------------------------------- /docs/index/functions/writeFile.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / writeFile 6 | 7 | # Function: writeFile() 8 | 9 | > **writeFile**(`path`, `data`, `options`?): `Promise`\<`void`\> 10 | 11 | Asynchronously writes data to a file, replacing the file if it already exists. 12 | 13 | ## Parameters 14 | 15 | • **path**: `PathOrFileDescriptor` 16 | 17 | A path to a file. If a URL is provided, it must use the `file:` protocol. 18 | URL support is _experimental_. 19 | If a file descriptor is provided, the underlying file will _not_ be closed automatically. 20 | 21 | • **data**: `string` \| `ArrayBufferView` 22 | 23 | The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string. 24 | 25 | • **options?**: `WriteFileOptions` 26 | 27 | Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag. 28 | If `encoding` is not supplied, the default of `'utf8'` is used. 29 | If `mode` is not supplied, the default of `0o666` is used. 30 | If `mode` is a string, it is parsed as an octal integer. 31 | If `flag` is not supplied, the default of `'w'` is used. 32 | 33 | ## Returns 34 | 35 | `Promise`\<`void`\> 36 | 37 | ## Defined in 38 | 39 | [src/utils.ts:10](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L10) 40 | -------------------------------------------------------------------------------- /docs/index/interfaces/AndroidLogOptions.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / AndroidLogOptions 6 | 7 | # Interface: AndroidLogOptions 8 | 9 | ## Extends 10 | 11 | - [`ReaderOptions`](ReaderOptions.md) 12 | 13 | ## Properties 14 | 15 | ### buffers? 16 | 17 | > `optional` **buffers**: (`"main"` \| `"system"` \| `"radio"` \| `"events"` \| `"crash"`)[] 18 | 19 | #### Defined in 20 | 21 | [src/android-device.ts:10](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/android-device.ts#L10) 22 | 23 | *** 24 | 25 | ### clear? 26 | 27 | > `optional` **clear**: `boolean` 28 | 29 | #### Defined in 30 | 31 | [src/android-device.ts:6](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/android-device.ts#L6) 32 | 33 | *** 34 | 35 | ### filterspecs? 36 | 37 | > `optional` **filterspecs**: `string`[] 38 | 39 | #### Defined in 40 | 41 | [src/android-device.ts:11](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/android-device.ts#L11) 42 | 43 | *** 44 | 45 | ### format? 46 | 47 | > `optional` **format**: `"raw"` \| `"long"` \| `"time"` \| `"brief"` \| `"process"` \| `"tag"` \| `"thread"` \| `"threadtime"` 48 | 49 | #### Defined in 50 | 51 | [src/android-device.ts:8](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/android-device.ts#L8) 52 | 53 | *** 54 | 55 | ### historic? 56 | 57 | > `optional` **historic**: `boolean` 58 | 59 | #### Defined in 60 | 61 | [src/android-device.ts:7](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/android-device.ts#L7) 62 | 63 | *** 64 | 65 | ### modifiers? 66 | 67 | > `optional` **modifiers**: (`"color"` \| `"year"` \| `"descriptive"` \| `"epoch"` \| `"monotonic"` \| `"printable"` \| `"uid"` \| `"usec"` \| `"UTC"` \| `"zone"`)[] 68 | 69 | #### Defined in 70 | 71 | [src/android-device.ts:9](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/android-device.ts#L9) 72 | 73 | *** 74 | 75 | ### separator? 76 | 77 | > `optional` **separator**: `string` 78 | 79 | A line separator to add to each generated line. 80 | 81 | #### Inherited from 82 | 83 | [`ReaderOptions`](ReaderOptions.md).[`separator`](ReaderOptions.md#separator) 84 | 85 | #### Defined in 86 | 87 | [src/utils.ts:36](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L36) 88 | 89 | *** 90 | 91 | ### stopSignal? 92 | 93 | > `optional` **stopSignal**: `Signal`\<`boolean`\> 94 | 95 | A signal to check. Reading will stop when signal is `true.` 96 | 97 | #### Inherited from 98 | 99 | [`ReaderOptions`](ReaderOptions.md).[`stopSignal`](ReaderOptions.md#stopsignal) 100 | 101 | #### Defined in 102 | 103 | [src/utils.ts:33](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L33) 104 | -------------------------------------------------------------------------------- /docs/index/interfaces/AutomationContext.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / AutomationContext 6 | 7 | # Interface: AutomationContext 8 | 9 | ## Properties 10 | 11 | ### appId? 12 | 13 | > `optional` **appId**: `string` 14 | 15 | iOS process owning this context. 16 | 17 | #### Defined in 18 | 19 | [src/automation.ts:79](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/automation.ts#L79) 20 | 21 | *** 22 | 23 | ### description? 24 | 25 | > `optional` **description**: `string` 26 | 27 | Context description 28 | 29 | #### Defined in 30 | 31 | [src/automation.ts:82](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/automation.ts#L82) 32 | 33 | *** 34 | 35 | ### devtoolsFrontendUrl 36 | 37 | > **devtoolsFrontendUrl**: `string` 38 | 39 | URL to a DevTools session for this context. 40 | 41 | #### Defined in 42 | 43 | [src/automation.ts:85](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/automation.ts#L85) 44 | 45 | *** 46 | 47 | ### faviconUrl? 48 | 49 | > `optional` **faviconUrl**: `string` 50 | 51 | URL of favicon image. 52 | 53 | #### Defined in 54 | 55 | [src/automation.ts:88](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/automation.ts#L88) 56 | 57 | *** 58 | 59 | ### id 60 | 61 | > **id**: `string` 62 | 63 | Context ID. 64 | 65 | #### Defined in 66 | 67 | [src/automation.ts:91](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/automation.ts#L91) 68 | 69 | *** 70 | 71 | ### thumbnailUrl? 72 | 73 | > `optional` **thumbnailUrl**: `string` 74 | 75 | URL of thumbnail image. 76 | 77 | #### Defined in 78 | 79 | [src/automation.ts:94](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/automation.ts#L94) 80 | 81 | *** 82 | 83 | ### title 84 | 85 | > **title**: `string` 86 | 87 | The title of the page loaded in this context. 88 | 89 | #### Defined in 90 | 91 | [src/automation.ts:97](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/automation.ts#L97) 92 | 93 | *** 94 | 95 | ### type? 96 | 97 | > `optional` **type**: `string` 98 | 99 | Type of context. 100 | 101 | #### Defined in 102 | 103 | [src/automation.ts:100](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/automation.ts#L100) 104 | 105 | *** 106 | 107 | ### url 108 | 109 | > **url**: `string` 110 | 111 | The URL of the page loaded in this context. 112 | 113 | #### Defined in 114 | 115 | [src/automation.ts:103](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/automation.ts#L103) 116 | 117 | *** 118 | 119 | ### webSocketDebuggerUrl 120 | 121 | > **webSocketDebuggerUrl**: `string` 122 | 123 | The URL where the debugger is running. 124 | 125 | #### Defined in 126 | 127 | [src/automation.ts:106](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/automation.ts#L106) 128 | -------------------------------------------------------------------------------- /docs/index/interfaces/AutomationOptions.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / AutomationOptions 6 | 7 | # Interface: AutomationOptions 8 | 9 | ## Extends 10 | 11 | - `BaseOptions` 12 | 13 | ## Properties 14 | 15 | ### alterPath()? 16 | 17 | > `optional` **alterPath**: (`path`) => `string` 18 | 19 | #### Parameters 20 | 21 | • **path**: `string` 22 | 23 | #### Returns 24 | 25 | `string` 26 | 27 | #### Inherited from 28 | 29 | `BaseOptions.alterPath` 30 | 31 | #### Defined in 32 | 33 | node\_modules/.pnpm/@types+chrome-remote-interface@0.31.14/node\_modules/@types/chrome-remote-interface/index.d.ts:10 34 | 35 | *** 36 | 37 | ### appId? 38 | 39 | > `optional` **appId**: `string` 40 | 41 | Only include contexts owned by this iOS process. 42 | 43 | #### Defined in 44 | 45 | [src/automation.ts:71](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/automation.ts#L71) 46 | 47 | *** 48 | 49 | ### ctxId? 50 | 51 | > `optional` **ctxId**: `string` 52 | 53 | The [AutomationContext.id](AutomationContext.md#id) to use. 54 | 55 | #### Defined in 56 | 57 | [src/automation.ts:74](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/automation.ts#L74) 58 | 59 | *** 60 | 61 | ### host? 62 | 63 | > `optional` **host**: `string` 64 | 65 | #### Inherited from 66 | 67 | `BaseOptions.host` 68 | 69 | #### Defined in 70 | 71 | node\_modules/.pnpm/@types+chrome-remote-interface@0.31.14/node\_modules/@types/chrome-remote-interface/index.d.ts:6 72 | 73 | *** 74 | 75 | ### port? 76 | 77 | > `optional` **port**: `number` 78 | 79 | #### Inherited from 80 | 81 | `BaseOptions.port` 82 | 83 | #### Defined in 84 | 85 | node\_modules/.pnpm/@types+chrome-remote-interface@0.31.14/node\_modules/@types/chrome-remote-interface/index.d.ts:7 86 | 87 | *** 88 | 89 | ### secure? 90 | 91 | > `optional` **secure**: `boolean` 92 | 93 | #### Inherited from 94 | 95 | `BaseOptions.secure` 96 | 97 | #### Defined in 98 | 99 | node\_modules/.pnpm/@types+chrome-remote-interface@0.31.14/node\_modules/@types/chrome-remote-interface/index.d.ts:8 100 | 101 | *** 102 | 103 | ### useHostName? 104 | 105 | > `optional` **useHostName**: `boolean` 106 | 107 | #### Inherited from 108 | 109 | `BaseOptions.useHostName` 110 | 111 | #### Defined in 112 | 113 | node\_modules/.pnpm/@types+chrome-remote-interface@0.31.14/node\_modules/@types/chrome-remote-interface/index.d.ts:9 114 | -------------------------------------------------------------------------------- /docs/index/interfaces/DeviceOptions.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / DeviceOptions 6 | 7 | # Interface: DeviceOptions 8 | 9 | Device manager configuration. 10 | 11 | ## Properties 12 | 13 | ### adb? 14 | 15 | > `optional` **adb**: `null` \| `string` 16 | 17 | Where to find the `adb` command. `undefined` means Android support is optional (enabled if `adb` is in the path) and 18 | `null` disables Android support completely. 19 | 20 | #### Defined in 21 | 22 | [src/device.ts:14](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L14) 23 | 24 | *** 25 | 26 | ### ideviceinstaller? 27 | 28 | > `optional` **ideviceinstaller**: `string` 29 | 30 | Where to find the `ideviceinstaller` command. Used by [iOSDevice.install](../classes/iOSDevice.md#install)/[iOSDevice.uninstall](../classes/iOSDevice.md#uninstall). 31 | 32 | #### Defined in 33 | 34 | [src/device.ts:17](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L17) 35 | 36 | *** 37 | 38 | ### idevicesyslog? 39 | 40 | > `optional` **idevicesyslog**: `string` 41 | 42 | Where to find the `idevicesyslog` command. Used by [iOSDevice.readLogs](../classes/iOSDevice.md#readlogs)/[iOSDevice.collectLogs](../classes/iOSDevice.md#collectlogs). 43 | 44 | #### Defined in 45 | 46 | [src/device.ts:20](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L20) 47 | 48 | *** 49 | 50 | ### ios\_instruments\_client? 51 | 52 | > `optional` **ios\_instruments\_client**: `string` 53 | 54 | Where to find the `ios_instruments_client` command. Used by [iOSDevice.start](../classes/iOSDevice.md#start)/[iOSDevice.stop](../classes/iOSDevice.md#stop). 55 | 56 | #### Defined in 57 | 58 | [src/device.ts:23](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L23) 59 | 60 | *** 61 | 62 | ### iwdpPort? 63 | 64 | > `optional` **iwdpPort**: `null` \| `number` 65 | 66 | What port `ios_webkit_debug_proxy` is listening on. `undefined` means iOS support is optional (enabled if 67 | `ios_webkit_debug_proxy` is listening on port 9221) and `null` disables iOS support completely. 68 | 69 | #### Defined in 70 | 71 | [src/device.ts:29](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L29) 72 | -------------------------------------------------------------------------------- /docs/index/interfaces/LocatorOptions.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / LocatorOptions 6 | 7 | # Interface: LocatorOptions 8 | 9 | ## Properties 10 | 11 | ### has? 12 | 13 | > `optional` **has**: [`Locator`](../classes/Locator.md) 14 | 15 | Only match if this Location also matches. 16 | 17 | #### Defined in 18 | 19 | [src/api.ts:23](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L23) 20 | 21 | *** 22 | 23 | ### hasText? 24 | 25 | > `optional` **hasText**: `string` \| `RegExp` 26 | 27 | Only match if this text Locator also matches. 28 | 29 | #### Defined in 30 | 31 | [src/api.ts:26](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L26) 32 | -------------------------------------------------------------------------------- /docs/index/interfaces/ReaderOptions.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / ReaderOptions 6 | 7 | # Interface: ReaderOptions 8 | 9 | ## Extended by 10 | 11 | - [`AndroidLogOptions`](AndroidLogOptions.md) 12 | - [`iOSLogOptions`](iOSLogOptions.md) 13 | 14 | ## Properties 15 | 16 | ### separator? 17 | 18 | > `optional` **separator**: `string` 19 | 20 | A line separator to add to each generated line. 21 | 22 | #### Defined in 23 | 24 | [src/utils.ts:36](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L36) 25 | 26 | *** 27 | 28 | ### stopSignal? 29 | 30 | > `optional` **stopSignal**: `Signal`\<`boolean`\> 31 | 32 | A signal to check. Reading will stop when signal is `true.` 33 | 34 | #### Defined in 35 | 36 | [src/utils.ts:33](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L33) 37 | -------------------------------------------------------------------------------- /docs/index/interfaces/ResolvedContextPath.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / ResolvedContextPath 6 | 7 | # Interface: ResolvedContextPath 8 | 9 | ## Properties 10 | 11 | ### device 12 | 13 | > **device**: [`Device`](../classes/Device.md) 14 | 15 | What device to use. 16 | 17 | #### Defined in 18 | 19 | [src/api.ts:31](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L31) 20 | 21 | *** 22 | 23 | ### options 24 | 25 | > **options**: [`AutomationOptions`](AutomationOptions.md) 26 | 27 | Options describing what web view context to use. 28 | 29 | #### Defined in 30 | 31 | [src/api.ts:37](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L37) 32 | 33 | *** 34 | 35 | ### webview 36 | 37 | > **webview**: `string` 38 | 39 | What web view to use. 40 | 41 | #### Defined in 42 | 43 | [src/api.ts:34](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L34) 44 | -------------------------------------------------------------------------------- /docs/index/interfaces/SelectorOptions.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / SelectorOptions 6 | 7 | # Interface: SelectorOptions 8 | 9 | ## Properties 10 | 11 | ### timeout? 12 | 13 | > `optional` **timeout**: `number` 14 | 15 | How long, in milliseconds, to wait for the target to be actionable. 16 | 17 | #### Defined in 18 | 19 | [src/api.ts:15](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L15) 20 | 21 | *** 22 | 23 | ### trial? 24 | 25 | > `optional` **trial**: `boolean` 26 | 27 | It true, don't actually perform the action requested. 28 | 29 | #### Defined in 30 | 31 | [src/api.ts:18](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/api.ts#L18) 32 | -------------------------------------------------------------------------------- /docs/index/interfaces/StartOptions.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / StartOptions 6 | 7 | # Interface: StartOptions 8 | 9 | ## Properties 10 | 11 | ### args? 12 | 13 | > `optional` **args**: `string`[] 14 | 15 | Optional application arguments. 16 | 17 | #### Defined in 18 | 19 | [src/device.ts:34](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L34) 20 | 21 | *** 22 | 23 | ### restart? 24 | 25 | > `optional` **restart**: `boolean` 26 | 27 | Close the application first, if it is already running. 28 | 29 | #### Defined in 30 | 31 | [src/device.ts:37](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L37) 32 | 33 | *** 34 | 35 | ### wait? 36 | 37 | > `optional` **wait**: `boolean` 38 | 39 | Wait for the application to start up before returning. 40 | 41 | #### Defined in 42 | 43 | [src/device.ts:40](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/device.ts#L40) 44 | -------------------------------------------------------------------------------- /docs/index/interfaces/iOSLogOptions.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [index](../README.md) / iOSLogOptions 6 | 7 | # Interface: iOSLogOptions 8 | 9 | ## Extends 10 | 11 | - [`ReaderOptions`](ReaderOptions.md) 12 | 13 | ## Properties 14 | 15 | ### exclude? 16 | 17 | > `optional` **exclude**: `string`[] 18 | 19 | Processes to exclude. 20 | 21 | #### Defined in 22 | 23 | [src/ios-device.ts:48](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/ios-device.ts#L48) 24 | 25 | *** 26 | 27 | ### include? 28 | 29 | > `optional` **include**: `string`[] 30 | 31 | Processes to include. 32 | 33 | #### Defined in 34 | 35 | [src/ios-device.ts:45](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/ios-device.ts#L45) 36 | 37 | *** 38 | 39 | ### match? 40 | 41 | > `optional` **match**: `string` 42 | 43 | Only include log lines that contain this string. 44 | 45 | #### Defined in 46 | 47 | [src/ios-device.ts:42](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/ios-device.ts#L42) 48 | 49 | *** 50 | 51 | ### quiet? 52 | 53 | > `optional` **quiet**: `boolean` 54 | 55 | If true, excludes a predefined set of noisy processes in addition to those specified via the [exclude](iOSLogOptions.md#exclude) option. 56 | 57 | #### Defined in 58 | 59 | [src/ios-device.ts:51](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/ios-device.ts#L51) 60 | 61 | *** 62 | 63 | ### separator? 64 | 65 | > `optional` **separator**: `string` 66 | 67 | A line separator to add to each generated line. 68 | 69 | #### Inherited from 70 | 71 | [`ReaderOptions`](ReaderOptions.md).[`separator`](ReaderOptions.md#separator) 72 | 73 | #### Defined in 74 | 75 | [src/utils.ts:36](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L36) 76 | 77 | *** 78 | 79 | ### stopSignal? 80 | 81 | > `optional` **stopSignal**: `Signal`\<`boolean`\> 82 | 83 | A signal to check. Reading will stop when signal is `true.` 84 | 85 | #### Inherited from 86 | 87 | [`ReaderOptions`](ReaderOptions.md).[`stopSignal`](ReaderOptions.md#stopsignal) 88 | 89 | #### Defined in 90 | 91 | [src/utils.ts:33](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/utils.ts#L33) 92 | -------------------------------------------------------------------------------- /docs/test/README.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../README.md) / test 6 | 7 | # test 8 | 9 | ## Index 10 | 11 | ### Classes 12 | 13 | - [DeviceWorkerLauncher](classes/DeviceWorkerLauncher.md) 14 | 15 | ### Interfaces 16 | 17 | - [DeviceWorkerFixtures](interfaces/DeviceWorkerFixtures.md) 18 | - [DeviceWorkerLauncherOptions](interfaces/DeviceWorkerLauncherOptions.md) 19 | - [DeviceWorkerOptions](interfaces/DeviceWorkerOptions.md) 20 | - [WebAppConfig](interfaces/WebAppConfig.md) 21 | 22 | ### Functions 23 | 24 | - [expect](functions/expect.md) 25 | - [getFixtureTimeout](functions/getFixtureTimeout.md) 26 | - [setFixtureTimeout](functions/setFixtureTimeout.md) 27 | - [test](functions/test.md) 28 | -------------------------------------------------------------------------------- /docs/test/classes/DeviceWorkerLauncher.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [test](../README.md) / DeviceWorkerLauncher 6 | 7 | # Class: DeviceWorkerLauncher\ 8 | 9 | Device and configuration manager. 10 | 11 | ## Type Parameters 12 | 13 | • **Options** *extends* [`DeviceWorkerLauncherOptions`](../interfaces/DeviceWorkerLauncherOptions.md) = [`DeviceWorkerLauncherOptions`](../interfaces/DeviceWorkerLauncherOptions.md) 14 | 15 | ## Constructors 16 | 17 | ### new DeviceWorkerLauncher() 18 | 19 | > **new DeviceWorkerLauncher**\<`Options`\>(`options`?): [`DeviceWorkerLauncher`](DeviceWorkerLauncher.md)\<`Options`\> 20 | 21 | #### Parameters 22 | 23 | • **options?**: `Options` 24 | 25 | #### Returns 26 | 27 | [`DeviceWorkerLauncher`](DeviceWorkerLauncher.md)\<`Options`\> 28 | 29 | #### Defined in 30 | 31 | [src/test.ts:63](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L63) 32 | 33 | ## Methods 34 | 35 | ### setup() 36 | 37 | > **setup**(`worker`, `headless`, `workerInfo`): `Promise`\<`string`\> 38 | 39 | Setup a device for the specified worker. 40 | 41 | The default implementation just returns the device ID from the [DeviceWorkerLauncherOptions#devices](../interfaces/DeviceWorkerLauncherOptions.md#devices) } 42 | array. A subclass might launch an emulator or provision to a physical device, and return its ID. 43 | 44 | #### Parameters 45 | 46 | • **worker**: `number` 47 | 48 | The worker index. 49 | 50 | • **headless**: `boolean` 51 | 52 | Whether to start the device in headless mode or not. 53 | 54 | • **workerInfo**: `WorkerInfo` 55 | 56 | The worker information. 57 | 58 | #### Returns 59 | 60 | `Promise`\<`string`\> 61 | 62 | The device ID to use. 63 | 64 | #### Defined in 65 | 66 | [src/test.ts:87](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L87) 67 | 68 | *** 69 | 70 | ### start() 71 | 72 | > **start**(`worker`, `device`, `workerInfo`): `Promise`\<[`WebAppConfig`](../interfaces/WebAppConfig.md)\> 73 | 74 | Launches the configured application on a device and returns information about what web view to connect to. 75 | 76 | The default implementation makes a fresh install of the application package, if specified in 77 | [DeviceWorkerLauncherOptions#archive](../interfaces/DeviceWorkerLauncherOptions.md#archive), and then launches the application specified in 78 | [DeviceWorkerLauncherOptions#app](../interfaces/DeviceWorkerLauncherOptions.md#app). 79 | 80 | #### Parameters 81 | 82 | • **worker**: `number` 83 | 84 | The worker index. 85 | 86 | • **device**: [`Device`](../../index/classes/Device.md) 87 | 88 | The device to start the application on. 89 | 90 | • **workerInfo**: `WorkerInfo` 91 | 92 | The worker information. 93 | 94 | #### Returns 95 | 96 | `Promise`\<[`WebAppConfig`](../interfaces/WebAppConfig.md)\> 97 | 98 | Information about the web view to connect to. 99 | 100 | #### Defined in 101 | 102 | [src/test.ts:106](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L106) 103 | 104 | *** 105 | 106 | ### stop() 107 | 108 | > **stop**(`worker`, `device`, `workerInfo`): `Promise`\<`void`\> 109 | 110 | Stops the configured application on a device. 111 | 112 | #### Parameters 113 | 114 | • **worker**: `number` 115 | 116 | The worker index. 117 | 118 | • **device**: [`Device`](../../index/classes/Device.md) 119 | 120 | The device to stop the application on. 121 | 122 | • **workerInfo**: `WorkerInfo` 123 | 124 | The worker information. 125 | 126 | #### Returns 127 | 128 | `Promise`\<`void`\> 129 | 130 | #### Defined in 131 | 132 | [src/test.ts:131](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L131) 133 | 134 | *** 135 | 136 | ### teardown() 137 | 138 | > **teardown**(`worker`, `workerInfo`): `Promise`\<`void`\> 139 | 140 | Teardown a device for the specified worker. 141 | 142 | The default implementation does nothing. A subclass might stop an emulator or release a physical device. 143 | 144 | #### Parameters 145 | 146 | • **worker**: `number` 147 | 148 | The worker index. 149 | 150 | • **workerInfo**: `WorkerInfo` 151 | 152 | The worker information. 153 | 154 | #### Returns 155 | 156 | `Promise`\<`void`\> 157 | 158 | #### Defined in 159 | 160 | [src/test.ts:148](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L148) 161 | -------------------------------------------------------------------------------- /docs/test/functions/expect.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [test](../README.md) / expect 6 | 7 | # Function: expect() 8 | 9 | > **expect**\<`T`\>(`actual`, `messageOrOptions`?): `MakeMatchers`\<`void`, `T`, `object`\> 10 | 11 | ## Type Parameters 12 | 13 | • **T** = `unknown` 14 | 15 | ## Parameters 16 | 17 | • **actual**: `T` 18 | 19 | • **messageOrOptions?**: `string` \| `object` 20 | 21 | ## Returns 22 | 23 | `MakeMatchers`\<`void`, `T`, `object`\> 24 | 25 | ## Defined in 26 | 27 | [src/test.ts:250](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L250) 28 | -------------------------------------------------------------------------------- /docs/test/functions/getFixtureTimeout.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [test](../README.md) / getFixtureTimeout 6 | 7 | # Function: getFixtureTimeout() 8 | 9 | > **getFixtureTimeout**(`fixture`): `number` \| `undefined` 10 | 11 | Returns the timeout for a device worker fixture. 12 | 13 | ## Parameters 14 | 15 | • **fixture**: keyof [`DeviceWorkerFixtures`](../interfaces/DeviceWorkerFixtures.md) 16 | 17 | The fixture to get the timeout for. 18 | 19 | ## Returns 20 | 21 | `number` \| `undefined` 22 | 23 | The timeout in milliseconds, or `undefined` if no specific fixture timeout has been set. 24 | 25 | ## Defined in 26 | 27 | [src/test.ts:171](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L171) 28 | -------------------------------------------------------------------------------- /docs/test/functions/setFixtureTimeout.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [test](../README.md) / setFixtureTimeout 6 | 7 | # Function: setFixtureTimeout() 8 | 9 | > **setFixtureTimeout**(`fixture`, `timeout`): `void` 10 | 11 | Configure the timeout for a device worker fixture. 12 | 13 | ## Parameters 14 | 15 | • **fixture**: keyof [`DeviceWorkerFixtures`](../interfaces/DeviceWorkerFixtures.md) 16 | 17 | The fixture to configure. 18 | 19 | • **timeout**: `undefined` \| `number` 20 | 21 | The timeout in milliseconds, or `undefined` for no specific fixture timeout. 22 | 23 | ## Returns 24 | 25 | `void` 26 | 27 | ## Defined in 28 | 29 | [src/test.ts:161](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L161) 30 | -------------------------------------------------------------------------------- /docs/test/functions/test.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [test](../README.md) / test 6 | 7 | # Function: test() 8 | 9 | ## test(title, body) 10 | 11 | > **test**(`title`, `body`): `void` 12 | 13 | Declares a test. 14 | - `test(title, body)` 15 | - `test(title, details, body)` 16 | 17 | **Usage** 18 | 19 | ```js 20 | import { test, expect } from '@playwright/test'; 21 | 22 | test('basic test', async ({ page }) => { 23 | await page.goto('https://playwright.dev/'); 24 | // ... 25 | }); 26 | ``` 27 | 28 | **Tags** 29 | 30 | You can tag tests by providing additional test details. Alternatively, you can include tags in the test title. Note 31 | that each tag must start with `@` symbol. 32 | 33 | ```js 34 | import { test, expect } from '@playwright/test'; 35 | 36 | test('basic test', { 37 | tag: '@smoke', 38 | }, async ({ page }) => { 39 | await page.goto('https://playwright.dev/'); 40 | // ... 41 | }); 42 | 43 | test('another test @smoke', async ({ page }) => { 44 | await page.goto('https://playwright.dev/'); 45 | // ... 46 | }); 47 | ``` 48 | 49 | Test tags are displayed in the test report, and are available to a custom reporter via `TestCase.tags` property. 50 | 51 | You can also filter tests by their tags during test execution: 52 | - in the [command line](https://playwright.dev/docs/test-cli#reference); 53 | - in the config with [testConfig.grep](https://playwright.dev/docs/api/class-testconfig#test-config-grep) and 54 | [testProject.grep](https://playwright.dev/docs/api/class-testproject#test-project-grep); 55 | 56 | Learn more about [tagging](https://playwright.dev/docs/test-annotations#tag-tests). 57 | 58 | **Annotations** 59 | 60 | You can annotate tests by providing additional test details. 61 | 62 | ```js 63 | import { test, expect } from '@playwright/test'; 64 | 65 | test('basic test', { 66 | annotation: { 67 | type: 'issue', 68 | description: 'https://github.com/microsoft/playwright/issues/23180', 69 | }, 70 | }, async ({ page }) => { 71 | await page.goto('https://playwright.dev/'); 72 | // ... 73 | }); 74 | ``` 75 | 76 | Test annotations are displayed in the test report, and are available to a custom reporter via 77 | `TestCase.annotations` property. 78 | 79 | You can also add annotations during runtime by manipulating 80 | [testInfo.annotations](https://playwright.dev/docs/api/class-testinfo#test-info-annotations). 81 | 82 | Learn more about [test annotations](https://playwright.dev/docs/test-annotations). 83 | 84 | ### Parameters 85 | 86 | • **title**: `string` 87 | 88 | Test title. 89 | 90 | • **body** 91 | 92 | Test body that takes one or two arguments: an object with fixtures and optional TestInfo. 93 | 94 | ### Returns 95 | 96 | `void` 97 | 98 | ### Defined in 99 | 100 | [src/test.ts:175](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L175) 101 | 102 | ## test(title, details, body) 103 | 104 | > **test**(`title`, `details`, `body`): `void` 105 | 106 | Declares a test. 107 | - `test(title, body)` 108 | - `test(title, details, body)` 109 | 110 | **Usage** 111 | 112 | ```js 113 | import { test, expect } from '@playwright/test'; 114 | 115 | test('basic test', async ({ page }) => { 116 | await page.goto('https://playwright.dev/'); 117 | // ... 118 | }); 119 | ``` 120 | 121 | **Tags** 122 | 123 | You can tag tests by providing additional test details. Alternatively, you can include tags in the test title. Note 124 | that each tag must start with `@` symbol. 125 | 126 | ```js 127 | import { test, expect } from '@playwright/test'; 128 | 129 | test('basic test', { 130 | tag: '@smoke', 131 | }, async ({ page }) => { 132 | await page.goto('https://playwright.dev/'); 133 | // ... 134 | }); 135 | 136 | test('another test @smoke', async ({ page }) => { 137 | await page.goto('https://playwright.dev/'); 138 | // ... 139 | }); 140 | ``` 141 | 142 | Test tags are displayed in the test report, and are available to a custom reporter via `TestCase.tags` property. 143 | 144 | You can also filter tests by their tags during test execution: 145 | - in the [command line](https://playwright.dev/docs/test-cli#reference); 146 | - in the config with [testConfig.grep](https://playwright.dev/docs/api/class-testconfig#test-config-grep) and 147 | [testProject.grep](https://playwright.dev/docs/api/class-testproject#test-project-grep); 148 | 149 | Learn more about [tagging](https://playwright.dev/docs/test-annotations#tag-tests). 150 | 151 | **Annotations** 152 | 153 | You can annotate tests by providing additional test details. 154 | 155 | ```js 156 | import { test, expect } from '@playwright/test'; 157 | 158 | test('basic test', { 159 | annotation: { 160 | type: 'issue', 161 | description: 'https://github.com/microsoft/playwright/issues/23180', 162 | }, 163 | }, async ({ page }) => { 164 | await page.goto('https://playwright.dev/'); 165 | // ... 166 | }); 167 | ``` 168 | 169 | Test annotations are displayed in the test report, and are available to a custom reporter via 170 | `TestCase.annotations` property. 171 | 172 | You can also add annotations during runtime by manipulating 173 | [testInfo.annotations](https://playwright.dev/docs/api/class-testinfo#test-info-annotations). 174 | 175 | Learn more about [test annotations](https://playwright.dev/docs/test-annotations). 176 | 177 | ### Parameters 178 | 179 | • **title**: `string` 180 | 181 | Test title. 182 | 183 | • **details**: `TestDetails` 184 | 185 | Additional test details. 186 | 187 | • **body** 188 | 189 | Test body that takes one or two arguments: an object with fixtures and optional TestInfo. 190 | 191 | ### Returns 192 | 193 | `void` 194 | 195 | ### Defined in 196 | 197 | [src/test.ts:175](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L175) 198 | -------------------------------------------------------------------------------- /docs/test/interfaces/DeviceWorkerFixtures.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [test](../README.md) / DeviceWorkerFixtures 6 | 7 | # Interface: DeviceWorkerFixtures 8 | 9 | The Onslip Automation Library fixtures for Playwright. 10 | 11 | ## Properties 12 | 13 | ### device 14 | 15 | > **device**: [`Device`](../../index/classes/Device.md) 16 | 17 | The connected [Device](../../index/classes/Device.md). 18 | 19 | #### Defined in 20 | 21 | [src/test.ts:25](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L25) 22 | 23 | *** 24 | 25 | ### webApp 26 | 27 | > **webApp**: [`Page`](../../index/classes/Page.md) 28 | 29 | The web app [Page](../../index/classes/Page.md) that is being automated. 30 | 31 | #### Defined in 32 | 33 | [src/test.ts:28](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L28) 34 | -------------------------------------------------------------------------------- /docs/test/interfaces/DeviceWorkerLauncherOptions.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [test](../README.md) / DeviceWorkerLauncherOptions 6 | 7 | # Interface: DeviceWorkerLauncherOptions 8 | 9 | [DeviceWorkerLauncher](../classes/DeviceWorkerLauncher.md) options. 10 | 11 | ## Properties 12 | 13 | ### app? 14 | 15 | > `optional` **app**: `string` 16 | 17 | If specified, the package/activity identifier or application bundle identifier to launch. 18 | 19 | #### Defined in 20 | 21 | [src/test.ts:37](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L37) 22 | 23 | *** 24 | 25 | ### archive? 26 | 27 | > `optional` **archive**: `string` 28 | 29 | If specified, path to the application to install on the device 30 | 31 | #### Defined in 32 | 33 | [src/test.ts:34](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L34) 34 | 35 | *** 36 | 37 | ### args? 38 | 39 | > `optional` **args**: `string`[] 40 | 41 | Optional application arguments. 42 | 43 | #### Defined in 44 | 45 | [src/test.ts:40](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L40) 46 | 47 | *** 48 | 49 | ### context? 50 | 51 | > `optional` **context**: `string` 52 | 53 | The web view/context to connect to (the actual device ID will be prepended to form a proper context path). 54 | 55 | #### Defined in 56 | 57 | [src/test.ts:43](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L43) 58 | 59 | *** 60 | 61 | ### devices? 62 | 63 | > `optional` **devices**: `string`[] 64 | 65 | A static list of device IDs to use (must match the number or workers) by default. 66 | 67 | #### Defined in 68 | 69 | [src/test.ts:46](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L46) 70 | -------------------------------------------------------------------------------- /docs/test/interfaces/DeviceWorkerOptions.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [test](../README.md) / DeviceWorkerOptions 6 | 7 | # Interface: DeviceWorkerOptions 8 | 9 | [DeviceWorkerFixtures](DeviceWorkerFixtures.md) configuration. 10 | 11 | ## Properties 12 | 13 | ### deviceWorkerConfig 14 | 15 | > **deviceWorkerConfig**: `null` \| `object` 16 | 17 | Configuration for the Onslip Automation Library fixtures for Playwright. 18 | 19 | #### Defined in 20 | 21 | [src/test.ts:10](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L10) 22 | -------------------------------------------------------------------------------- /docs/test/interfaces/WebAppConfig.md: -------------------------------------------------------------------------------- 1 | [**@onslip/automation**](../../README.md) • **Docs** 2 | 3 | *** 4 | 5 | [@onslip/automation](../../README.md) / [test](../README.md) / WebAppConfig 6 | 7 | # Interface: WebAppConfig 8 | 9 | [resolveWebViewContext](../../index/functions/resolveWebViewContext.md) arguments that should be used to connect to the web app. 10 | 11 | ## Properties 12 | 13 | ### contextPath 14 | 15 | > **contextPath**: `string` 16 | 17 | Specify what device, web view and context to use. 18 | 19 | #### Defined in 20 | 21 | [src/test.ts:52](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L52) 22 | 23 | *** 24 | 25 | ### proxyPort 26 | 27 | > **proxyPort**: `number` 28 | 29 | The port to bind the web view to. See [Device.bindWebView](../../index/classes/Device.md#bindwebview). 30 | 31 | #### Defined in 32 | 33 | [src/test.ts:55](https://github.com/Onslip/automation/blob/13befc40996d96bb2935315b372b921212adc8b4/src/test.ts#L55) 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@onslip/automation", 3 | "version": "1.3.0", 4 | "description": "Remote-control any old Android or iOS WebView in a Playwright-inspired way", 5 | "license": "Apache-2.0", 6 | "author": "Martin Blom ", 7 | "repository": "https://github.com/Onslip/automation.git", 8 | "main": "build/src/index.js", 9 | "types": "build/src/index.d.ts", 10 | "exports": { 11 | ".": { 12 | "types": "./build/src/index.d.ts", 13 | "default": "./build/src/index.js" 14 | }, 15 | "./test": { 16 | "types": "./build/src/test.d.ts", 17 | "default": "./build/src/test.js" 18 | }, 19 | "./build/src/test": { 20 | "types": "./build/src/test.d.ts", 21 | "default": "./build/src/test.js" 22 | } 23 | }, 24 | "files": [ 25 | "CHANGELOG.md", 26 | "build/*.js", 27 | "build/src", 28 | "src" 29 | ], 30 | "dependencies": { 31 | "@divine/synchronization": "^1.2.1", 32 | "@types/chrome-remote-interface": "~0.31.14", 33 | "chrome-remote-interface": "~0.33.2", 34 | "jimp": "~0.22.12" 35 | }, 36 | "devDependencies": { 37 | "@changesets/cli": "^2.27.7", 38 | "@types/node": "^22.5.0", 39 | "typedoc": "^0.26.6", 40 | "typedoc-plugin-markdown": "^4.2.6", 41 | "typescript": "~5.5.4" 42 | }, 43 | "peerDependencies": { 44 | "@playwright/test": "*" 45 | }, 46 | "peerDependenciesMeta": { 47 | "@playwright/test": { 48 | "optional": true 49 | } 50 | }, 51 | "pnpm": { 52 | "onlyBuiltDependencies": [] 53 | }, 54 | "engines": { 55 | "node": ">= 12.4" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/android-device.ts: -------------------------------------------------------------------------------- 1 | import type { AutomationOptions } from './automation'; 2 | import { Device, DeviceOptions, StartOptions } from './device'; 3 | import { collectLines, execFile, readCommandOutput, ReaderOptions } from './utils'; 4 | 5 | export interface AndroidLogOptions extends ReaderOptions { 6 | clear?: boolean; 7 | historic?: boolean; 8 | format?: 'brief' | 'process' | 'tag' | 'thread' | 'raw' | 'time' | 'threadtime' | 'long'; 9 | modifiers?: ('color' | 'descriptive' | 'epoch' | 'monotonic' | 'printable' | 'uid' | 'usec' | 'UTC' | 'year' | 'zone')[]; 10 | buffers?: ('main' | 'system' | 'radio' | 'events' | 'crash')[]; 11 | filterspecs?: string[]; 12 | } 13 | 14 | /** 15 | * This class manages Android devices and applications. 16 | */ 17 | export class AndroidDevice extends Device { 18 | /** 19 | * Finds all connected Android devices by executing `adb devices`. 20 | * 21 | * @param options Device manager options. 22 | * @returns A list of detected iOS devices. 23 | */ 24 | static override async findDevices(options: DeviceOptions = {}): Promise { 25 | const adb = options.adb === null ? null : options?.adb ?? 'adb'; 26 | 27 | try { 28 | return adb === null ? [] : 29 | (await execFile(adb, ['devices'])).stdout.split('\n') 30 | .map((line) => /(^[^\s]+)\s+device$/.exec(line)?.[1]!).filter(Boolean) 31 | .map((id) => new AndroidDevice(id, adb, options)); 32 | } catch (err) { 33 | if (!options.adb) { 34 | return []; // User did not specify adb path; fail silently 35 | } else { 36 | throw new Error(`Failed to invoke ${options.adb}; verify that the command is installed and available`); 37 | } 38 | } 39 | } 40 | 41 | private constructor(id: string, private _adb: string, private _options: DeviceOptions) { 42 | super(id, 'android'); 43 | } 44 | 45 | override toString(): string { 46 | return `[AndroidDevice ${this.id}]`; 47 | } 48 | 49 | override async osVersion(): Promise { 50 | return this.shell(`getprop ro.build.version.release`); 51 | } 52 | 53 | override async deviceName(): Promise { 54 | return this.shell(`getprop ro.product.model`); 55 | } 56 | 57 | override async install(archive: string, options?: string[]): Promise { 58 | const marshmallow = parseInt(await this.osVersion()) >= 6; 59 | await execFile(this._adb, ['-s', this.id, 'install', ...options ?? marshmallow ? ['-r', '-g'] : ['-r'], archive]); 60 | } 61 | 62 | override async start(app: string, options?: StartOptions): Promise { 63 | const args = options?.args?.map((arg) => `"${arg.replace(/([\\"])/g, '\\$1')}"`).join(' ') ?? ''; 64 | await this.shell(`am start ${options?.restart ? '-S' : ''} ${options?.wait ? '-W' : ''} -a android.intent.action.MAIN -n "${app}" ${args}`); 65 | } 66 | 67 | override async stop(app: string): Promise { 68 | const pkg = app.split('/')[0]; 69 | await this.shell(`am force-stop "${pkg}"`); 70 | } 71 | 72 | override async uninstall(app: string): Promise { 73 | const pkg = app.split('/')[0]; 74 | await execFile(this._adb, ['-s', this.id, 'uninstall', pkg]); 75 | } 76 | 77 | readLogs(options?: AndroidLogOptions): AsyncGenerator; 78 | readLogs(options?: AndroidLogOptions, timeout?: number): AsyncGenerator; 79 | override async *readLogs(options?: AndroidLogOptions, timeout?: number): AsyncGenerator { 80 | const buffer = options?.buffers ? ['-b', options?.buffers?.join(',')] : []; 81 | const recent = options?.historic ? [] : ['-T', '1']; 82 | 83 | if (options?.clear) { 84 | await execFile(this._adb, ['-s', this.id, 'logcat', '-c', ...buffer]); 85 | } 86 | 87 | return yield* readCommandOutput(this._adb, [ 88 | '-s', this.id, 'logcat', 89 | '-v', [options?.format ?? 'threadtime', ...(options?.modifiers ?? [])].join(','), 90 | ...recent, ...buffer, ...(options?.filterspecs ?? []) 91 | ], options, timeout); 92 | } 93 | 94 | override async collectLogs(options?: Omit): Promise<() => Promise> { 95 | return collectLines((stopSignal) => this.readLogs({ separator: '\n', ...options, stopSignal }, 100)); 96 | } 97 | 98 | override async findWebViews(): Promise { 99 | return (await this.shell('cat /proc/net/unix')).split('\n') 100 | .map((line) => /@(.*devtools_remote.*)/.exec(line)?.[1]!).filter(Boolean); 101 | } 102 | 103 | override async bindWebView(webviewId: string, port: number): Promise { 104 | await execFile(this._adb, ['-s', this.id, 'forward', `tcp:${port}`, `localabstract:${webviewId}`]); 105 | 106 | return { host: 'localhost', port } 107 | } 108 | 109 | // MARK: - Android-specific methods 110 | 111 | async shell(command: string): Promise { 112 | return (await execFile(this._adb, ['-s', this.id, 'shell', command])).stdout; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/device.ts: -------------------------------------------------------------------------------- 1 | import type { findWebViewContexts, openWebView } from './api'; 2 | import type { AutomationOptions } from './automation'; 3 | import type { iOSDevice } from './ios-device'; 4 | import { ReaderOptions, sleep } from './utils'; 5 | 6 | /** 7 | * Device manager configuration. 8 | */ 9 | export interface DeviceOptions { 10 | /** 11 | * Where to find the `adb` command. `undefined` means Android support is optional (enabled if `adb` is in the path) and 12 | * `null` disables Android support completely. 13 | */ 14 | adb?: string | null; 15 | 16 | /** Where to find the `ideviceinstaller` command. Used by {@link iOSDevice.install}/{@link iOSDevice.uninstall}. */ 17 | ideviceinstaller?: string; 18 | 19 | /** Where to find the `idevicesyslog` command. Used by {@link iOSDevice.readLogs}/{@link iOSDevice.collectLogs}. */ 20 | idevicesyslog?: string; 21 | 22 | /** Where to find the `ios_instruments_client` command. Used by {@link iOSDevice.start}/{@link iOSDevice.stop}. */ 23 | ios_instruments_client?: string; 24 | 25 | /** 26 | * What port `ios_webkit_debug_proxy` is listening on. `undefined` means iOS support is optional (enabled if 27 | * `ios_webkit_debug_proxy` is listening on port 9221) and `null` disables iOS support completely. 28 | */ 29 | iwdpPort?: number | null; 30 | } 31 | 32 | export interface StartOptions { 33 | /** Optional application arguments. */ 34 | args?: string[]; 35 | 36 | /** Close the application first, if it is already running. */ 37 | restart?: boolean; 38 | 39 | /** Wait for the application to start up before returning. */ 40 | wait?: boolean; 41 | } 42 | 43 | /** 44 | * This class manages Android and iOS devices and applications. 45 | */ 46 | export abstract class Device { 47 | /** 48 | * Finds a single device, given a device ID. 49 | * 50 | * @param deviceId The device ID to find. 51 | * @param options Device manager options. 52 | * @param timeout If specified, the method will wait for the device to appear this many milliseconds (0 means 53 | * forever). 54 | * @returns The device, if found, else `undefined`. 55 | */ 56 | static async findDevice(deviceId: string, options?: DeviceOptions, timeout?: number): Promise { 57 | const expires = timeout === undefined ? 0 : Date.now() + (timeout || 1_000_000_000_000); 58 | 59 | while (true) { 60 | const device = (await Device.findDevices(options)).find((device) => device.id === deviceId); 61 | 62 | if (device || Date.now() >= expires) { 63 | return device; 64 | } else { 65 | await sleep(100); 66 | } 67 | } 68 | } 69 | 70 | /** 71 | * Finds all connected Android and iOS devices. 72 | * 73 | * @param options Device manager options. 74 | * @returns A list of detected devices. 75 | */ 76 | static async findDevices(options?: DeviceOptions): Promise { 77 | const { AndroidDevice } = await import('./android-device'); 78 | const { iOSDevice } = await import('./ios-device'); 79 | 80 | return [ 81 | ...await AndroidDevice.findDevices(options), 82 | ...await iOSDevice.findDevices(options), 83 | ].sort((a, b) => a.id.localeCompare(b.id)); 84 | } 85 | 86 | protected constructor(public id: string, public type: 'android' | 'ios') { 87 | } 88 | 89 | /** 90 | * Returns the Android/iOS version number. 91 | * 92 | * @returns The version number. 93 | */ 94 | abstract osVersion(): Promise; 95 | 96 | /** 97 | * Returns the name of the device. 98 | * 99 | * @returns The device name. 100 | */ 101 | abstract deviceName(): Promise; 102 | 103 | /** 104 | * Installs an application onto the device. 105 | * 106 | * @param archive The path to the application to install (APK/IPA/directory). 107 | * @param options Optional installation options, if the subclass supports it. 108 | */ 109 | abstract install(archive: string, options?: string[]): Promise; 110 | 111 | /** 112 | * Launches an application/activity on the device. 113 | * 114 | * @param app The package/activity identifier or application bundle identifier to launch. 115 | * @param options Optional start options. 116 | */ 117 | abstract start(app: string, options?: StartOptions): Promise; 118 | 119 | /** 120 | * Kills an application on the device. 121 | * 122 | * @param app The package/activity identifier or application bundle identifier to stop. 123 | */ 124 | abstract stop(app: string): Promise; 125 | 126 | /** 127 | * Uninstalls an application from the device. 128 | * 129 | * @param app The package/bundle identifier to uninstall. 130 | */ 131 | abstract uninstall(app: string): Promise; 132 | 133 | /** 134 | * Reads log lines from the device. 135 | * 136 | * @param options Reader options. For device-specific options, see the subclass method. 137 | * @returns An async iterator generating one line at a time. 138 | */ 139 | abstract readLogs(options?: ReaderOptions): AsyncGenerator; 140 | 141 | /** 142 | * Reads log lines from the device, with heartbeats. 143 | * 144 | * @param options Reader options. For device-specific options, see the subclass method. 145 | * @param timeout The timeout, in milliseconds. If no lines has been produced within this time, an `undefined` 146 | * value is generated instead of a string. 147 | * @returns An async iterator generating one line at a time, or `undefined` on timeouts. 148 | */ 149 | abstract readLogs(options?: ReaderOptions, timeout?: number): AsyncGenerator; 150 | 151 | /** 152 | * Begins collecting and buffering logs from the device. When the returned function is called, all lines are 153 | * returned as an array. 154 | * 155 | * By default, this method adds a LF to each collected line, making the array suitable to be dumped to disk as-is. 156 | * 157 | * @param options Reader options. For device-specific options, see the subclass method. 158 | * @returns A function that, when invoked, stops logging and returns all collected lines. 159 | */ 160 | abstract collectLogs(options?: ReaderOptions): Promise<() => Promise>; 161 | 162 | /** 163 | * Finds all debuggable web views on the device. 164 | * 165 | * For additional information, see the subclass documentation of this method. 166 | * 167 | * @returns An array of all debuggable web view identifiers. 168 | */ 169 | abstract findWebViews(): Promise; 170 | 171 | /** 172 | * Binds a web view to the specified port on `localhost`. 173 | * 174 | * For additional information, see the subclass documentation of this method. 175 | * 176 | * @param webviewId The web view identifier to bind. 177 | * @param port The port to bind the web view to. 178 | * @returns Options suitable to pass to {@link findWebViewContexts} or {@link openWebView}. 179 | */ 180 | abstract bindWebView(webviewId: string, port: number): Promise; 181 | } 182 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './android-device'; 2 | export * from './api'; 3 | export { AutomationContext, AutomationOptions } from './automation'; 4 | export * from './device'; 5 | export * from './ios-device'; 6 | export * from './utils'; 7 | -------------------------------------------------------------------------------- /src/ios-device.ts: -------------------------------------------------------------------------------- 1 | import { get } from 'http'; 2 | import type { AndroidDevice } from './android-device'; 3 | import type { findWebViewContexts, openWebView } from './api'; 4 | import { AutomationOptions } from './automation'; 5 | import { Device, DeviceOptions, StartOptions } from './device'; 6 | import { collectLines, execFile, readCommandOutput, ReaderOptions } from './utils'; 7 | 8 | // Good sources of information: 9 | // 10 | // * https://github.com/libimobiledevice/libimobiledevice 11 | // * https://github.com/troybowman/ios_instruments_client 12 | 13 | interface IWDPDevice { 14 | deviceId: string; 15 | deviceName: string; 16 | deviceOSVersion: string; 17 | url: string; 18 | } 19 | 20 | interface IWDPContext { 21 | devtoolsFrontendUrl: string; 22 | faviconUrl: string; 23 | thumbnailUrl: string; 24 | title: string; 25 | url: string; 26 | webSocketDebuggerUrl: string; 27 | appId: string; 28 | } 29 | 30 | async function getJSON(url: string): Promise { 31 | const chunks: Buffer[] = []; 32 | 33 | await new Promise((resolve, reject) => { 34 | get(url, (res) => res.on('data', (chunk) => chunks.push(chunk)).on('end', resolve)).on('error', reject); 35 | }); 36 | 37 | return JSON.parse(Buffer.concat(chunks).toString()); 38 | } 39 | 40 | export interface iOSLogOptions extends ReaderOptions { 41 | /** Only include log lines that contain this string. */ 42 | match?: string; 43 | 44 | /** Processes to include. */ 45 | include?: string[]; 46 | 47 | /** Processes to exclude. */ 48 | exclude?: string[]; 49 | 50 | /** If true, excludes a predefined set of noisy processes in addition to those specified via the {@link exclude} option. */ 51 | quiet?: boolean; 52 | } 53 | 54 | /** 55 | * This class manages iOS devices and applications. 56 | */ 57 | export class iOSDevice extends Device { 58 | /** 59 | * Finds all connected iOS devices by querying the `ios_webkit_debug_proxy` HTTP server. 60 | * 61 | * @param options Device manager options. 62 | * @returns A list of detected iOS devices. 63 | */ 64 | static override async findDevices(options: DeviceOptions = {}): Promise { 65 | const iwdpPort = options.iwdpPort === null ? null : options?.iwdpPort ?? 9221; 66 | const iwdpJSON = `http://localhost:${iwdpPort}/json`; 67 | 68 | try { 69 | return iwdpPort === null ? [] : 70 | (await getJSON(iwdpJSON)) 71 | .map((iwdpDevice) => new iOSDevice(iwdpDevice, iwdpPort, options)); 72 | } catch (err) { 73 | if (!options.iwdpPort) { 74 | return []; // User did not specify port; fail silently 75 | } else { 76 | throw new Error(`Request to ${iwdpJSON} failed; verify that ios_webkit_debug_proxy is running`); 77 | } 78 | } 79 | } 80 | 81 | private constructor(private _iwdpDevice: IWDPDevice, private _iwdpPort: number, private _options: DeviceOptions) { 82 | super(_iwdpDevice.deviceId, 'ios'); 83 | } 84 | 85 | override toString(): string { 86 | return `[iOSDevice ${this.id} «${this._iwdpDevice.deviceName}»]`; 87 | } 88 | 89 | override async osVersion(): Promise { 90 | return this._iwdpDevice.deviceOSVersion; 91 | } 92 | 93 | override async deviceName(): Promise { 94 | return this._iwdpDevice.deviceName; 95 | } 96 | 97 | override async install(archive: string): Promise { 98 | await execFile(this._options.ideviceinstaller ?? 'ideviceinstaller', [ 99 | '-u', this.id, 100 | '-i', archive 101 | ]); 102 | } 103 | 104 | override async start(app: string, options?: StartOptions): Promise { 105 | if (options?.restart || await this._getPID(app) === null) { 106 | await execFile(this._options.ios_instruments_client ?? 'ios_instruments_client', [ 107 | '-d', this.id, 'launch', app, 108 | ]); 109 | 110 | while (options?.wait && !await this._getPID(app)) { 111 | // Keep waiting 112 | } 113 | } 114 | } 115 | 116 | override async stop(app: string): Promise { 117 | const pid = await this._getPID(app); 118 | 119 | if (pid !== null) { 120 | await execFile(this._options.ios_instruments_client ?? 'ios_instruments_client', [ 121 | '-d', this.id, 'kill', pid 122 | ]); 123 | } 124 | } 125 | 126 | override async uninstall(app: string): Promise { 127 | await execFile(this._options.ideviceinstaller ?? 'ideviceinstaller', [ 128 | '-u', this.id, 129 | '-U', app 130 | ]); 131 | } 132 | 133 | readLogs(options?: iOSLogOptions): AsyncGenerator; 134 | readLogs(options?: iOSLogOptions, timeout?: number): AsyncGenerator; 135 | override async *readLogs(options?: iOSLogOptions, timeout?: number): AsyncGenerator { 136 | const quiet = options?.quiet ?? !options?.include; 137 | 138 | return yield* readCommandOutput(this._options.idevicesyslog ?? 'idevicesyslog', [ 139 | '-u', this.id, 140 | ...(options?.match ? ['-m', options.match] : []), 141 | ...(options?.include ? ['-p', options.include.join('|') ] : []), 142 | ...(options?.exclude ? ['-e', options.exclude.join('|') ] : []), 143 | ...(quiet ? ['-q'] : []), 144 | ], options, timeout); 145 | } 146 | 147 | override async collectLogs(options?: Omit): Promise<() => Promise> { 148 | return collectLines((stopSignal) => this.readLogs({ separator: '\n', ...options, stopSignal }, 100)); 149 | } 150 | 151 | /** 152 | * Finds all debuggable web views on the device. 153 | * 154 | * For iOS devices, this method is optional. {@link findWebViewContexts} and {@link openWebView} can access contexts 155 | * from all iOS web views if not restricted by {@link AutomationOptions.appId}. 156 | * 157 | * @returns An array of all debuggable web view identifiers. 158 | */ 159 | override async findWebViews(): Promise { 160 | const [ host, port ] = this._iwdpDevice.url.split(':'); 161 | 162 | return (await getJSON(`http://${host}:${port}/json`)) 163 | .filter((context) => !!context.url) // Skip JSContext 164 | .map((context) => context.appId) 165 | .filter((value, index, array) => array.indexOf(value) === index); 166 | } 167 | 168 | /** 169 | * Returns options to be passed to {@link findWebViewContexts} and {@link openWebView}. Unlike 170 | * {@link AndroidDevice}, no `localhost` port is actually opened and the (optional) {@link webviewId} parameter is 171 | * just used to set the {@link AutomationOptions.appId} option to restrict contexts to the specified web view. 172 | * 173 | * @param webviewId The web view identifier target. 174 | * @returns Options suitable to pass to {@link findWebViewContexts} or {@link openWebView}. 175 | */ 176 | override async bindWebView(webviewId?: string): Promise { 177 | const [ host, port ] = this._iwdpDevice.url.split(':'); 178 | 179 | return { host, port: Number(port), appId: webviewId }; 180 | } 181 | 182 | // MARK: - iOS-specific methods 183 | 184 | private async _getPID(app: string): Promise { 185 | // Wow this sucks. The process list shows ExecutableName, not CFBundleIdentifier. 186 | let appInfo: Record | undefined; 187 | const applist = await execFile(this._options.ios_instruments_client ?? 'ios_instruments_client', ['-d', this.id, 'applist'], { maxBuffer: 100e6 }); 188 | for (const line of applist.stdout.split('\n')) { 189 | if (line === '{') { 190 | appInfo = {}; 191 | } else if (line === '}' && appInfo?.['CFBundleIdentifier'] === `"${app}"`) { 192 | break; 193 | } else if (appInfo) { 194 | const [, key, value ] = /^\s+([^\s]+)\s*=\s*(.*);$/.exec(line) ?? []; 195 | key && (appInfo[key] = value); 196 | } 197 | } 198 | 199 | const procName = appInfo?.['ExecutableName']; 200 | const procList = await execFile(this._options.ios_instruments_client ?? 'ios_instruments_client', ['-d', this.id, 'proclist']); 201 | const procInfo = procList.stdout 202 | .split('\n') 203 | .map((line) => /^\s*(\d+)\s+(.*)/.exec(line)) 204 | .filter((match) => match?.[2] === procName); 205 | 206 | if (procInfo.length > 1) { 207 | throw new Error(`App '${app}' with executable name '${procName}' matched multiple processes: ${procInfo.map((match) => match?.[1])}` ) 208 | } 209 | 210 | return procInfo[0]?.[1] ?? null; 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /src/matchers.cts: -------------------------------------------------------------------------------- 1 | import { createRequire } from 'module'; 2 | import { resolve } from 'path'; 3 | 4 | // Look up playwright, starting inside the @playwright/test package 5 | const playwright = createRequire(require.resolve('@playwright/test')).resolve('playwright'); 6 | const matchersJS = resolve(playwright, '../lib/matchers/matchers.js'); 7 | 8 | export default require(matchersJS); 9 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import { Queue, Signal } from '@divine/synchronization'; 2 | import { execFile as _execFile, spawn } from 'child_process'; 3 | import { mkdir as _mkdir, writeFile as _writeFile } from 'fs'; 4 | import { pipeline as _pipeline } from 'stream'; 5 | import { promisify } from 'util'; 6 | 7 | export const execFile = promisify(_execFile); 8 | export const mkdir = promisify(_mkdir); 9 | export const pipeline = promisify(_pipeline); 10 | export const writeFile = promisify(_writeFile); 11 | 12 | /** 13 | * Throws an error. 14 | * 15 | * @param error The error to throw. 16 | * @throws The provided error. 17 | */ 18 | export function throwError(error: Error): never { 19 | throw error; 20 | } 21 | 22 | /** 23 | * Does nothing for a while. 24 | * 25 | * @param timeout The sleep duration in milliseconds 26 | */ 27 | export function sleep(timeout: number): Promise { 28 | return new Promise((resolve) => setTimeout(resolve, timeout)); 29 | } 30 | 31 | export interface ReaderOptions { 32 | /** A signal to check. Reading will stop when signal is `true.` */ 33 | stopSignal?: Signal; 34 | 35 | /** A line separator to add to each generated line. */ 36 | separator?: string; 37 | } 38 | 39 | /** 40 | * Spawns a command and reads its standard output line by line. 41 | * 42 | * @param command The command to executed. 43 | * @param args Command arguments. 44 | * @param options Reader options. 45 | * @returns An async iterator generating one line at a time. 46 | */ 47 | export function readCommandOutput(command: string, args: string[], options?: ReaderOptions): AsyncGenerator; 48 | 49 | /** 50 | * Spawns a command and reads its standard output line by line, with heartbeats. 51 | * 52 | * @param command The command to executed. 53 | * @param args Command arguments. 54 | * @param options Reader options. 55 | * @param timeout The timeout, in milliseconds. If no lines has been produced within this time, an `undefined` value is 56 | * generated instead of a string. 57 | * @returns An async iterator generating one line at a time, or `undefined` on timeouts. 58 | */ 59 | export function readCommandOutput(command: string, args: string[], options?: ReaderOptions, timeout?: number): AsyncGenerator; 60 | 61 | export async function* readCommandOutput(command: string, args: string[], options?: ReaderOptions, timeout?: number): AsyncGenerator { 62 | const mqueue = new Queue(); 63 | const bgproc = spawn(command, args); 64 | 65 | const killOnExit = () => bgproc.kill(); 66 | bgproc.on('exit', () => process.off('exit', killOnExit)); 67 | process.on('exit', killOnExit); 68 | 69 | const checkStopSignal = (stop: boolean): unknown => stop ? mqueue.push(null) : options?.stopSignal?.wait().then(checkStopSignal); 70 | checkStopSignal(false); 71 | 72 | bgproc.on('exit', (ecode) => mqueue.push(ecode ?? -1)); 73 | bgproc.on('error', (error) => mqueue.push(error)); 74 | bgproc.stdout.on('error', (error) => mqueue.push(error)); 75 | bgproc.stdout.on('data', (chunk) => mqueue.push(String(chunk))); 76 | 77 | try { 78 | const separator = options?.separator ?? ''; 79 | let partialLine = ''; 80 | 81 | while (true) { 82 | const event = await mqueue.shiftOrWait(timeout); 83 | 84 | if (event === 0 || event === null) { 85 | break; 86 | } else if (typeof event === 'number') { 87 | throw new Error(`Failed to run '${bgproc.spawnargs.join(' ')}': Exit code ${event}`); 88 | } else if (event instanceof Error) { 89 | throw event; 90 | } else if (typeof event === 'string') { 91 | const lines = (partialLine + event).split('\n'); 92 | partialLine = lines.pop() ?? ''; 93 | 94 | for (const line of lines) { 95 | yield line + separator; 96 | } 97 | } else { 98 | yield undefined; 99 | } 100 | } 101 | 102 | if (partialLine !== '') { 103 | yield partialLine; 104 | } 105 | } finally { 106 | bgproc.kill(); 107 | } 108 | } 109 | 110 | /** 111 | * Begins collecting and buffering lines from an async iterator, like the one returned by {@link readCommandOutput}. 112 | * When the returned function is called, all lines are returned as an array. 113 | * 114 | * @param stream A callback that should create the async iterator and stop generating lines when the provided signal 115 | * becomes true. 116 | * @returns A function that, when invoked, stops reading and returns all collected lines as an array. 117 | */ 118 | 119 | export function collectLines(stream: (stopSignal: Signal) => AsyncIterable): () => Promise { 120 | const stopSignal = new Signal(); 121 | const lines = (async () => { 122 | const lines: string[] = []; 123 | 124 | for await (const line of stream(stopSignal)) { 125 | if (typeof line === 'string') { 126 | lines.push(line); 127 | } 128 | } 129 | 130 | return lines; 131 | })(); 132 | 133 | return () => (stopSignal.notifyAll(true), lines); 134 | } 135 | -------------------------------------------------------------------------------- /tests/example.automation.e2e.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from '../src/test'; 2 | 3 | test('has title', async ({ webApp }) => { 4 | // Expect a title "to contain" a substring. 5 | await expect(webApp.locator('title')).toHaveText(/Capacitor/); 6 | }); 7 | 8 | test('get started link', async ({ webApp }) => { 9 | // Expect the "get started" button to link to https://capacitorjs.com. 10 | await expect(webApp.locator('.button', { hasText: 'Read more' })).toHaveAttribute('href', 'https://capacitorjs.com'); 11 | }); 12 | -------------------------------------------------------------------------------- /tests/example.playwright.spec.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | 3 | test('has title', async ({ page }) => { 4 | await page.goto('https://playwright.dev/'); 5 | 6 | // Expect a title "to contain" a substring. 7 | await expect(page).toHaveTitle(/Playwright/); 8 | }); 9 | 10 | test('get started link', async ({ page }) => { 11 | await page.goto('https://playwright.dev/'); 12 | 13 | // Click the get started link. 14 | await page.getByRole('link', { name: 'Get started' }).click(); 15 | 16 | // Expects page to have a heading with the name of Installation. 17 | await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible(); 18 | }); 19 | -------------------------------------------------------------------------------- /tests/playwright.android.ts: -------------------------------------------------------------------------------- 1 | import { WorkerInfo } from '@playwright/test'; 2 | import { execFile, sleep } from '../src'; 3 | import { DeviceWorkerLauncher, DeviceWorkerLauncherOptions } from '../src/test'; 4 | 5 | export interface AndroidLauncherOptions extends DeviceWorkerLauncherOptions { 6 | emulator?: { 7 | name: (worker: number) => string, 8 | system: string, 9 | device: string, 10 | ports?: number[], 11 | }, 12 | } 13 | 14 | export class AndroidLauncher extends DeviceWorkerLauncher { 15 | private emulators: (ReturnType | undefined)[] = []; 16 | 17 | override async setup(worker: number, headless: boolean, workerInfo: WorkerInfo) { 18 | const dwConfig = this.deviceWorkerConfig(workerInfo); 19 | 20 | if (this.options?.emulator) { 21 | const emulatorPort = 5300 + worker * 2; 22 | const deviceId = `emulator-${emulatorPort}`; 23 | 24 | dwConfig?.console?.info?.(`⚙️ Creating AVD ${this.options.emulator.name(worker)}`); 25 | await execFile('avdmanager', ['--silent', 'create', 'avd', 26 | '--force', 27 | '--name', this.options.emulator.name(worker), 28 | '--package', this.options.emulator.system, 29 | '--device', this.options.emulator.device, 30 | ]); 31 | 32 | // Ensure ADB server is running before starting emulator 33 | await execFile('adb', ['start-server']); 34 | 35 | dwConfig?.console?.info?.(`⚙️ Starting ${headless ? 'headless ' : ''}emulator ${this.options.emulator.name(worker)} as device ${deviceId}`); 36 | this.emulators[worker]?.child.kill(); 37 | this.emulators[worker] = execFile('emulator', [ 38 | '-avd', this.options.emulator.name(worker), 39 | '-port', `${emulatorPort}`, 40 | '-no-snapshot', 41 | ...headless ? [ '-no-window' ] : [], 42 | ]); 43 | 44 | for (let i = 0; (await execFile('adb', ['-s', deviceId, 'wait-for-device', 'shell', 'getprop', 'sys.boot_completed'])).stdout.trim() !== '1'; ++i) { 45 | i % 10 || dwConfig?.console?.debug?.(`🐢 Waiting for device ${deviceId} to boot ...`); 46 | await sleep(1000); 47 | } 48 | 49 | for (const port of this.options.emulator.ports ?? []) { 50 | dwConfig?.console?.info?.(`⚙️ Forwarding localhost port ${port} from device ${deviceId} to host`); 51 | await execFile('adb', ['-s', deviceId, 'reverse', `tcp:${port}`, `tcp:${port}`]); 52 | } 53 | 54 | return deviceId; 55 | } else { 56 | return super.setup(worker, headless, workerInfo); 57 | } 58 | } 59 | 60 | override async teardown(worker: number, workerInfo: WorkerInfo) { 61 | const dwConfig = this.deviceWorkerConfig(workerInfo); 62 | 63 | if (this.options?.emulator) { 64 | dwConfig?.console?.info?.(`⚙️ Stopping emulator ${this.options.emulator.name(worker)}`); 65 | this.emulators[worker]?.child.kill(); 66 | await this.emulators[worker]?.catch(dwConfig?.console?.error ?? console.error); 67 | 68 | dwConfig?.console?.info?.(`⚙️ Deleting AVD ${this.options.emulator.name(worker)}`); 69 | await execFile('avdmanager', ['delete', 'avd', '--name', this.options.emulator.name(worker)]); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /tests/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, devices } from '@playwright/test'; 2 | import { DeviceWorkerLauncher, DeviceWorkerOptions, setFixtureTimeout } from '../src/test'; 3 | import { AndroidLauncher } from './playwright.android.ts'; 4 | import { iOSLauncher } from './playwright.ios.ts'; 5 | 6 | // Launch an Android emulator and install a test app on it 7 | const androidLauncher = new AndroidLauncher({ 8 | archive: __dirname + '/testapp/android/app/build/outputs/apk/debug/app-debug.apk', 9 | app: 'com.onslip.automation.testapp/.MainActivity', 10 | 11 | emulator: { 12 | name: (worker) => `automation-${worker}`, 13 | system: 'system-images;android-34;google_apis;arm64-v8a', 14 | device: '10.1in WXGA (Tablet)', 15 | }, 16 | }); 17 | 18 | // Launch an iOS simulator and install a test app on it (except that it doesn't work) 19 | const iosLauncher = new iOSLauncher({ 20 | archive: __dirname + '/testapp/ios/App/DerivedData/App/Build/Products/Debug-iphonesimulator/App.app', 21 | app: 'com.onslip.automation.testapp', 22 | 23 | emulator: { 24 | name: (worker) => `automation-${worker}`, 25 | system: 'com.apple.CoreSimulator.SimRuntime.iOS-17-5', 26 | device: 'iPad Pro 11-inch (M4)', 27 | }, 28 | }); 29 | 30 | // Test an app that is already running on an external device (this works with both Android and iOS) 31 | const externalLauncher = new DeviceWorkerLauncher({ 32 | devices: [ 'feba19fc98c93945dc42dd7f9940d658b5dd211b' ], 33 | }) 34 | 35 | // Set fixture timeouts so that the launchers have enough time to start up 36 | setFixtureTimeout('device', 120_000); 37 | setFixtureTimeout('webApp', 60_000); 38 | 39 | export default defineConfig<{}, DeviceWorkerOptions>({ 40 | webServer: { 41 | command: 'pnpm -C testapp run preview --port 3000 --strictPort', 42 | url: 'http://localhost:3000/', 43 | }, 44 | use: { 45 | baseURL: 'http://localhost:3000/', 46 | headless: false, 47 | }, 48 | projects: [{ 49 | name: 'Desktop Chrome', 50 | use: { ...devices['Desktop Chrome'] }, 51 | }, { 52 | name: 'Desktop Firefox', 53 | use: { ...devices['Desktop Firefox'] }, 54 | }, { 55 | name: 'Desktop Safari', 56 | use: { ...devices['Desktop Safari'] }, 57 | }, { 58 | name: 'Android WebApp', 59 | testMatch: '**/*.e2e.ts', 60 | use: { ...devices['Galaxy Tab S4 landscape'], 61 | deviceWorkerConfig: { 62 | console, // Debug launcher & automation 63 | launcher: androidLauncher, 64 | }, 65 | }, 66 | }, { 67 | name: 'iPad WebApp', 68 | testMatch: '**/*.e2e.ts', 69 | testIgnore: '*', // Project disabled! 70 | use: { ...devices['iPad Pro 11 landscape'], 71 | deviceWorkerConfig: { 72 | console, // Debug launcher & automation 73 | launcher: iosLauncher, 74 | } 75 | }, 76 | }, { 77 | name: 'External WebApp', 78 | testMatch: '**/*.e2e.ts', 79 | testIgnore: '*', // Project disabled! 80 | use: { ...devices['Nexus 10'], 81 | deviceWorkerConfig: { 82 | console, // Debug launcher & automation 83 | launcher: externalLauncher, 84 | } 85 | }, 86 | }], 87 | }); 88 | -------------------------------------------------------------------------------- /tests/playwright.ios.ts: -------------------------------------------------------------------------------- 1 | import { WorkerInfo } from '@playwright/test'; 2 | import { execFile } from '../src'; 3 | import { DeviceWorkerLauncher, DeviceWorkerLauncherOptions } from '../src/test'; 4 | 5 | export interface iOSLauncherOptions extends DeviceWorkerLauncherOptions { 6 | emulator?: { 7 | name: (worker: number) => string, 8 | system: string, 9 | device: string, 10 | }, 11 | } 12 | 13 | export class iOSLauncher extends DeviceWorkerLauncher { 14 | private simulators: (string | undefined)[] = []; 15 | 16 | override async setup(worker: number, headless: boolean, workerInfo: WorkerInfo) { 17 | const dwConfig = this.deviceWorkerConfig(workerInfo); 18 | 19 | if (this.options?.emulator) { 20 | dwConfig?.console?.info?.(`⚙️ Creating simulator ${this.options.emulator.name(worker)}`); 21 | const deviceId = this.simulators[worker] = (await execFile('xcrun', [ 22 | 'simctl', 'create', 23 | this.options.emulator.name(worker), 24 | this.options.emulator.device, 25 | this.options.emulator.system 26 | ])).stdout.trim(); 27 | 28 | dwConfig?.console?.info?.(`⚙️ Starting simulator ${this.options.emulator.name(worker)} as device ${deviceId}`); 29 | await execFile('xcrun', ['simctl', 'boot', deviceId]); 30 | 31 | if (!headless) { 32 | dwConfig?.console?.info?.(`⚙️ Opening simulator UI for device ${deviceId}`); 33 | await execFile('open', ['-a', 'Simulator', `--args`, `-CurrentDeviceUDID`, deviceId]).catch(dwConfig?.console?.error ?? console.error); 34 | } 35 | 36 | dwConfig?.console?.error?.(`⚙️ The web inspector socket is at ${await this.simulatorSocket(deviceId)},`); 37 | dwConfig?.console?.error?.(`⚙️ but since ios_webkit_debug_proxy doesn't detects iOS simulators properly, this is not really going to work ...`); 38 | 39 | return deviceId; 40 | } else { 41 | return super.setup(worker, headless, workerInfo); 42 | } 43 | } 44 | 45 | override async teardown(worker: number, workerInfo: WorkerInfo) { 46 | const dwConfig = this.deviceWorkerConfig(workerInfo); 47 | 48 | if (this.options?.emulator) { 49 | const deviceId = this.simulators[worker] ?? this.options.emulator.name(worker); 50 | 51 | dwConfig?.console?.info?.(`⚙️ Stopping simulator ${deviceId}`); 52 | await execFile('xcrun', ['simctl', 'shutdown', deviceId]).catch(dwConfig?.console?.error ?? console.error); 53 | 54 | dwConfig?.console?.info?.(`⚙️ Deleting simulator ${deviceId}`); 55 | await execFile('xcrun', ['simctl', 'delete', deviceId]); 56 | } 57 | } 58 | 59 | private async simulatorSocket(deviceId: string) { 60 | const lsof = (await execFile('lsof', ['-aUc', 'launchd_sim'])).stdout.split('\n'); 61 | const proc = lsof.find((line) => RegExp(`com\.apple\.CoreSimulator\.SimDevice\.${deviceId}`).test(line))?.split(/\s+/)[1]; 62 | const sock = lsof.find((line) => RegExp(`^[^ ]+\\s+${proc}\\s.*com\.apple\.webinspectord_sim\.socket`).test(line))?.split(/\s+/)[7]; 63 | 64 | // Example lsof output: 65 | // launchd_s 88333 mb 4u unix 0xda3c088bc3fdbaf0 0t0 /tmp/com.apple.CoreSimulator.SimDevice.5B7EBC7F-6778-42E7-8CCC-56ACDC3C9ED0/syslogsock 66 | // launchd_s 88333 mb 5u unix 0x360627c6ecf0e28 0t0 /private/tmp/com.apple.launchd.VNtrfJseJr/com.apple.webinspectord_sim.socket 67 | 68 | if (!sock) { 69 | throw new Error(`Failed to find web inspector socket for simulator ${deviceId}`); 70 | } 71 | 72 | return sock; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tests/side-by-side.e2e.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from '../src/test'; 2 | 3 | test.beforeEach(({ page }) => page.goto('/')); 4 | 5 | test('has text', async ({ page, webApp: auto }) => { 6 | await expect(page.locator('title')).toHaveText(/Capacitor/, { useInnerText: true }); 7 | await expect(auto.locator('title')).toHaveText(/Capacitor/, { useInnerText: true });; 8 | }); 9 | 10 | test('has attribute', async ({ page, webApp: auto }) => { 11 | await expect(page.locator('.button', { hasText: 'Read more' })).toHaveAttribute('href', 'https://capacitorjs.com'); 12 | await expect(auto.locator('.button', { hasText: 'Read more' })).toHaveAttribute('href', 'https://capacitorjs.com'); 13 | }); 14 | -------------------------------------------------------------------------------- /tests/testapp/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | node_modules/ 3 | .vscode/ 4 | *.map 5 | .DS_Store 6 | .sourcemaps 7 | dist/ 8 | -------------------------------------------------------------------------------- /tests/testapp/README.md: -------------------------------------------------------------------------------- 1 | ## Created with Capacitor Create App 2 | 3 | This app was created using [`@capacitor/create-app`](https://github.com/ionic-team/create-capacitor-app), 4 | and comes with a very minimal shell for building an app. 5 | 6 | ### Running this example 7 | 8 | To run the provided example, you can use `npm start` command. 9 | 10 | ```bash 11 | npm start 12 | ``` 13 | -------------------------------------------------------------------------------- /tests/testapp/android/.gitignore: -------------------------------------------------------------------------------- 1 | # Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore 2 | 3 | # Built application files 4 | *.apk 5 | *.aar 6 | *.ap_ 7 | *.aab 8 | 9 | # Files for the ART/Dalvik VM 10 | *.dex 11 | 12 | # Java class files 13 | *.class 14 | 15 | # Generated files 16 | bin/ 17 | gen/ 18 | out/ 19 | # Uncomment the following line in case you need and you don't have the release build type files in your app 20 | # release/ 21 | 22 | # Gradle files 23 | .gradle/ 24 | build/ 25 | 26 | # Local configuration file (sdk path, etc) 27 | local.properties 28 | 29 | # Proguard folder generated by Eclipse 30 | proguard/ 31 | 32 | # Log Files 33 | *.log 34 | 35 | # Android Studio Navigation editor temp files 36 | .navigation/ 37 | 38 | # Android Studio captures folder 39 | captures/ 40 | 41 | # IntelliJ 42 | *.iml 43 | .idea/workspace.xml 44 | .idea/tasks.xml 45 | .idea/gradle.xml 46 | .idea/assetWizardSettings.xml 47 | .idea/dictionaries 48 | .idea/libraries 49 | # Android Studio 3 in .gitignore file. 50 | .idea/caches 51 | .idea/modules.xml 52 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 53 | .idea/navEditor.xml 54 | 55 | # Keystore files 56 | # Uncomment the following lines if you do not want to check your keystore files in. 57 | #*.jks 58 | #*.keystore 59 | 60 | # External native build folder generated in Android Studio 2.2 and later 61 | .externalNativeBuild 62 | .cxx/ 63 | 64 | # Google Services (e.g. APIs or Firebase) 65 | # google-services.json 66 | 67 | # Freeline 68 | freeline.py 69 | freeline/ 70 | freeline_project_description.json 71 | 72 | # fastlane 73 | fastlane/report.xml 74 | fastlane/Preview.html 75 | fastlane/screenshots 76 | fastlane/test_output 77 | fastlane/readme.md 78 | 79 | # Version control 80 | vcs.xml 81 | 82 | # lint 83 | lint/intermediates/ 84 | lint/generated/ 85 | lint/outputs/ 86 | lint/tmp/ 87 | # lint/reports/ 88 | 89 | # Android Profiling 90 | *.hprof 91 | 92 | # Cordova plugins for Capacitor 93 | capacitor-cordova-android-plugins 94 | 95 | # Copied web assets 96 | app/src/main/assets/public 97 | 98 | # Generated Config files 99 | app/src/main/assets/capacitor.config.json 100 | app/src/main/assets/capacitor.plugins.json 101 | app/src/main/res/xml/config.xml 102 | -------------------------------------------------------------------------------- /tests/testapp/android/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build/* 2 | !/build/.npmkeep 3 | -------------------------------------------------------------------------------- /tests/testapp/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | namespace "com.onslip.automation.testapp" 5 | compileSdk rootProject.ext.compileSdkVersion 6 | defaultConfig { 7 | applicationId "com.onslip.automation.testapp" 8 | minSdkVersion rootProject.ext.minSdkVersion 9 | targetSdkVersion rootProject.ext.targetSdkVersion 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 13 | aaptOptions { 14 | // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. 15 | // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61 16 | ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~' 17 | } 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | } 26 | 27 | repositories { 28 | flatDir{ 29 | dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs' 30 | } 31 | } 32 | 33 | dependencies { 34 | implementation fileTree(include: ['*.jar'], dir: 'libs') 35 | implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" 36 | implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion" 37 | implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion" 38 | implementation project(':capacitor-android') 39 | testImplementation "junit:junit:$junitVersion" 40 | androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion" 41 | androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" 42 | implementation project(':capacitor-cordova-android-plugins') 43 | } 44 | 45 | apply from: 'capacitor.build.gradle' 46 | 47 | try { 48 | def servicesJSON = file('google-services.json') 49 | if (servicesJSON.text) { 50 | apply plugin: 'com.google.gms.google-services' 51 | } 52 | } catch(Exception e) { 53 | logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work") 54 | } 55 | -------------------------------------------------------------------------------- /tests/testapp/android/app/capacitor.build.gradle: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN 2 | 3 | android { 4 | compileOptions { 5 | sourceCompatibility JavaVersion.VERSION_17 6 | targetCompatibility JavaVersion.VERSION_17 7 | } 8 | } 9 | 10 | apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle" 11 | dependencies { 12 | implementation project(':capacitor-camera') 13 | implementation project(':capacitor-splash-screen') 14 | 15 | } 16 | 17 | 18 | if (hasProperty('postBuildExtras')) { 19 | postBuildExtras() 20 | } 21 | -------------------------------------------------------------------------------- /tests/testapp/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /tests/testapp/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.getcapacitor.myapp; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import android.content.Context; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | import androidx.test.platform.app.InstrumentationRegistry; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * @see Testing documentation 15 | */ 16 | @RunWith(AndroidJUnit4.class) 17 | public class ExampleInstrumentedTest { 18 | 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 23 | 24 | assertEquals("com.getcapacitor.app", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 32 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/java/com/onslip/automation/testapp/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.onslip.automation.testapp; 2 | 3 | import com.getcapacitor.BridgeActivity; 4 | 5 | public class MainActivity extends BridgeActivity {} 6 | -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/drawable-land-hdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/drawable-land-hdpi/splash.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/drawable-land-mdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/drawable-land-mdpi/splash.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/drawable-land-xhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/drawable-land-xhdpi/splash.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/drawable-land-xxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/drawable-land-xxhdpi/splash.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/drawable-land-xxxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/drawable-land-xxxhdpi/splash.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/drawable-port-hdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/drawable-port-hdpi/splash.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/drawable-port-mdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/drawable-port-mdpi/splash.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/drawable-port-xhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/drawable-port-xhdpi/splash.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/drawable-port-xxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/drawable-port-xxhdpi/splash.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/drawable-port-xxxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/drawable-port-xxxhdpi/splash.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/drawable/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/drawable/splash.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | testapp 4 | testapp 5 | com.onslip.automation.testapp 6 | com.onslip.automation.testapp 7 | 8 | -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 17 | 18 | 19 | 22 | -------------------------------------------------------------------------------- /tests/testapp/android/app/src/main/res/xml/file_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /tests/testapp/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.getcapacitor.myapp; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | 14 | @Test 15 | public void addition_isCorrect() throws Exception { 16 | assertEquals(4, 2 + 2); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/testapp/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | mavenCentral() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:8.2.1' 11 | classpath 'com.google.gms:google-services:4.4.0' 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | apply from: "variables.gradle" 19 | 20 | allprojects { 21 | repositories { 22 | google() 23 | mavenCentral() 24 | } 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /tests/testapp/android/capacitor.settings.gradle: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN 2 | include ':capacitor-android' 3 | project(':capacitor-android').projectDir = new File('../node_modules/.pnpm/@capacitor+android@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/android/capacitor') 4 | 5 | include ':capacitor-camera' 6 | project(':capacitor-camera').projectDir = new File('../node_modules/.pnpm/@capacitor+camera@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/camera/android') 7 | 8 | include ':capacitor-splash-screen' 9 | project(':capacitor-splash-screen').projectDir = new File('../node_modules/.pnpm/@capacitor+splash-screen@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/splash-screen/android') 10 | -------------------------------------------------------------------------------- /tests/testapp/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | # AndroidX package structure to make it clearer which packages are bundled with the 20 | # Android operating system, and which are packaged with your app's APK 21 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 22 | android.useAndroidX=true 23 | -------------------------------------------------------------------------------- /tests/testapp/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /tests/testapp/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /tests/testapp/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | # This is normally unused 84 | # shellcheck disable=SC2034 85 | APP_BASE_NAME=${0##*/} 86 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit 87 | 88 | # Use the maximum available, or set MAX_FD != -1 to use that value. 89 | MAX_FD=maximum 90 | 91 | warn () { 92 | echo "$*" 93 | } >&2 94 | 95 | die () { 96 | echo 97 | echo "$*" 98 | echo 99 | exit 1 100 | } >&2 101 | 102 | # OS specific support (must be 'true' or 'false'). 103 | cygwin=false 104 | msys=false 105 | darwin=false 106 | nonstop=false 107 | case "$( uname )" in #( 108 | CYGWIN* ) cygwin=true ;; #( 109 | Darwin* ) darwin=true ;; #( 110 | MSYS* | MINGW* ) msys=true ;; #( 111 | NONSTOP* ) nonstop=true ;; 112 | esac 113 | 114 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 115 | 116 | 117 | # Determine the Java command to use to start the JVM. 118 | if [ -n "$JAVA_HOME" ] ; then 119 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 120 | # IBM's JDK on AIX uses strange locations for the executables 121 | JAVACMD=$JAVA_HOME/jre/sh/java 122 | else 123 | JAVACMD=$JAVA_HOME/bin/java 124 | fi 125 | if [ ! -x "$JAVACMD" ] ; then 126 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 127 | 128 | Please set the JAVA_HOME variable in your environment to match the 129 | location of your Java installation." 130 | fi 131 | else 132 | JAVACMD=java 133 | if ! command -v java >/dev/null 2>&1 134 | then 135 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 136 | 137 | Please set the JAVA_HOME variable in your environment to match the 138 | location of your Java installation." 139 | fi 140 | fi 141 | 142 | # Increase the maximum file descriptors if we can. 143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 144 | case $MAX_FD in #( 145 | max*) 146 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 147 | # shellcheck disable=SC3045 148 | MAX_FD=$( ulimit -H -n ) || 149 | warn "Could not query maximum file descriptor limit" 150 | esac 151 | case $MAX_FD in #( 152 | '' | soft) :;; #( 153 | *) 154 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 155 | # shellcheck disable=SC3045 156 | ulimit -n "$MAX_FD" || 157 | warn "Could not set maximum file descriptor limit to $MAX_FD" 158 | esac 159 | fi 160 | 161 | # Collect all arguments for the java command, stacking in reverse order: 162 | # * args from the command line 163 | # * the main class name 164 | # * -classpath 165 | # * -D...appname settings 166 | # * --module-path (only if needed) 167 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 168 | 169 | # For Cygwin or MSYS, switch paths to Windows format before running java 170 | if "$cygwin" || "$msys" ; then 171 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 172 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 173 | 174 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 175 | 176 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 177 | for arg do 178 | if 179 | case $arg in #( 180 | -*) false ;; # don't mess with options #( 181 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 182 | [ -e "$t" ] ;; #( 183 | *) false ;; 184 | esac 185 | then 186 | arg=$( cygpath --path --ignore --mixed "$arg" ) 187 | fi 188 | # Roll the args list around exactly as many times as the number of 189 | # args, so each arg winds up back in the position where it started, but 190 | # possibly modified. 191 | # 192 | # NB: a `for` loop captures its iteration list before it begins, so 193 | # changing the positional parameters here affects neither the number of 194 | # iterations, nor the values presented in `arg`. 195 | shift # remove old arg 196 | set -- "$@" "$arg" # push replacement arg 197 | done 198 | fi 199 | 200 | 201 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 202 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 203 | 204 | # Collect all arguments for the java command; 205 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 206 | # shell script including quotes and variable substitutions, so put them in 207 | # double quotes to make sure that they get re-expanded; and 208 | # * put everything else in single quotes, so that it's not re-expanded. 209 | 210 | set -- \ 211 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 212 | -classpath "$CLASSPATH" \ 213 | org.gradle.wrapper.GradleWrapperMain \ 214 | "$@" 215 | 216 | # Stop when "xargs" is not available. 217 | if ! command -v xargs >/dev/null 2>&1 218 | then 219 | die "xargs is not available" 220 | fi 221 | 222 | # Use "xargs" to parse quoted args. 223 | # 224 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 225 | # 226 | # In Bash we could simply go: 227 | # 228 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 229 | # set -- "${ARGS[@]}" "$@" 230 | # 231 | # but POSIX shell has neither arrays nor command substitution, so instead we 232 | # post-process each arg (as a line of input to sed) to backslash-escape any 233 | # character that might be a shell metacharacter, then use eval to reverse 234 | # that process (while maintaining the separation between arguments), and wrap 235 | # the whole thing up as a single "set" statement. 236 | # 237 | # This will of course break if any of these variables contains a newline or 238 | # an unmatched quote. 239 | # 240 | 241 | eval "set -- $( 242 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 243 | xargs -n1 | 244 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 245 | tr '\n' ' ' 246 | )" '"$@"' 247 | 248 | exec "$JAVACMD" "$@" 249 | -------------------------------------------------------------------------------- /tests/testapp/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /tests/testapp/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | include ':capacitor-cordova-android-plugins' 3 | project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/') 4 | 5 | apply from: 'capacitor.settings.gradle' -------------------------------------------------------------------------------- /tests/testapp/android/variables.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | minSdkVersion = 22 3 | compileSdkVersion = 34 4 | targetSdkVersion = 34 5 | androidxActivityVersion = '1.8.0' 6 | androidxAppCompatVersion = '1.6.1' 7 | androidxCoordinatorLayoutVersion = '1.2.0' 8 | androidxCoreVersion = '1.12.0' 9 | androidxFragmentVersion = '1.6.2' 10 | coreSplashScreenVersion = '1.0.1' 11 | androidxWebkitVersion = '1.9.0' 12 | junitVersion = '4.13.2' 13 | androidxJunitVersion = '1.1.5' 14 | androidxEspressoCoreVersion = '3.5.1' 15 | cordovaAndroidVersion = '10.1.1' 16 | } -------------------------------------------------------------------------------- /tests/testapp/capacitor.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "appId": "com.onslip.automation.testapp", 3 | "appName": "testapp", 4 | "webDir": "dist", 5 | "plugins": { 6 | "SplashScreen": { 7 | "launchShowDuration": 0 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /tests/testapp/ios/.gitignore: -------------------------------------------------------------------------------- 1 | App/build 2 | App/Pods 3 | App/output 4 | App/App/public 5 | DerivedData 6 | xcuserdata 7 | 8 | # Cordova plugins for Capacitor 9 | capacitor-cordova-ios-plugins 10 | 11 | # Generated Config files 12 | App/App/capacitor.config.json 13 | App/App/config.xml 14 | -------------------------------------------------------------------------------- /tests/testapp/ios/App/App.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/testapp/ios/App/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /tests/testapp/ios/App/App/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Capacitor 3 | 4 | @UIApplicationMain 5 | class AppDelegate: UIResponder, UIApplicationDelegate { 6 | 7 | var window: UIWindow? 8 | 9 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 10 | // Override point for customization after application launch. 11 | return true 12 | } 13 | 14 | func applicationWillResignActive(_ application: UIApplication) { 15 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 16 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 17 | } 18 | 19 | func applicationDidEnterBackground(_ application: UIApplication) { 20 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 21 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 22 | } 23 | 24 | func applicationWillEnterForeground(_ application: UIApplication) { 25 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 26 | } 27 | 28 | func applicationDidBecomeActive(_ application: UIApplication) { 29 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 30 | } 31 | 32 | func applicationWillTerminate(_ application: UIApplication) { 33 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 34 | } 35 | 36 | func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { 37 | // Called when the app was launched with a url. Feel free to add additional processing here, 38 | // but if you want the App API to support tracking app url opens, make sure to keep this call 39 | return ApplicationDelegateProxy.shared.application(app, open: url, options: options) 40 | } 41 | 42 | func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { 43 | // Called when the app was launched with an activity, including Universal Links. 44 | // Feel free to add additional processing here, but if you want the App API to support 45 | // tracking app url opens, make sure to keep this call 46 | return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler) 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /tests/testapp/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png -------------------------------------------------------------------------------- /tests/testapp/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "AppIcon-512@2x.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/testapp/ios/App/App/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /tests/testapp/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "splash-2732x2732-2.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "splash-2732x2732-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "splash-2732x2732.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /tests/testapp/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png -------------------------------------------------------------------------------- /tests/testapp/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png -------------------------------------------------------------------------------- /tests/testapp/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png -------------------------------------------------------------------------------- /tests/testapp/ios/App/App/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /tests/testapp/ios/App/App/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/testapp/ios/App/App/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | testapp 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | UIViewControllerBasedStatusBarAppearance 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /tests/testapp/ios/App/Podfile: -------------------------------------------------------------------------------- 1 | require_relative '../../node_modules/.pnpm/@capacitor+ios@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/ios/scripts/pods_helpers' 2 | 3 | platform :ios, '13.0' 4 | use_frameworks! 5 | 6 | # workaround to avoid Xcode caching of Pods that requires 7 | # Product -> Clean Build Folder after new Cordova plugins installed 8 | # Requires CocoaPods 1.6 or newer 9 | install! 'cocoapods', :disable_input_output_paths => true 10 | 11 | def capacitor_pods 12 | pod 'Capacitor', :path => '../../node_modules/.pnpm/@capacitor+ios@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/ios' 13 | pod 'CapacitorCordova', :path => '../../node_modules/.pnpm/@capacitor+ios@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/ios' 14 | pod 'CapacitorCamera', :path => '../../node_modules/.pnpm/@capacitor+camera@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/camera' 15 | pod 'CapacitorSplashScreen', :path => '../../node_modules/.pnpm/@capacitor+splash-screen@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/splash-screen' 16 | end 17 | 18 | target 'App' do 19 | capacitor_pods 20 | # Add your Pods here 21 | end 22 | 23 | post_install do |installer| 24 | assertDeploymentTarget(installer) 25 | end 26 | -------------------------------------------------------------------------------- /tests/testapp/ios/App/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Capacitor (6.1.2): 3 | - CapacitorCordova 4 | - CapacitorCamera (6.0.2): 5 | - Capacitor 6 | - CapacitorCordova (6.1.2) 7 | - CapacitorSplashScreen (6.0.2): 8 | - Capacitor 9 | 10 | DEPENDENCIES: 11 | - "Capacitor (from `../../node_modules/.pnpm/@capacitor+ios@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/ios`)" 12 | - "CapacitorCamera (from `../../node_modules/.pnpm/@capacitor+camera@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/camera`)" 13 | - "CapacitorCordova (from `../../node_modules/.pnpm/@capacitor+ios@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/ios`)" 14 | - "CapacitorSplashScreen (from `../../node_modules/.pnpm/@capacitor+splash-screen@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/splash-screen`)" 15 | 16 | EXTERNAL SOURCES: 17 | Capacitor: 18 | :path: "../../node_modules/.pnpm/@capacitor+ios@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/ios" 19 | CapacitorCamera: 20 | :path: "../../node_modules/.pnpm/@capacitor+camera@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/camera" 21 | CapacitorCordova: 22 | :path: "../../node_modules/.pnpm/@capacitor+ios@6.1.2_@capacitor+core@6.1.2/node_modules/@capacitor/ios" 23 | CapacitorSplashScreen: 24 | :path: "../../node_modules/.pnpm/@capacitor+splash-screen@6.0.2_@capacitor+core@6.1.2/node_modules/@capacitor/splash-screen" 25 | 26 | SPEC CHECKSUMS: 27 | Capacitor: 679f9673fdf30597493a6362a5d5bf233d46abc2 28 | CapacitorCamera: ed022171dbf3853e68eec877b4d78995378af6b7 29 | CapacitorCordova: f48c89f96c319101cd2f0ce8a2b7449b5fb8b3dd 30 | CapacitorSplashScreen: 250df9ef8014fac5c7c1fd231f0f8b1d8f0b5624 31 | 32 | PODFILE CHECKSUM: 514e1875ca374c9581d383aa30449ad30eb0d78b 33 | 34 | COCOAPODS: 1.15.2 35 | -------------------------------------------------------------------------------- /tests/testapp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "capacitor-app", 3 | "version": "1.0.0", 4 | "description": "An Amazing Capacitor App", 5 | "main": "index.js", 6 | "keywords": [ 7 | "capacitor", 8 | "mobile" 9 | ], 10 | "scripts": { 11 | "start": "vite", 12 | "build": "vite build", 13 | "preview": "vite preview" 14 | }, 15 | "dependencies": { 16 | "@capacitor/android": "^6.1.2", 17 | "@capacitor/camera": "^6.0.2", 18 | "@capacitor/core": "^6.1.2", 19 | "@capacitor/ios": "^6.1.2", 20 | "@capacitor/splash-screen": "^6.0.2", 21 | "build": "^0.1.4" 22 | }, 23 | "devDependencies": { 24 | "@capacitor/cli": "^6.1.2", 25 | "vite": "^5.4.1" 26 | }, 27 | "author": "", 28 | "license": "ISC" 29 | } 30 | -------------------------------------------------------------------------------- /tests/testapp/src/assets/icon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/src/assets/icon/favicon.ico -------------------------------------------------------------------------------- /tests/testapp/src/assets/imgs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Onslip/automation/c8256bc623902b85b80b149926155f1a764d0447/tests/testapp/src/assets/imgs/logo.png -------------------------------------------------------------------------------- /tests/testapp/src/css/style.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | } 6 | -------------------------------------------------------------------------------- /tests/testapp/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Awesome Capacitor App 6 | 10 | 11 | 12 | 13 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /tests/testapp/src/js/capacitor-welcome.js: -------------------------------------------------------------------------------- 1 | import { SplashScreen } from '@capacitor/splash-screen'; 2 | import { Camera } from '@capacitor/camera'; 3 | 4 | window.customElements.define( 5 | 'capacitor-welcome', 6 | class extends HTMLElement { 7 | constructor() { 8 | super(); 9 | 10 | SplashScreen.hide(); 11 | 12 | const root = this.attachShadow({ mode: 'open' }); 13 | 14 | root.innerHTML = ` 15 | 58 |
59 | 60 |

Capacitor

61 |
62 |
63 |

64 | Capacitor makes it easy to build powerful apps for the app stores, mobile web (Progressive Web Apps), and desktop, all 65 | with a single code base. 66 |

67 |

Getting Started

68 |

69 | You'll probably need a UI framework to build a full-featured app. Might we recommend 70 | Ionic? 71 |

72 |

73 | Visit capacitorjs.com for information 74 | on using native features, building plugins, and more. 75 |

76 | Read more 77 |

Tiny Demo

78 |

79 | This demo shows how to call Capacitor plugins. Say cheese! 80 |

81 |

82 | 83 |

84 |

85 | 86 |

87 |
88 |
89 | `; 90 | } 91 | 92 | connectedCallback() { 93 | const self = this; 94 | 95 | self.shadowRoot.querySelector('#take-photo').addEventListener('click', async function (e) { 96 | try { 97 | const photo = await Camera.getPhoto({ 98 | resultType: 'uri', 99 | }); 100 | 101 | const image = self.shadowRoot.querySelector('#image'); 102 | if (!image) { 103 | return; 104 | } 105 | 106 | image.src = photo.webPath; 107 | } catch (e) { 108 | console.warn('User cancelled', e); 109 | } 110 | }); 111 | } 112 | }, 113 | ); 114 | 115 | window.customElements.define( 116 | 'capacitor-welcome-titlebar', 117 | class extends HTMLElement { 118 | constructor() { 119 | super(); 120 | const root = this.attachShadow({ mode: 'open' }); 121 | root.innerHTML = ` 122 | 138 | 139 | `; 140 | } 141 | }, 142 | ); 143 | -------------------------------------------------------------------------------- /tests/testapp/src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "App", 3 | "short_name": "App", 4 | "start_url": "index.html", 5 | "display": "standalone", 6 | "icons": [{ 7 | "src": "assets/imgs/logo.png", 8 | "sizes": "512x512", 9 | "type": "image/png" 10 | }], 11 | "background_color": "#31d53d", 12 | "theme_color": "#31d53d" 13 | } 14 | -------------------------------------------------------------------------------- /tests/testapp/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | 3 | export default defineConfig({ 4 | root: './src', 5 | build: { 6 | outDir: '../dist', 7 | minify: false, 8 | emptyOutDir: true, 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "forceConsistentCasingInFileNames": true, 5 | "noFallthroughCasesInSwitch": true, 6 | "noImplicitOverride": true, 7 | "noImplicitReturns": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.driver.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "build", 5 | "module": "CommonJS", 6 | "target": "ES2019", 7 | "lib": [ "ES2019" ], 8 | 9 | "composite": true, 10 | "declaration": true, 11 | "sourceMap": true, 12 | "declarationMap": true, 13 | 14 | "esModuleInterop": true, 15 | "moduleResolution": "Node", 16 | "resolveJsonModule": true, 17 | }, 18 | "include": [ 19 | "src/**/*.ts", "src/**/*.cts", "src/**/*.json", 20 | ], 21 | } 22 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [], 3 | "references": [ 4 | { "path": "tsconfig.driver.json" }, 5 | { "path": "tsconfig.runtime.json" }, 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.runtime.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "outFile": "build/automation-runtime.js", 5 | "module": "None", 6 | "target": "ES5", 7 | "removeComments": true, 8 | "typeRoots": [], 9 | "lib": [ "ES2015", "DOM" ] 10 | }, 11 | "include": [ 12 | "automation-runtime.ts" 13 | ] 14 | } 15 | --------------------------------------------------------------------------------