Using Espresso idling resource with multiple activities

前端 未结 2 1026
青春惊慌失措
青春惊慌失措 2021-02-06 02:24

I have a firstActivity that launches the secondActivity, where in the secondActivity I have a loading Dialog (not AsyncTask), and I need to make Espresso wait until the dialog d

2条回答
  •  悲&欢浪女
    2021-02-06 03:06

    I stumbled upon this question in my search for a similar answer. Using concepts from Stefano Dacchille's article on IdlingResources, I built the following idling resource that waits for a specific Activity to be active before firing. In my case, I know the dialog is showing when a fragment with a specific tag exists. This isn't the same as the OP's test, but the concepts should translate well.

    public class BusyWhenFragmentExistsInActivityIdlingResource implements IdlingResource {
        private FragmentActivity activity = null;
        private final String fragmentTag;
        private ResourceCallback resourceCallback;
        private boolean wasIdleLastTime = true; // Start off as idle
        private final String name;
        // Need this strong reference because ActivityLifecycleMonitorRegistry won't hold one
        private final ActivityLifecycleCallback activityLifecycleCallback;
    
        public BusyWhenFragmentExistsInActivityIdlingResource(
                final Class clazz,
                final String fragmentTag
        ){
            name = BusyWhenFragmentExistsInActivityIdlingResource.class.getSimpleName()+" "+clazz.getSimpleName();
            this.fragmentTag = fragmentTag;
            activityLifecycleCallback = new ActivityLifecycleCallback() {
                @Override
                public void onActivityLifecycleChanged(Activity activity, Stage stage) {
                    if (!FragmentActivity.class.isAssignableFrom(activity.getClass())) {
                        return;
                    }
                    FragmentActivity fragmentActivity = (FragmentActivity) activity;
                    if (!clazz.isAssignableFrom(fragmentActivity.getClass())) {
                        return;
                    }
                    switch (stage){
                        case RESUMED:
                            BusyWhenFragmentExistsInActivityIdlingResource.this.activity = fragmentActivity;
                            break;
                        case STOPPED:
                            BusyWhenFragmentExistsInActivityIdlingResource.this.activity = null;
                            break;
                    }
                }
            };
    
            ActivityLifecycleMonitorRegistry.getInstance()
                    .addLifecycleCallback(activityLifecycleCallback);
    
        }
        @Override
        public String getName() {
            return name;
        }
    
        @Override
        public boolean isIdleNow() {
            if (activity==null) {
                return wasIdleLastTime = true;
            }
            boolean isIdleThisTime = activity
                    .getSupportFragmentManager()
                    .findFragmentByTag(fragmentTag)==null;
    
            if (!wasIdleLastTime && isIdleThisTime && resourceCallback!=null){
                resourceCallback.onTransitionToIdle();
            }
            return wasIdleLastTime = isIdleThisTime;
        }
    
        @Override
        public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
            this.resourceCallback = resourceCallback;
        }
    }
    

    To use it, add something similar to this to your test:

    @Before
    public void setUp() throws Exception {
        registerIdlingResources(new BusyWhenFragmentExistsInActivityIdlingResource(
                SomeOtherActivity.class,
                BaseActivity.LOADING_DIALOG
        ));
    }
    

提交回复
热议问题