зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1395409: Add testActivityStreamPocketReferrer. r=liuche
MozReview-Commit-ID: FlcMG5IewRH --HG-- extra : rebase_source : 0d744d9f3d4ffa55a594da566f2eacea0f1a3a17
This commit is contained in:
Родитель
b0442493e5
Коммит
f1b1b8b981
|
@ -8,6 +8,7 @@ package org.mozilla.gecko.activitystream.homepanel.topstories;
|
|||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
@ -19,6 +20,7 @@ import org.mozilla.gecko.AppConstants;
|
|||
import org.mozilla.gecko.Locales;
|
||||
import org.mozilla.gecko.activitystream.homepanel.StreamRecyclerAdapter;
|
||||
import org.mozilla.gecko.activitystream.homepanel.model.TopStory;
|
||||
import org.mozilla.gecko.annotation.RobocopTarget;
|
||||
import org.mozilla.gecko.util.FileUtils;
|
||||
import org.mozilla.gecko.util.ProxySelector;
|
||||
|
||||
|
@ -53,6 +55,13 @@ public class PocketStoriesLoader extends AsyncTaskLoader<List<TopStory>> {
|
|||
|
||||
public static final String POCKET_REFERRER_URI = "https://getpocket.com/recommendations";
|
||||
|
||||
@RobocopTarget
|
||||
@VisibleForTesting public static final String PLACEHOLDER_TITLE = "Placeholder ";
|
||||
private static final String DEFAULT_PLACEHOLDER_URL = "https://www.mozilla.org/#";
|
||||
static {
|
||||
setPlaceholderUrl(DEFAULT_PLACEHOLDER_URL);
|
||||
}
|
||||
|
||||
// Pocket SharedPreferences keys
|
||||
private static final String POCKET_PREFS_FILE = "PocketStories";
|
||||
private static final String CACHE_TIMESTAMP_MILLIS_PREFIX = "timestampMillis-";
|
||||
|
@ -72,9 +81,13 @@ public class PocketStoriesLoader extends AsyncTaskLoader<List<TopStory>> {
|
|||
private static final int CONNECT_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(15);
|
||||
private static final int READ_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(15);
|
||||
|
||||
private static boolean isTesting = false;
|
||||
|
||||
private String localeLang;
|
||||
private final SharedPreferences sharedPreferences;
|
||||
|
||||
private static String placeholderUrl;
|
||||
|
||||
public PocketStoriesLoader(Context context) {
|
||||
super(context);
|
||||
|
||||
|
@ -84,7 +97,8 @@ public class PocketStoriesLoader extends AsyncTaskLoader<List<TopStory>> {
|
|||
|
||||
@Override
|
||||
protected void onStartLoading() {
|
||||
if (APIKEY == null) {
|
||||
// We don't want to hit the network if we're testing.
|
||||
if (APIKEY == null || isTesting) {
|
||||
deliverResult(makePlaceholderStories());
|
||||
return;
|
||||
}
|
||||
|
@ -187,11 +201,25 @@ public class PocketStoriesLoader extends AsyncTaskLoader<List<TopStory>> {
|
|||
|
||||
private static List<TopStory> makePlaceholderStories() {
|
||||
final List<TopStory> stories = new LinkedList<>();
|
||||
final String TITLE_PREFIX = "Placeholder ";
|
||||
for (int i = 0; i < DEFAULT_COUNT; i++) {
|
||||
// Urls must be different for bookmark/pinning UI to work properly. Assume this is true for Pocket stories.
|
||||
stories.add(new TopStory(TITLE_PREFIX + i, "https://www.mozilla.org/#" + i, null));
|
||||
stories.add(new TopStory(PLACEHOLDER_TITLE + i, placeholderUrl + i, null));
|
||||
}
|
||||
return stories;
|
||||
}
|
||||
|
||||
private static void setPlaceholderUrl(String placeholderUrl) {
|
||||
// See use of placeholderUrl for why suffix is necessary.
|
||||
final String requiredSuffix = "#";
|
||||
if (!placeholderUrl.endsWith(requiredSuffix)) {
|
||||
placeholderUrl = placeholderUrl + requiredSuffix;
|
||||
}
|
||||
PocketStoriesLoader.placeholderUrl = placeholderUrl;
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
@VisibleForTesting public static void configureForTesting(final String placeholderUrl) {
|
||||
isTesting = true;
|
||||
setPlaceholderUrl(placeholderUrl);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,6 +108,7 @@ skip-if = android_version == "18"
|
|||
[src/org/mozilla/gecko/tests/testAboutHomePageNavigation.java]
|
||||
disabled=see bug 947550, bug 979038 and bug 977952
|
||||
[src/org/mozilla/gecko/tests/testAboutHomeVisibility.java]
|
||||
[src/org/mozilla/gecko/tests/testActivityStreamPocketReferrer.java]
|
||||
[src/org/mozilla/gecko/tests/testAppMenuPathways.java]
|
||||
[src/org/mozilla/gecko/tests/testBackButtonInEditMode.java]
|
||||
[src/org/mozilla/gecko/tests/testBrowserDatabaseHelperUpgrades.java]
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import android.util.Log;
|
||||
import com.robotium.solo.Condition;
|
||||
import org.mozilla.gecko.activitystream.homepanel.topstories.PocketStoriesLoader;
|
||||
import org.mozilla.gecko.tests.helpers.NavigationHelper;
|
||||
import org.mozilla.gecko.tests.helpers.WaitHelper;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
|
||||
import static org.mozilla.gecko.tests.helpers.AssertionHelper.*;
|
||||
|
||||
/**
|
||||
* It's very important that suggestions from Pocket are opened with a Pocket URI in the referrer: this is
|
||||
* what this test is for.
|
||||
*
|
||||
* We want to verify:
|
||||
* - Clicking or long clicking a Pocket top story has a Pocket referrer.
|
||||
* - Clicking or long clicking other items on top sites does not have a Pocket referrer.
|
||||
*
|
||||
* The ideal test is to set up a server that will assert that clicks that should have a Pocket referrer
|
||||
* have one in the request headers and clicks that should not have a referrer do not have one. However,
|
||||
* it's non-trivial to set up such a server in our harness so we instead intercept Tab:Load JS events
|
||||
* and verify they have the referrer. This isn't ideal because we might drop the ball passing the referrer
|
||||
* to Gecko, or Gecko might drop the ball, but this test should help regressions if we manually test the
|
||||
* referrers are working.
|
||||
*/
|
||||
public class testActivityStreamPocketReferrer extends JavascriptBridgeTest {
|
||||
|
||||
private static final String LOGTAG =
|
||||
StringUtils.safeSubstring(testActivityStreamPocketReferrer.class.getSimpleName(), 0, 23);
|
||||
|
||||
private static final String JS_FILE = "testActivityStreamPocketReferrer.js";
|
||||
|
||||
private boolean wasTabLoadReceived = false;
|
||||
private boolean tabLoadContainsPocketReferrer = false;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
// Override the default placeholder URL so we don't access the network during testing.
|
||||
// Note: this actually only seems to take effect after we load a page and go back to about:home.
|
||||
PocketStoriesLoader.configureForTesting(getAbsoluteHostnameUrl(StringHelper.get().ROBOCOP_BLANK_PAGE_01_URL));
|
||||
}
|
||||
|
||||
public void testActivityStreamPocketReferrer() throws Exception {
|
||||
blockForReadyAndLoadJS(JS_FILE);
|
||||
NavigationHelper.goBack(); // to top sites.
|
||||
|
||||
checkReferrerInTopStories();
|
||||
checkReferrerInTopStoriesContextMenu();
|
||||
|
||||
checkNoReferrerInTopSites(); // relies on changes to Top Sites from previous tests.
|
||||
|
||||
// Ideally, we'd also test that there is no referrer for highlights but it's more
|
||||
// challenging to get an item to show up in highlights (bookmark the page) and to scroll
|
||||
// to open it: to save time, I chose not to implement it.
|
||||
}
|
||||
|
||||
private void checkReferrerInTopStories() {
|
||||
Log.d(LOGTAG, "testReferrerInTopStories");
|
||||
|
||||
WaitHelper.waitForPageLoad(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mSolo.clickOnText(PocketStoriesLoader.PLACEHOLDER_TITLE); // Click Top Story placeholder item.
|
||||
}
|
||||
});
|
||||
|
||||
assertTabLoadEventContainsPocketReferrer(true);
|
||||
NavigationHelper.goBack(); // to top sites.
|
||||
}
|
||||
|
||||
private void checkReferrerInTopStoriesContextMenu() throws Exception {
|
||||
Log.d(LOGTAG, "testReferrerInTopStoriesContextMenu");
|
||||
|
||||
mSolo.clickLongOnText(PocketStoriesLoader.PLACEHOLDER_TITLE); // Open Top Story context menu.
|
||||
mSolo.clickOnText(StringHelper.get().CONTEXT_MENU_OPEN_IN_NEW_TAB);
|
||||
WaitHelper.waitFor("context menu to close after item selection.", new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return !mSolo.searchText(StringHelper.get().CONTEXT_MENU_OPEN_IN_NEW_TAB);
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
// There's no simple way to block until a background page loads so instead, we sleep for 500ms.
|
||||
// Our JS listener is attached the whole time so if the message is sent, we'll receive it and cache it
|
||||
// while we're sleeping.
|
||||
Thread.sleep(500);
|
||||
assertTabLoadEventContainsPocketReferrer(true);
|
||||
}
|
||||
|
||||
private void checkNoReferrerInTopSites() {
|
||||
Log.d(LOGTAG, "testNoReferrerInTopSites");
|
||||
|
||||
WaitHelper.waitForPageLoad(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Through the previous tests, we've added a top site called "Browser Blank Page...".
|
||||
// Only part of that label will be visible, however.
|
||||
mSolo.clickOnText("Browser Bl"); // Click on a Top Site.
|
||||
}
|
||||
});
|
||||
|
||||
assertTabLoadEventContainsPocketReferrer(false);
|
||||
NavigationHelper.goBack(); // to top sites.
|
||||
}
|
||||
|
||||
private void assertTabLoadEventContainsPocketReferrer(final boolean expectedContainsReferrer) {
|
||||
// We intercept the Tab:Load event in JS and, due to limitations in JavascriptBridge,
|
||||
// store the data there until Java asks for it.
|
||||
getJS().syncCall("copyTabLoadEventMetadataToJava"); // expected to call copyTabLoad...Receiver
|
||||
|
||||
fAssertTrue("Expected Tab:Load to be called", wasTabLoadReceived);
|
||||
fAssertEquals("Checking for expected existence of pocket referrer from Tab:Load event in JS",
|
||||
expectedContainsReferrer, tabLoadContainsPocketReferrer);
|
||||
}
|
||||
|
||||
// JS methods.
|
||||
public void copyTabLoadEventMetadataToJavaReceiver(final boolean wasTabLoadReceived, final boolean tabLoadContainsPocketReferrer) {
|
||||
Log.d(LOGTAG, "setTabLoadContainsPocketReferrer called via JS: " + wasTabLoadReceived + ", " + tabLoadContainsPocketReferrer);
|
||||
this.wasTabLoadReceived = wasTabLoadReceived;
|
||||
this.tabLoadContainsPocketReferrer = tabLoadContainsPocketReferrer;
|
||||
}
|
||||
|
||||
public void log(final String s) {
|
||||
Log.d(LOGTAG, "jsLog: " + s);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Messaging.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let java = new JavaBridge(this);
|
||||
do_register_cleanup(() => {
|
||||
EventDispatcher.instance.unregisterListener(listener);
|
||||
|
||||
java.disconnect();
|
||||
});
|
||||
do_test_pending();
|
||||
|
||||
var wasTabLoadReceived = false;
|
||||
var tabLoadContainsPocketReferrer = false;
|
||||
|
||||
let listener = {
|
||||
onEvent: function(event, data, callback) {
|
||||
java.asyncCall("log", "Tab:Load url: " + data.url);
|
||||
java.asyncCall("log", "Tab:Load referrerURI: " + data.referrerURI);
|
||||
if (event !== "Tab:Load" ||
|
||||
data.url === "about:home") {
|
||||
return;
|
||||
}
|
||||
|
||||
wasTabLoadReceived = true;
|
||||
if (data.referrerURI && data.referrerURI.search("pocket") > 0) {
|
||||
tabLoadContainsPocketReferrer = true;
|
||||
} else {
|
||||
tabLoadContainsPocketReferrer = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
EventDispatcher.for(win).registerListener(listener, ["Tab:Load"]);
|
||||
|
||||
// Java functions.
|
||||
function copyTabLoadEventMetadataToJava() {
|
||||
java.syncCall("copyTabLoadEventMetadataToJavaReceiver", wasTabLoadReceived, tabLoadContainsPocketReferrer);
|
||||
wasTabLoadReceived = false;
|
||||
}
|
Загрузка…
Ссылка в новой задаче