Bug 1357633 - part2 : add tests. draft
authorAlastor Wu <alwu@mozilla.com>
Wed, 10 May 2017 23:43:14 +0800
changeset 575534 bfb4839224ef9522db54c0685fab8c614271392c
parent 575533 83315d73e46186f3aee0b7977a31edab786bd08f
child 627947 f31029e73f48fdf7aa788538755949932192f74c
push id58087
push useralwu@mozilla.com
push dateWed, 10 May 2017 15:44:29 +0000
bugs1357633, 1357639
milestone55.0a1
Bug 1357633 - part2 : add tests. Based on bug1357639, add new test tasks. MozReview-Commit-ID: 9k8ZkF00MwG
mobile/android/tests/browser/robocop/robocop_media_playback_js.html
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/MediaPlaybackTest.java
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/StringHelper.java
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/JavascriptBridge.java
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAudioFocus.java
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testMediaControl.java
new file mode 100644
--- /dev/null
+++ b/mobile/android/tests/browser/robocop/robocop_media_playback_js.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<audio id="testAudio" src="audio.ogg" loop></audio>
+<script type="application/javascript" src="robocop_head.js"></script>
+<script type="text/javascript">
+var audio = document.getElementById("testAudio");
+
+let test = {
+  play_audio : function() {
+    audio.play();
+  },
+
+  pause_audio : function() {
+    audio.pause();
+  },
+
+  adjust_audio_volume : function(volume) {
+    audio.volume = volume;
+  },
+
+  adjust_audio_muted : function(muted) {
+    audio.muted = muted;
+  },
+
+  finish_test: function() {
+    java.disconnect();
+  },
+};
+
+var java = new JavaBridge(test);
+
+</script>
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/MediaPlaybackTest.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/MediaPlaybackTest.java
@@ -6,31 +6,33 @@ package org.mozilla.gecko.tests;
 
 import org.mozilla.gecko.Actions;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.Tabs;
 import org.mozilla.gecko.media.AudioFocusAgent;
 import org.mozilla.gecko.media.AudioFocusAgent.State;
 import org.mozilla.gecko.media.MediaControlService;
