Fix Bug 1515411 - Disable Return to AMO for 65 Beta and Release (#4627)
This commit is contained in:
Родитель
9f3d228bad
Коммит
41af1777aa
|
@ -340,10 +340,15 @@ class _ASRouter {
|
|||
}
|
||||
}
|
||||
|
||||
// Group existing blocked messages with messages blocked through preferences
|
||||
const excludeList = ASRouterPreferences.providers.filter(p => p.exclude)
|
||||
.reduce((blocked, p) => blocked.concat(p.exclude), this.state.messageBlockList);
|
||||
|
||||
this.setState(prevState => ({
|
||||
providers,
|
||||
// Clear any messages from removed providers
|
||||
messages: [...prevState.messages.filter(message => providerIDs.includes(message.provider))],
|
||||
messageBlockList: excludeList,
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
@ -153,6 +153,24 @@ function sortMessagesByWeightedRank(messages) {
|
|||
.map(({message}) => message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Messages with targeting should get evaluated first, this way we can have
|
||||
* fallback messages (no targeting at all) that will show up if nothing else
|
||||
* matched
|
||||
*/
|
||||
function sortMessagesByTargeting(messages) {
|
||||
return messages.sort((a, b) => {
|
||||
if (a.targeting && !b.targeting) {
|
||||
return -1;
|
||||
}
|
||||
if (!a.targeting && b.targeting) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
const TargetingGetters = {
|
||||
get locale() {
|
||||
return Services.locale.appLocaleAsLangTag;
|
||||
|
@ -347,7 +365,8 @@ this.ASRouterTargeting = {
|
|||
* @returns {obj} an AS router message
|
||||
*/
|
||||
async findMatchingMessage({messages, trigger, context, onError}) {
|
||||
const sortedMessages = sortMessagesByWeightedRank([...messages]);
|
||||
const weightSortedMessages = sortMessagesByWeightedRank([...messages]);
|
||||
const sortedMessages = sortMessagesByTargeting(weightSortedMessages);
|
||||
|
||||
for (const candidate of sortedMessages) {
|
||||
if (
|
||||
|
|
|
@ -212,6 +212,8 @@ const PREFS_CONFIG = new Map([
|
|||
type: "local",
|
||||
localProvider: "OnboardingMessageProvider",
|
||||
enabled: true,
|
||||
// Block specific messages from this local provider
|
||||
exclude: ["RETURN_TO_AMO_1"],
|
||||
}),
|
||||
}],
|
||||
// See browser/app/profile/firefox.js for other ASR preferences. They must be defined there to enable roll-outs.
|
||||
|
|
|
@ -145,7 +145,6 @@ const ONBOARDING_MESSAGES = async () => ([
|
|||
{
|
||||
id: "FXA_1",
|
||||
template: "fxa_overlay",
|
||||
targeting: "attributionData.campaign != 'non-fx-button' && attributionData.source != 'addons.mozilla.org'",
|
||||
trigger: {id: "firstRun"},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -130,6 +130,14 @@ describe("ASRouter", () => {
|
|||
|
||||
assert.deepEqual(Router.state.messageBlockList, ["foo"]);
|
||||
});
|
||||
it("should set state.messageBlockList to the block list in ASRouterPreferences", async () => {
|
||||
setMessageProviderPref([{id: "onboarding", type: "local", exclude: ["RTAMO"]}]);
|
||||
messageBlockList = ["foo"];
|
||||
Router = new _ASRouter();
|
||||
await Router.init(channel, createFakeStorage(), dispatchStub);
|
||||
|
||||
assert.deepEqual(Router.state.messageBlockList, ["foo", "RTAMO"]);
|
||||
});
|
||||
it("should set state.messageImpressions to the messageImpressions object in persistent storage", async () => {
|
||||
// Note that messageImpressions are only kept if a message exists in router and has a .frequency property,
|
||||
// otherwise they will be cleaned up by .cleanupImpressions()
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {CachedTargetingGetter} from "lib/ASRouterTargeting.jsm";
|
||||
import {ASRouterTargeting, CachedTargetingGetter} from "lib/ASRouterTargeting.jsm";
|
||||
import {OnboardingMessageProvider} from "lib/OnboardingMessageProvider.jsm";
|
||||
|
||||
// Note that tests for the ASRouterTargeting environment can be found in
|
||||
// test/functional/mochitest/browser_asrouter_targeting.js
|
||||
|
@ -50,4 +51,23 @@ describe("#CachedTargetingGetter", () => {
|
|||
assert.calledOnce(global.Cu.reportError);
|
||||
}
|
||||
});
|
||||
it("should check targeted message before message without targeting", async () => {
|
||||
const messages = (await OnboardingMessageProvider.getUntranslatedMessages());
|
||||
const stub = sandbox.stub(ASRouterTargeting, "checkMessageTargeting").resolves();
|
||||
const context = {attributionData: {campaign: "non-fx-button", source: "addons.mozilla.org"}};
|
||||
await ASRouterTargeting.findMatchingMessage({messages, trigger: {id: "firstRun"}, context});
|
||||
|
||||
assert.calledTwice(stub);
|
||||
assert.equal(stub.firstCall.args[0].id, "RETURN_TO_AMO_1");
|
||||
assert.equal(stub.secondCall.args[0].id, "FXA_1");
|
||||
});
|
||||
it("should return FxA message (is fallback)", async () => {
|
||||
const messages = (await OnboardingMessageProvider.getUntranslatedMessages())
|
||||
.filter(m => m.id !== "RETURN_TO_AMO_1");
|
||||
const context = {attributionData: {campaign: "non-fx-button", source: "addons.mozilla.org"}};
|
||||
const result = await ASRouterTargeting.findMatchingMessage({messages, trigger: {id: "firstRun"}, context});
|
||||
|
||||
assert.isDefined(result);
|
||||
assert.equal(result.id, "FXA_1");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import {mountWithIntl} from "test/unit/utils";
|
||||
import React from "react";
|
||||
import {ReturnToAMO} from "content-src/asrouter/templates/ReturnToAMO/ReturnToAMO";
|
||||
|
||||
describe("<ReturnToAMO>", () => {
|
||||
let dispatch;
|
||||
let onReady;
|
||||
beforeEach(() => {
|
||||
dispatch = sinon.stub();
|
||||
onReady = sinon.stub();
|
||||
const content = {
|
||||
primary_button: {},
|
||||
secondary_button: {},
|
||||
};
|
||||
|
||||
mountWithIntl(<ReturnToAMO onReady={onReady} dispatch={dispatch} content={content} />);
|
||||
});
|
||||
|
||||
it("should call onReady on componentDidMount", () => {
|
||||
assert.calledOnce(onReady);
|
||||
});
|
||||
});
|
|
@ -8,19 +8,35 @@ describe("<StartupOverlay>", () => {
|
|||
let dispatch;
|
||||
let onReady;
|
||||
let onBlock;
|
||||
let sandbox;
|
||||
beforeEach(() => {
|
||||
dispatch = sinon.stub();
|
||||
onReady = sinon.stub();
|
||||
onBlock = sinon.stub();
|
||||
sandbox = sinon.sandbox.create();
|
||||
dispatch = sandbox.stub();
|
||||
onReady = sandbox.stub();
|
||||
onBlock = sandbox.stub();
|
||||
|
||||
wrapper = mountWithIntl(<StartupOverlay onBlock={onBlock} onReady={onReady} dispatch={dispatch} />);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it("should not render if state.show is false", () => {
|
||||
wrapper.setState({overlayRemoved: true});
|
||||
assert.isTrue(wrapper.isEmptyRender());
|
||||
});
|
||||
|
||||
it("should call prop.onReady after mount + timeout", async () => {
|
||||
const clock = sandbox.useFakeTimers();
|
||||
wrapper = mountWithIntl(<StartupOverlay onBlock={onBlock} onReady={onReady} dispatch={dispatch} />);
|
||||
wrapper.setState({overlayRemoved: false});
|
||||
|
||||
clock.tick(10);
|
||||
|
||||
assert.calledOnce(onReady);
|
||||
});
|
||||
|
||||
it("should emit UserEvent SKIPPED_SIGNIN when you click the skip button", () => {
|
||||
let skipButton = wrapper.find(".skip-button");
|
||||
assert.ok(skipButton.exists());
|
||||
|
|
|
@ -270,6 +270,11 @@ const TEST_GLOBAL = {
|
|||
return Promise.resolve(stringsIds.map(({id, args}) => ({value: {string_id: id, args}})));
|
||||
}
|
||||
},
|
||||
FxAccountsConfig: {
|
||||
promiseEmailFirstURI(id) {
|
||||
return Promise.resolve(id);
|
||||
},
|
||||
},
|
||||
};
|
||||
overrider.set(TEST_GLOBAL);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче