Skip to content

Commit

Permalink
WIP: forward isInitialRun from instrumentation app to app under test
Browse files Browse the repository at this point in the history
  • Loading branch information
bartekpacia committed Oct 10, 2023
1 parent 7683960 commit 21d4862
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@
import android.os.Bundle;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnitRunner;

import pl.leancode.patrol.contracts.Contracts;
import pl.leancode.patrol.contracts.PatrolAppServiceClientException;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;

import static pl.leancode.patrol.contracts.Contracts.DartGroupEntry;
import static pl.leancode.patrol.contracts.Contracts.RunDartTestResponse;
Expand All @@ -30,6 +28,13 @@
public class PatrolJUnitRunner extends AndroidJUnitRunner {
public PatrolAppServiceClient patrolAppServiceClient;

/**
* <p>
* Available only after onCreate() has been run.
* </p>
*/
protected boolean isInitialRun;

@Override
protected boolean shouldWaitForActivitiesToComplete() {
return false;
Expand All @@ -40,10 +45,10 @@ public void onCreate(Bundle arguments) {
super.onCreate(arguments);

// This is only true when the ATO requests a list of tests from the app during the initial run.
boolean isInitialRun = Boolean.parseBoolean(arguments.getString("listTestsForOrchestrator"));
this.isInitialRun = Boolean.parseBoolean(arguments.getString("listTestsForOrchestrator"));

Logger.INSTANCE.i("--------------------------------");
Logger.INSTANCE.i("PatrolJUnitRunner.onCreate() " + (isInitialRun ? "(initial run)" : ""));
Logger.INSTANCE.i("PatrolJUnitRunner.onCreate() " + (this.isInitialRun ? "(initial run)" : ""));
}

/**
Expand All @@ -69,6 +74,7 @@ public void setUp(Class<?> activityClass) {
// Currently, the only synchronization point we're interested in is when the app under test returns the list of tests.
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.putExtra("isInitialRun", isInitialRun);
intent.setClassName(instrumentation.getTargetContext(), activityClass.getCanonicalName());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
instrumentation.getTargetContext().startActivity(intent);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,52 @@
package pl.leancode.patrol

import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result

class PatrolPlugin : FlutterPlugin, MethodCallHandler {
class PatrolPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
private lateinit var channel: MethodChannel

private var isInitialRun: Boolean? = null

override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "pl.leancode.patrol/main")
channel.setMethodCallHandler(this)
}

override fun onMethodCall(call: MethodCall, result: Result) {
result.notImplemented()
when (call.method) {
"inInitialRun" -> result.success(isInitialRun)
else -> result.notImplemented()
}
}

override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}

override fun onAttachedToActivity(binding: ActivityPluginBinding) {
val intent = binding.activity.intent
if (!intent.hasExtra("isInitialRun")) {
throw IllegalStateException("PatrolPlugin must be initialized with intent having isInitialRun boolean")
}

isInitialRun = intent.getBooleanExtra("isInitialRun", false)
}

override fun onDetachedFromActivityForConfigChanges() {
// Do nothing
}

override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
// Do nothing
}

override fun onDetachedFromActivity() {
// Do nothing
}
}
8 changes: 8 additions & 0 deletions packages/patrol/lib/src/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ void patrolTest(
tags: tags,
(widgetTester) async {
if (!constants.hotRestartEnabled) {
if (await global_state.isInitialRun) {
// Fall through tests during the initial run that discovers tests.
//
// This is required to be able to find all setUpAll callbacks.
return;
}

// If Patrol's native automation feature is enabled, then this test will
// be executed only if the native side requested it to be executed.
// Otherwise, it returns early.
Expand All @@ -153,6 +160,7 @@ void patrolTest(
return;
}
}

if (!kIsWeb && io.Platform.isIOS) {
widgetTester.binding.platformDispatcher.onSemanticsEnabledChanged = () {
// This callback is empty on purpose. It's a workaround for tests
Expand Down
7 changes: 7 additions & 0 deletions packages/patrol/lib/src/global_state.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// ignore: implementation_imports
import 'package:flutter/services.dart';
import 'package:test_api/src/backend/invoker.dart';

/// Maximum test case length for ATO, after transformations.
Expand Down Expand Up @@ -42,3 +43,9 @@ String get currentTestIndividualName {
bool get isCurrentTestPassing {
return Invoker.current!.liveTest.state.result.isPassing;
}

const _channel = MethodChannel('pl.leancode.patrol/main');

Future<bool> get isInitialRun async {
return await _channel.invokeMethod('isInitialRun') as bool;
}
5 changes: 5 additions & 0 deletions packages/patrol_cli/lib/src/test_bundler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ ${generateGroupsCode(testFilePaths).split('\n').map((e) => ' $e').join('\n')}
binding.patrolAppService = appService;
await runAppService(appService);
// An additional callback to discover setUpAlls.
tearDownAll(() {
print('PATROL_DEBUG: calling tearDownAll to print setUpAlls');
});
// Until now, the native test runner was waiting for us, the Dart side, to
// come alive. Now that we did, let's tell it that we're ready to be asked
// about Dart tests.
Expand Down

0 comments on commit 21d4862

Please sign in to comment.