diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f29899a..80797e14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## X.X.X - Added a new flag, 'loadAPMScriptsAsync', which can load the APM related scripts automatically for Async implementations +- Adding remaining request queue size information to every request +- Fixed a bug where unnecessary device ID merge information was sent to the server ## 23.2.2 - Default max segmentation value count changed from 30 to 100 diff --git a/cypress/integration/remaining_requests.js b/cypress/integration/remaining_requests.js new file mode 100644 index 00000000..c12fd579 --- /dev/null +++ b/cypress/integration/remaining_requests.js @@ -0,0 +1,71 @@ +/* eslint-disable require-jsdoc */ +var Countly = require("../../lib/countly"); +var hp = require("../support/helper"); + +function initMain(shouldStopRequests) { + Countly.init({ + app_key: "YOUR_APP_KEY", + url: "https://try.count.ly", + // would prevent requests from being sent to the server if true + test_mode: shouldStopRequests + }); +} + +describe("Remaining requests tests ", () => { + it("Checks the requests for rr", () => { + hp.haltAndClearStorage(() => { + initMain(false); + + // Create a session and end it + Countly.begin_session(); + Countly.end_session(undefined, true); + + // We expect 3 requests: begin_session, end_session, orientation + hp.interceptAndCheckRequests(undefined, undefined, undefined, undefined, "begin_session", (requestParams) => { + expect(requestParams.get("begin_session")).to.equal("1"); + expect(requestParams.get("rr")).to.equal("3"); + }); + hp.interceptAndCheckRequests(undefined, undefined, undefined, undefined, "end_session", (requestParams) => { + expect(requestParams.get("end_session")).to.equal("1"); + expect(requestParams.get("rr")).to.equal("2"); + }); + hp.interceptAndCheckRequests(undefined, undefined, undefined, undefined, "orientation", (requestParams) => { + expect(JSON.parse(requestParams.get("events"))[0].key).to.equal("[CLY]_orientation"); + expect(requestParams.get("rr")).to.equal("1"); + }); + cy.wait(100).then(() => { + cy.fetch_local_request_queue().then((rq) => { + expect(rq.length).to.equal(0); + }); + }); + }); + }); + it("No rr if no request was made to the server", () => { + hp.haltAndClearStorage(() => { + initMain(true); + + // Create a session and end it + Countly.begin_session(); + Countly.end_session(undefined, true); + cy.fetch_local_request_queue().then((rq) => { + // We expect 3 requests in queue: begin_session, end_session, orientation + expect(rq.length).to.equal(3); + expect(rq[0].rr).to.equal(3); + expect(rq[1].rr).to.equal(undefined); + expect(rq[2].rr).to.equal(undefined); + + // Change ID + Countly.change_id("newID"); + cy.fetch_local_request_queue().then((rq2) => { + // We expect 4 requests in queue: begin_session, end_session, orientation and change ID + cy.log(rq2); + expect(rq2.length).to.equal(4); + expect(rq2[0].rr).to.equal(3); // still 3 as it was assigned at the time of the first request creation + expect(rq2[1].rr).to.equal(undefined); + expect(rq2[2].rr).to.equal(undefined); + expect(rq2[3].rr).to.equal(undefined); + }); + }); + }); + }); +}); diff --git a/cypress/integration/sessions.js b/cypress/integration/sessions.js index 4ddc55da..81d5dbea 100644 --- a/cypress/integration/sessions.js +++ b/cypress/integration/sessions.js @@ -21,10 +21,10 @@ function initMain() { }); } const dummyQueue = [ - { begin_session: 1, metrics: "{\"_app_version\":\"0.0\",\"_ua\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:96.0) Gecko/20100101 Firefox/96.0\",\"_resolution\":\"1568x882\",\"_density\":1.2244897959183674,\"_locale\":\"en-US\"}", app_key: "YOUR_APP_KEY", device_id: "55669b9b-f9d7-4ed5-bc77-ec5ebb65ddd8", sdk_name: "javascript_native_web", sdk_version: "21.11.0", timestamp: 1644909864950, hour: 10, dow: 2 }, - { events: "[{\"key\":\"[CLY]_orientation\",\"count\":1,\"segmentation\":{\"mode\":\"portrait\"},\"timestamp\":1644909864949,\"hour\":10,\"dow\":2}]", app_key: "YOUR_APP_KEY", device_id: "55669b9b-f9d7-4ed5-bc77-ec5ebb65ddd8", sdk_name: "javascript_native_web", sdk_version: "21.11.0", timestamp: 1644909864958, hour: 10, dow: 2 }, - { session_duration: 4, metrics: "{\"_ua\":\"hey\"}", app_key: "YOUR_APP_KEY", device_id: "55669b9b-f9d7-4ed5-bc77-ec5ebb65ddd8", sdk_name: "javascript_native_web", sdk_version: "21.11.0", timestamp: 1644909868015, hour: 10, dow: 2 }, - { end_session: 1, session_duration: 10, metrics: "{\"_ua\":\"hey\"}", app_key: "YOUR_APP_KEY", device_id: "55669b9b-f9d7-4ed5-bc77-ec5ebb65ddd8", sdk_name: "javascript_native_web", sdk_version: "21.11.0", timestamp: 1644909869459, hour: 10, dow: 2 } + { begin_session: 1, metrics: "{\"_app_version\":\"0.0\",\"_ua\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:96.0) Gecko/20100101 Firefox/96.0\",\"_resolution\":\"1568x882\",\"_density\":1.2244897959183674,\"_locale\":\"en-US\"}", app_key: "YOUR_APP_KEY", device_id: "55669b9b-f9d7-4ed5-bc77-ec5ebb65ddd8", sdk_name: "javascript_native_web", sdk_version: "21.11.0", timestamp: 1644909864950, hour: 10, dow: 2, t: 1, rr: 0 }, + { events: "[{\"key\":\"[CLY]_orientation\",\"count\":1,\"segmentation\":{\"mode\":\"portrait\"},\"timestamp\":1644909864949,\"hour\":10,\"dow\":2}]", app_key: "YOUR_APP_KEY", device_id: "55669b9b-f9d7-4ed5-bc77-ec5ebb65ddd8", sdk_name: "javascript_native_web", sdk_version: "21.11.0", timestamp: 1644909864958, hour: 10, dow: 2, t: 1, rr: 0 }, + { session_duration: 4, metrics: "{\"_ua\":\"hey\"}", app_key: "YOUR_APP_KEY", device_id: "55669b9b-f9d7-4ed5-bc77-ec5ebb65ddd8", sdk_name: "javascript_native_web", sdk_version: "21.11.0", timestamp: 1644909868015, hour: 10, dow: 2, t: 1, rr: 0 }, + { end_session: 1, session_duration: 10, metrics: "{\"_ua\":\"hey\"}", app_key: "YOUR_APP_KEY", device_id: "55669b9b-f9d7-4ed5-bc77-ec5ebb65ddd8", sdk_name: "javascript_native_web", sdk_version: "21.11.0", timestamp: 1644909869459, hour: 10, dow: 2, t: 1, rr: 0 } ]; describe("Session tests ", () => { diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 6cbed946..fa909560 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -31,6 +31,7 @@ Cypress.Commands.add("check_request_commons", (testObject, appKey) => { expect(testObject.device_id).to.be.ok; expect(testObject.sdk_name).to.be.exist; expect(testObject.sdk_version).to.be.ok; + expect(testObject.t).to.be.within(0, 3); const metrics = JSON.parse(testObject.metrics); expect(metrics._ua).to.be.ok; }); diff --git a/cypress/support/helper.js b/cypress/support/helper.js index 5a633bd7..76450573 100644 --- a/cypress/support/helper.js +++ b/cypress/support/helper.js @@ -48,6 +48,30 @@ var waitFunction = function(startTime, waitTime, waitIncrement, continueCallback } }; +/** + * This intercepts the request the SDK makes and returns the request parameters to the callback function + * @param {String} requestType - GET, POST, PUT, DELETE + * @param {String} requestUrl - request url (https://try.count.ly) + * @param {String} endPoint - endpoint (/i) + * @param {String} requestParams - request parameters (?begin_session=**) + * @param {String} alias - alias for the request + * @param {Function} callback - callback function + */ +function interceptAndCheckRequests(requestType, requestUrl, endPoint, requestParams, alias, callback) { + requestType = requestType || "GET"; + requestUrl = requestUrl || "https://try.count.ly"; + endPoint = endPoint || "/i"; + requestParams = requestParams || "?**"; + alias = alias || "getXhr"; + + cy.intercept(requestType, requestUrl + endPoint + requestParams).as(alias); + cy.wait("@" + alias).then((xhr) => { + const url = new URL(xhr.request.url); + const searchParams = url.searchParams; + callback(searchParams); + }); +} + // gathered events. count and segmentation key/values must be consistent const eventArray = [ // first event must be custom event @@ -192,5 +216,6 @@ module.exports = { waitFunction, events, eventArray, - testNormalFlow + testNormalFlow, + interceptAndCheckRequests }; \ No newline at end of file diff --git a/lib/countly.js b/lib/countly.js index 06a25c5d..ee05723f 100644 --- a/lib/countly.js +++ b/lib/countly.js @@ -1121,7 +1121,9 @@ this.disable_offline_mode(newId); return; } - if (this.device_id !== newId) { + // eqeq is used here since we want to catch number to string checks too. type conversion might happen at a new init + // eslint-disable-next-line eqeqeq + if (this.device_id != newId) { if (!merge) { // empty event queue sendEventsForced(); @@ -3774,6 +3776,7 @@ if (!offlineMode && requestQueue.length > 0 && readyToProcess && getTimestamp() > failTimeout) { readyToProcess = false; var params = requestQueue[0]; + params.rr = requestQueue.length; // added at 23.2.3. It would give the current length of the queue. That includes the current request. log(logLevelEnums.DEBUG, "Processing request", params); setValueInStorage("cly_queue", requestQueue, true); if (!self.test_mode) {