+import org.mozilla.gecko.tests.helpers.JavascriptBridge;
 
 import android.content.Intent;
 import android.content.Context;
 
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.graphics.drawable.Icon;
 import android.os.Build;
 import android.service.notification.StatusBarNotification;
 
 import com.robotium.solo.Condition;
 
 abstract class MediaPlaybackTest extends BaseTest {
     private Context mContext;
     private int mPrevIcon = 0;
+    private JavascriptBridge mJs;
 
     private static final int UI_CHANGED_WAIT_MS = 6000;
 
     protected final void info(String msg) {
         mAsserter.dumpLog(msg);
     }
 
     protected final Context getContext() {
@@ -294,9 +296,35 @@ abstract class MediaPlaybackTest extends
         mAsserter.ok(isAvailableToCheckNotification(),
                      "Checking the android version for media control testing",
                      "The API to check system notification is only available after version 23.");
     }
 
     protected final boolean isAvailableToCheckNotification() {
         return Build.VERSION.SDK_INT >= 23;
     }
+
+     /**
+     * Can communicte with JS bey getJS(), but caller should create and destroy
+     * JSBridge manually.
+     */
+    protected JavascriptBridge getJS() {
+        mAsserter.ok(mJs != null,
+                     "JSBridege existence check",
+                     "Should connect JSBridge before using JS!");
+        return mJs;
+    }
+
+    protected void createJSBridge() {
+        mAsserter.ok(mJs == null,
+                     "JSBridege existence check",
+                     "Should not recreate the JSBridge!");
+        mJs = new JavascriptBridge(this, mActions, mAsserter);
+    }
+
+    protected void destroyJSBridge() {
+        mAsserter.ok(mJs != null,
+                     "JSBridege existence check",
+                     "Should create JSBridge before destroy it!");
+        mJs.disconnect();
+        mJs = null;
+    }
 }
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/StringHelper.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/StringHelper.java
@@ -80,16 +80,17 @@ public class StringHelper {
     public final String ROBOCOP_OFFLINE_STORAGE_URL = "/robocop/robocop_offline_storage.html";
     public final String ROBOCOP_PICTURE_LINK_URL = "/robocop/robocop_picture_link.html";
     public final String ROBOCOP_SEARCH_URL = "/robocop/robocop_search.html";
     public final String ROBOCOP_TEXT_PAGE_URL = "/robocop/robocop_text_page.html";
     public final String ROBOCOP_ADOBE_FLASH_URL = "/robocop/robocop_adobe_flash.html";
     public final String ROBOCOP_INPUT_URL = "/robocop/robocop_input.html";
     public final String ROBOCOP_READER_MODE_BASIC_ARTICLE = "/robocop/reader_mode_pages/basic_article.html";
     public final String ROBOCOP_LINK_TO_SLOW_LOADING = "/robocop/robocop_link_to_slow_loading.html";
+    public final String ROBOCOP_MEDIA_PLAYBACK_JS_URL = "/robocop/robocop_media_playback_js.html";
     public final String ROBOCOP_MEDIA_PLAYBACK_LOOP_URL = "/robocop/robocop_media_playback_loop.html";
 
     private final String ROBOCOP_JS_HARNESS_URL = "/robocop/robocop_javascript.html";
 
     // Robocop page images
     public final String ROBOCOP_PICTURE_URL = "/robocop/Firefox.jpg";
 
     // Robocop page titles
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/JavascriptBridge.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/JavascriptBridge.java
@@ -100,16 +100,27 @@ public final class JavascriptBridge {
     // If JavaBridge has been loaded
     private boolean mJavaBridgeLoaded;
 
     /* package */ static void init(final UITestContext context) {
         sActions = context.getActions();
         sAsserter = context.getAsserter();
     }
 
+    public JavascriptBridge(final Object target, final Actions action, final Assert asserter) {
+        sActions = action;
+        sAsserter = asserter;
+        mTarget = target;
+        mMethods = target.getClass().getMethods();
+        mExpecter = sActions.expectGlobalEvent(Actions.EventType.GECKO, EVENT_TYPE);
+        // The JS here is unrelated to a test harness, so we
+        // have our message parser end on assertion failure.
+        mLogParser = new JavascriptMessageParser(sAsserter, true);
+    }
+
     public JavascriptBridge(final Object target) {
         mTarget = target;
         mMethods = target.getClass().getMethods();
         mExpecter = sActions.expectGlobalEvent(Actions.EventType.GECKO, EVENT_TYPE);
         // The JS here is unrelated to a test harness, so we
         // have our message parser end on assertion failure.
         mLogParser = new JavascriptMessageParser(sAsserter, true);
     }
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAudioFocus.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAudioFocus.java
@@ -18,16 +18,19 @@ public class testAudioFocus extends Medi
         info("- run test : testBasicAbility -");
         testBasicAbility();
 
         info("- run test : testAudioFocusChanged -");
         testAudioFocusChanged();
 
         info("- run test : testSwitchTab -");
         testSwitchTab();
+
+        info("- run test : testAdjustMediaVolumeOrMuted -");
+        testAdjustMediaVolumeOrMuted();
     }
 
     private void testBasicAbility() {
         info("- check audio focus in the beginning -");
         mAsserter.is(getAudioFocusAgent().getAudioFocusState(),
                      State.LOST_FOCUS,
                      "Should not own audio focus.");
 
@@ -135,9 +138,63 @@ public class testAudioFocus extends Medi
         addTab(BLANK_URL);
 
         info("- should still own the audio focus -");
         checkAudioFocusStateAfterChanged(true);
 
         info("- close tab -");
         closeAllTabs();
     }
+
+   /**
+     * Audio focus should only be requested when media is audible.
+     */
+    private void testAdjustMediaVolumeOrMuted() {
+        info("- create JSBridge -");
+        createJSBridge();
+
+        info("- load URL -");
+        final String MEDIA_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_MEDIA_PLAYBACK_JS_URL);
+        loadUrlAndWait(MEDIA_URL);
+
+        info("- play media -");
+        getJS().syncCall("play_audio");
+
+        info("- wait until media starts playing -");
+        final Tab tab = Tabs.getInstance().getSelectedTab();
+        waitUntilTabMediaStarted(tab);
+
+        info("- wait tab becomes audible -");
+        checkTabAudioPlayingState(tab, true /* audible */);
+        checkAudioFocusStateAfterChanged(true);
+
+        info("- change media's volume to 0.0 -");
+        getJS().syncCall("adjust_audio_volume", 0.0);
+        checkTabAudioPlayingState(tab, false /* non-audible */);
+        checkAudioFocusStateAfterChanged(false);
+
+        info("- change media's volume to 1.0 -");
+        getJS().syncCall("adjust_audio_volume", 1.0);
+        checkTabAudioPlayingState(tab, true /* audible */);
+        checkAudioFocusStateAfterChanged(true);
+
+        info("- mute media -");
+        getJS().syncCall("adjust_audio_muted", true);
+        checkTabAudioPlayingState(tab, false /* non-audible */);
+        checkAudioFocusStateAfterChanged(false);
+
+        info("- unmute media -");
+        getJS().syncCall("adjust_audio_muted", false);
+        checkTabAudioPlayingState(tab, true /* audible */);
+        checkAudioFocusStateAfterChanged(true);
+
+        info("- pause media -");
+        getJS().syncCall("pause_audio");
+        checkTabAudioPlayingState(tab, false /* non-audible */);
+        checkAudioFocusStateAfterChanged(false);
+
+        info("- close tab -");
+        closeAllTabs();
+
+        info("- destroy JSBridge -");
+        destroyJSBridge();
+    }
 }
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testMediaControl.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testMediaControl.java
@@ -27,16 +27,22 @@ public class testMediaControl extends Me
         info("- run test : testAudioFocusChanged -");
         testAudioFocusChanged();
 
         info("- run test : testSwitchTab -");
         testSwitchTab();
 
         info("- run test : testCloseTab -");
         testCloseTab();
