Skip to content

Commit

Permalink
✨ SwG - Add sendBeacon method to AmpFetcher (#26951)
Browse files Browse the repository at this point in the history
* add sendBeacon method to be overriden later

* fix tests and data type checking

* remove comment

* restore sendBeacon to fix unrelated Xhr tests
  • Loading branch information
mborof committed Feb 25, 2020
1 parent b8e3006 commit 6ca272a
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,9 @@ class AmpFetcher {
constructor(win) {
/** @const @private {!../../../src/service/xhr-impl.Xhr} */
this.xhr_ = Services.xhrFor(win);

/** @private @const {!Window} */
this.win_ = win;
}

/** @override */
Expand All @@ -612,6 +615,34 @@ class AmpFetcher {
fetch(input, opt_init) {
return this.xhr_.fetch(input, opt_init); //needed to kepp closure happy
}

/**
* POST data to a URL endpoint, do not wait for a response.
* @param {string} url
* @param {string|!Object} data
*/
sendBeacon(url, data) {
const contentType = 'application/x-www-form-urlencoded;charset=UTF-8';
const body =
'f.req=' +
JSON.stringify(/** @type {JsonObject} */ (data.toArray(false)));
const {navigator} = this.win_;

if (navigator.sendBeacon) {
const blob = new Blob([body], {type: contentType});
navigator.sendBeacon(url, blob);
return;
}

// Only newer browsers support beacon. Fallback to standard XHR POST.
const init = {
method: 'POST',
headers: {'Content-Type': contentType},
credentials: 'include',
body,
};
this.fetch(url, init);
}
}

// Register the extension services.
Expand Down Expand Up @@ -651,6 +682,16 @@ export function getFetcherClassForTesting() {
return Fetcher;
}

/**
* TODO(mborof): remove once not required by test-amp-subscriptions-google.js
* @package
* @visibleForTesting
* @return {*}
*/
export function getAmpFetcherClassForTesting() {
return AmpFetcher;
}

/**
* TODO(dvoytenko): remove once compiler type checking is fixed for third_party.
* @package
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ import {
Entitlement,
GrantReason,
} from '../../../amp-subscriptions/0.1/entitlement';
import {GoogleSubscriptionsPlatform} from '../amp-subscriptions-google';
import {
GoogleSubscriptionsPlatform,
getAmpFetcherClassForTesting,
} from '../amp-subscriptions-google';
import {PageConfig} from '../../../../third_party/subscriptions-project/config';
import {ServiceAdapter} from '../../../amp-subscriptions/0.1/service-adapter';
import {Services} from '../../../../src/services';
Expand All @@ -39,6 +42,71 @@ import {toggleExperiment} from '../../../../src/experiments';
const PLATFORM_ID = 'subscribe.google.com';
const AMP_URL = 'myAMPurl.amp';

describes.realWin('AmpFetcher', {amp: true}, env => {
let win;
let ampdoc;
let fetcher;
let xhr;

const sentUrl = 'url';
const sentArray = [
'embed',
'tx',
'refer',
'utmS',
'utmC',
'utmM',
'sku',
true,
['exp1', 'exp2'],
'version',
'baseUrl',
];
const sentMessage = {
toArray: function() {
return sentArray;
},
};
const contentType = 'application/x-www-form-urlencoded;charset=UTF-8';
const expectedBodyString = 'f.req=' + JSON.stringify(sentArray);
const AmpFetcher = getAmpFetcherClassForTesting();

beforeEach(() => {
win = env.win;
ampdoc = env.ampdoc;
fetcher = new AmpFetcher(ampdoc.win);
xhr = Services.xhrFor(env.win);
});

it('should support beacon when beacon supported', async () => {
const expectedBlob = new Blob([expectedBodyString], {type: contentType});
env.sandbox.stub(win.navigator, 'sendBeacon').callsFake((url, body) => {
expect(url).to.equal(sentUrl);
expect(body).to.deep.equal(expectedBlob);
});
fetcher.sendBeacon(sentUrl, sentMessage);
});

it('should support beacon when beacon not supported', async () => {
const tempFun = win.navigator.sendBeacon;
win.navigator.sendBeacon = null;
env.sandbox.stub(xhr, 'fetch').callsFake((url, init) => {
expect(url).to.equal(sentUrl);
expect(init).to.deep.equal({
method: 'POST',
headers: {'Content-Type': contentType},
credentials: 'include',
body: expectedBodyString,
});
});

fetcher.sendBeacon(sentUrl, sentMessage);

// Restore the original function so we don't break Xhr tests throughout AMP.
win.navigator.sendBeacon = tempFun;
});
});

describes.realWin('amp-subscriptions-google', {amp: true}, env => {
let ampdoc;
let pageConfig;
Expand Down

0 comments on commit 6ca272a

Please sign in to comment.