diff --git a/docs.json b/docs.json
index 62e674bcf..f638a03cb 100644
--- a/docs.json
+++ b/docs.json
@@ -195,6 +195,10 @@
{
"title": "Browserstack",
"href": "/documentation/integrations/browserstack"
+ },
+ {
+ "title": "LambdaTest",
+ "href": "/documentation/integrations/lambdatest"
}
]
},
diff --git a/docs/documentation/integrations/lambdatest.mdx b/docs/documentation/integrations/lambdatest.mdx
new file mode 100644
index 000000000..497fdb8db
--- /dev/null
+++ b/docs/documentation/integrations/lambdatest.mdx
@@ -0,0 +1,62 @@
+---
+title: Integrations - LambdaTest
+---
+
+# LambdaTest overview
+
+[LambdaTest App Test Automation] is a popular cloud device farm.
+
+This integration is currently Android-only.
+
+### Change runner
+
+Modify the **app-level build.gradle**:
+
+```groovy title="android/app/build.gradle"
+android {
+ // ...
+ defaultConfig {
+ //...
+ testInstrumentationRunner "pl.leancode.patrol.LambdaTestPatrolJUnitRunner"
+ }
+ // ...
+}
+
+// ...
+```
+
+### Upload to LambdaTest
+
+To run Android UI tests on LambdaTest:
+
+1. Upload the app under test APK to LambdaTest ([see docs][LT_app_docs])
+2. Upload the instrumentation app APK to LambdaTest ([see docs][LT_test_docs])
+3. Start test execution on LambdaTest ([see docs][LT_execute_docs])
+
+```
+$ export LAMBDATEST_PROJECT=AwesomeApp # optional
+$ export LAMBDATEST_DEVICES="[\"Pixel 7 Pro-13\"]" # optional
+• Building apk with entrypoint test_bundle.dart...
+✓ Completed building apk with entrypoint test_bundle.dart (11.0s)
+ % Total % Received % Xferd Average Speed Time Time Time Current
+ Dload Upload Total Spent Left Speed
+100 82.4M 100 255 100 82.4M 7 2897k 0:00:31 0:00:36 0:00:02 2051k
+Uploaded app, "app_id": "lt://APP1016047291733313441063634",
+Uploaded testsuite, "app_id": "lt://APP1016047291733312896265135",
+{
+ "status": [
+ "Success"
+ ],
+ "buildId": [
+ "5875687"
+ ],
+ "message": [
+ ""
+ ]
+}
+```
+
+[LT_app_docs]: https://www.lambdatest.com/support/docs/getting-started-with-flutter-dart-android-automation/#step-2-upload-your-application
+[LT_test_docs]: https://www.lambdatest.com/support/docs/getting-started-with-flutter-dart-android-automation/#step-3-uploading-test-suite
+[LT_execute_docs]: https://www.lambdatest.com/support/docs/getting-started-with-flutter-dart-android-automation/#step-4-executing-the-test
+[LambdaTest App Test Automation]: https://www.lambdatest.com/app-test-automation
diff --git a/packages/patrol/android/src/main/kotlin/pl/leancode/patrol/LambdaTestPatrolJUnitRunner.java b/packages/patrol/android/src/main/kotlin/pl/leancode/patrol/LambdaTestPatrolJUnitRunner.java
new file mode 100644
index 000000000..a4837584f
--- /dev/null
+++ b/packages/patrol/android/src/main/kotlin/pl/leancode/patrol/LambdaTestPatrolJUnitRunner.java
@@ -0,0 +1,52 @@
+package pl.leancode.patrol;
+
+import android.util.Log;
+import pl.leancode.patrol.contracts.PatrolAppServiceClientException;
+
+import java.net.Inet4Address;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Enumeration;
+import java.util.Objects;
+
+public class LambdaTestPatrolJUnitRunner extends PatrolJUnitRunner {
+ @Override
+ public PatrolAppServiceClient createAppServiceClient() {
+ // Create client with a default constructor (localhost:8082) by default.
+ PatrolAppServiceClient client = new PatrolAppServiceClient();
+ waitForPatrolAppService();
+
+ try {
+ client.listDartTests();
+ } catch (PatrolAppServiceClientException ex) {
+ ex.printStackTrace();
+ // If the client on localhost:8082 fails, let's apply the wokraround
+ Logger.INSTANCE.i("PatrolAppServiceClientException in createAppServiceClient " + ex.getMessage());
+ Logger.INSTANCE.i("LOOPBACK: " + getLoopback());
+ client = new PatrolAppServiceClient(getLoopback());
+ }
+
+ return client;
+ }
+
+ public String getLoopback() {
+ try {
+ Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
+ while (interfaces.hasMoreElements()) {
+ NetworkInterface i = interfaces.nextElement();
+ Log.d("LOOPBACK", i.getDisplayName());
+ if (Objects.equals(i.getDisplayName(), "tun0")) {
+ for (java.net.InterfaceAddress a : i.getInterfaceAddresses()) {
+ if (a.getAddress() instanceof Inet4Address) {
+ return a.getAddress().toString().substring(1);
+ }
+ }
+ }
+
+ }
+ } catch (SocketException e) {
+ }
+
+ return null;
+ }
+}