+
+        info("- run test : testResumeMediaFromPage -");
+        testResumeMediaFromPage();
+
+        info("- run test : testAdjustMediaVolumeOrMuted -");
+        testAdjustMediaVolumeOrMuted();
     }
 
     private void testBasicBehaviors() {
         info("- load URL -");
         final String MEDIA_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_MEDIA_PLAYBACK_LOOP_URL);
         loadUrlAndWait(MEDIA_URL);
 
         info("- wait until media starts playing -");
@@ -154,9 +160,94 @@ public class testMediaControl extends Me
 
         info("- media control should disappear -");
         waitUntilNotificationUIChanged();
         checkIfMediaNotificationBeCleared();
 
         info("- close tab -");
         closeAllTabs();
     }
+
+   /**
+     * Media control and audio focus should be changed as well when user resume
+     * media from page, instead of from media control.
+     */
+    private void testResumeMediaFromPage() {
+        info("- create JSBridge -");
+        createJSBridge();
+
+        info("- load URL -");
+        final String MEDIA_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_MEDIA_PLAYBACK_JS_URL);
+        loadUrlAndWait(MEDIA_URL);
+
+        info("- play media -");
+        getJS().syncCall("play_audio");
+
+        info("- wait until media starts playing -");
+        final Tab tab = Tabs.getInstance().getSelectedTab();
+        waitUntilTabMediaStarted(tab);
+        checkIfMediaPlayingSuccess(true /* playing */);
+
+        info("- simulate media control pause -");
+        notifyMediaControlService(MediaControlService.ACTION_PAUSE);
+        checkIfMediaPlayingSuccess(false /* paused */);
+
+        info("- resume media from page -");
+        getJS().syncCall("play_audio");
+        checkIfMediaPlayingSuccess(true /* playing */);
+
+        info("- pause media from page -");
+        getJS().syncCall("pause_audio");
+        checkIfMediaPlayingSuccess(false /* paused */, true /* clear notification */);
+
+        info("- close tab -");
+        closeAllTabs();
+
+        info("- destroy JSBridge -");
+        destroyJSBridge();
+    }
+
+    /**
+     * Media control should always be displayed even the media becomes non-audible.
+     */
+    private void testAdjustMediaVolumeOrMuted() {
+        info("- create JSBridge -");
+        createJSBridge();
+
+        info("- load URL -");
+        final String MEDIA_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_MEDIA_PLAYBACK_JS_URL);
+        loadUrlAndWait(MEDIA_URL);
+
+        info("- play media -");
+        getJS().syncCall("play_audio");
+
+        info("- wait until media starts playing -");
+        final Tab tab = Tabs.getInstance().getSelectedTab();
+        waitUntilTabMediaStarted(tab);
+        checkIfMediaPlayingSuccess(true /* playing */);
+
+        info("- change media's volume to 0.0 -");
+        getJS().syncCall("adjust_audio_volume", 0.0);
+        checkMediaNotificationStates(tab, true);
+
+        info("- change media's volume to 1.0 -");
+        getJS().syncCall("adjust_audio_volume", 1.0);
+        checkMediaNotificationStates(tab, true);
+
+        info("- mute media -");
+        getJS().syncCall("adjust_audio_muted", true);
+        checkMediaNotificationStates(tab, true);
+
+        info("- unmute media -");
+        getJS().syncCall("adjust_audio_muted", false);
+        checkMediaNotificationStates(tab, true);
+
+        info("- pause media -");
+        getJS().syncCall("pause_audio");
+        checkIfMediaPlayingSuccess(false /* paused */, true /* clear notification */);
+
+        info("- close tab -");
+        closeAllTabs();
+
+        info("- destroy JSBridge -");
+        destroyJSBridge();
+    }
 }