Skip to content

Commit 99be37d

Browse files
authored
Merge pull request #531 from Countly/new-release-additions-11.0
SDK update 24.11.0 and fixes
2 parents 26195ad + d09a7d9 commit 99be37d

File tree

12 files changed

+711
-456
lines changed

12 files changed

+711
-456
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
## 24.11.0
2+
- Mitigated an issue where SDK could try to send old stored offline mode data during init if `clear_stored_id` was true
3+
- Mitigated an issue where the SDK could stayed on offline mode after the first init with `offline_mode` set to true
4+
- Mitigated an issue where old Rating widget stickers were not cleared when a new one was presented
5+
6+
- Improved view tracking logic
7+
- Default request method is now set to "POST"
8+
- Healtchecks won't be sent in offline mode anymore
9+
- Added a new interface 'feedback' which includes convenience methods to show feedback widgets:
10+
- showNPS([String nameIDorTag]) - for displaying the first available NPS widget or one with the given name, Tag or ID value
11+
- showSurvey([String nameIDorTag]) - for displaying the first available Survey widget or one with the given name, Tag or ID value
12+
- showRating([String nameIDorTag]) - for displaying the first available Rating widget or one with the given name, Tag or ID value
13+
114
## 24.4.1
215
- Added types for the SDK
316
- Added a new method `set_id(newDeviceId)` for managing device ID changes according to the device ID Type

cypress/e2e/bridged_utils.cy.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function initMain(name, version) {
1515
}
1616

1717
const SDK_NAME = "javascript_native_web";
18-
const SDK_VERSION = "24.4.1";
18+
const SDK_VERSION = "24.11.0";
1919

2020
// tests
2121
describe("Bridged SDK Utilities Tests", () => {

cypress/e2e/device_id_init_scenarios.cy.js

Lines changed: 177 additions & 77 deletions
Large diffs are not rendered by default.

cypress/e2e/health_check.cy.js

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,42 @@ function initMain() {
1010
});
1111
}
1212

13-
describe("Health Check tests ", () => {
13+
describe("Health Check tests", () => {
1414
it("Check if health check is sent at the beginning", () => {
1515
hp.haltAndClearStorage(() => {
1616
initMain();
17-
cy.intercept("https://your.domain.count.ly/i?*").as("getXhr");
18-
cy.wait("@getXhr").then((xhr) => {
19-
const url = new URL(xhr.request.url);
17+
cy.intercept("POST", "https://your.domain.count.ly/i").as("postXhr");
18+
cy.wait("@postXhr").then((xhr) => {
19+
const body = xhr.request.body;
20+
const params = new URLSearchParams(body);
2021

21-
// Test the 'hc' parameter
22-
const hcParam = url.searchParams.get("hc");
23-
const hcParamObj = JSON.parse(hcParam);
22+
const hcParam = params.get("hc");
23+
const hcParamObj = JSON.parse(decodeURIComponent(hcParam));
2424
expect(hcParamObj).to.eql({ el: 0, wl: 0, sc: -1, em: "" });
2525

26-
// Test the 'metrics' parameter
27-
const metricsParam = url.searchParams.get("metrics");
26+
const metricsParam = params.get("metrics");
2827
expect(metricsParam).to.equal("{\"_app_version\":\"0.0\",\"_ua\":\"abcd\"}");
2928

30-
// check nothing in the request queue
3129
cy.fetch_local_request_queue().then((rq) => {
3230
expect(rq.length).to.equal(0);
3331
});
3432
});
3533
});
3634
});
35+
it("Check no health check is sent in offline mode", () => {
36+
hp.haltAndClearStorage(() => {
37+
Countly.init({
38+
app_key: "YOUR_APP_KEY",
39+
url: "https://your.domain.count.ly",
40+
test_mode: true,
41+
offline_mode: true
42+
});
43+
44+
cy.intercept("POST", "https://your.domain.count.ly/i").as("postXhr");
45+
cy.get('@postXhr').should('not.exist');
46+
cy.fetch_local_request_queue().then((rq) => {
47+
expect(rq.length).to.equal(0);
48+
});
49+
});
50+
});
3751
});

cypress/e2e/remaining_requests.cy.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ describe("Remaining requests tests ", () => {
1818
initMain(false);
1919

2020
// We will expect 4 requests: health check, begin_session, end_session, orientation
21-
hp.interceptAndCheckRequests(undefined, undefined, undefined, "?hc=*", "hc", (requestParams) => {
21+
hp.interceptAndCheckRequests("POST", undefined, undefined, "?hc=*", "hc", (requestParams) => {
2222
const params = JSON.parse(requestParams.get("hc"));
2323
assert.isTrue(typeof params.el === "number");
2424
assert.isTrue(typeof params.wl === "number");
@@ -29,19 +29,19 @@ describe("Remaining requests tests ", () => {
2929
cy.wait(1000).then(() => {
3030
// Create a session
3131
Countly.begin_session();
32-
hp.interceptAndCheckRequests(undefined, undefined, undefined, "?begin_session=*", "begin_session", (requestParams) => {
32+
hp.interceptAndCheckRequests("POST", undefined, undefined, "?begin_session=*", "begin_session", (requestParams) => {
3333
expect(requestParams.get("begin_session")).to.equal("1");
3434
expect(requestParams.get("rr")).to.equal("3");
3535
expect(requestParams.get("av")).to.equal(av);
3636
});
3737
// End the session
3838
Countly.end_session(undefined, true);
39-
hp.interceptAndCheckRequests(undefined, undefined, undefined, "?end_session=*", "end", (requestParams) => {
39+
hp.interceptAndCheckRequests("POST", undefined, undefined, "?end_session=*", "end", (requestParams) => {
4040
expect(requestParams.get("end_session")).to.equal("1");
4141
expect(requestParams.get("rr")).to.equal("2");
4242
expect(requestParams.get("av")).to.equal(av);
4343
});
44-
hp.interceptAndCheckRequests(undefined, undefined, undefined, undefined, "orientation", (requestParams) => {
44+
hp.interceptAndCheckRequests("POST", undefined, undefined, undefined, "orientation", (requestParams) => {
4545
expect(JSON.parse(requestParams.get("events"))[0].key).to.equal("[CLY]_orientation");
4646
expect(requestParams.get("rr")).to.equal("1");
4747
expect(requestParams.get("av")).to.equal(av);

cypress/support/helper.js

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -68,31 +68,43 @@ var waitFunction = function(startTime, waitTime, waitIncrement, continueCallback
6868
};
6969

7070
/**
71-
* This intercepts the request the SDK makes and returns the request parameters to the callback function
72-
* @param {String} requestType - GET, POST, PUT, DELETE
73-
* @param {String} requestUrl - request url (https://your.domain.count.ly)
74-
* @param {String} endPoint - endpoint (/i)
75-
* @param {String} requestParams - request parameters (?begin_session=**)
71+
* Intercepts SDK requests and returns request parameters to the callback function.
72+
* @param {String} requestType - GET or POST
73+
* @param {String} requestUrl - base URL (e.g., https://your.domain.count.ly)
74+
* @param {String} endPoint - endpoint (e.g., /i)
75+
* @param {String} aliasParam - parameter to match in requests (e.g., "hc", "begin_session")
7676
* @param {String} alias - alias for the request
77-
* @param {Function} callback - callback function
77+
* @param {Function} callback - callback function for parsed parameters
7878
*/
79-
function interceptAndCheckRequests(requestType, requestUrl, endPoint, requestParams, alias, callback) {
80-
// requestType = requestType || "GET";
81-
requestUrl = requestUrl || "https://your.domain.count.ly"; // TODO: might be needed in the future but not yet
79+
function interceptAndCheckRequests(requestType, requestUrl, endPoint, aliasParam, alias, callback) {
80+
requestType = requestType || "GET";
81+
requestUrl = requestUrl || "https://your.domain.count.ly";
8282
endPoint = endPoint || "/i";
83-
requestParams = requestParams || "?*";
8483
alias = alias || "getXhr";
8584

86-
cy.intercept(requestUrl + endPoint + requestParams, (req) => {
87-
// const { url } = req;
88-
req.reply(200, {result: "Success"}, {
85+
// Intercept requests
86+
cy.intercept(requestType, requestUrl + endPoint + "*", (req) => {
87+
if (requestType === "POST" && req.body) {
88+
// Parse URL-encoded body for POST requests
89+
const params = new URLSearchParams(req.body);
90+
callback(params);
91+
} else {
92+
// Parse URL parameters for GET requests
93+
const url = new URL(req.url);
94+
const params = url.searchParams;
95+
callback(params);
96+
}
97+
req.reply(200, { result: "Success" }, {
8998
"x-countly-rr": "2"
9099
});
91100
}).as(alias);
101+
102+
// Wait for the request alias to be triggered
92103
cy.wait("@" + alias).then((xhr) => {
93-
const url = new URL(xhr.request.url);
94-
const searchParams = url.searchParams;
95-
callback(searchParams);
104+
const params = requestType === "POST" && xhr.request.body
105+
? new URLSearchParams(xhr.request.body)
106+
: new URL(xhr.request.url).searchParams;
107+
callback(params);
96108
});
97109
}
98110

examples/examples_feedback_widgets.html

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,21 @@
2222
});
2323

2424
//=================================================
25-
// Fetching and displaying feedback widgets
25+
// Displaying feedback widgets
26+
//=================================================
27+
Countly.feedback.showNPS();
28+
29+
// OR with a specific ID, name or tag
30+
// const id = 'ID_from_server';
31+
// Countly.feedback.showNPS(id);
32+
33+
// Other feedback widgets
34+
// Countly.feedback.showSurvey();
35+
// Countly.feedback.showRating();
36+
37+
38+
//=================================================
39+
// ADVANCED: Fetching and displaying feedback widgets
2640
//=================================================
2741
function fetchAndDisplayWidget() {
2842
// Fetch user's feedbacks widgets from the server (must have been created at server first)

lib/countly.d.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,33 @@ declare module "countly-sdk-web" {
456456
| null
457457
): void;
458458

459+
/**
460+
* Feedback interface with convenience methods for feedback widgets:
461+
* - showNPS([nameIDorTag]) - shows an NPS widget by name, id, or tag, or a random one if not provided
462+
* - showSurvey([nameIDorTag]) - shows a Survey widget by name, id, or tag, or a random one if not provided
463+
* - showRating([nameIDorTag]) - shows a Rating widget by name, id, or tag, or a random one if not provided
464+
*/
465+
const feedback: Feedback;
466+
interface Feedback {
467+
/**
468+
* Displays the first available NPS widget or the one with the provided name, id, or tag.
469+
* @param nameIDorTag - Optional name, id, or tag of the NPS widget to display.
470+
*/
471+
showNPS(nameIDorTag?: string): void;
472+
473+
/**
474+
* Displays the first available Survey widget or the one with the provided name, id, or tag.
475+
* @param nameIDorTag - Optional name, id, or tag of the Survey widget to display.
476+
*/
477+
showSurvey(nameIDorTag?: string): void;
478+
479+
/**
480+
* Displays the first available Rating widget or the one with the provided name, id, or tag.
481+
* @param nameIDorTag - Optional name, id, or tag of the Rating widget to display.
482+
*/
483+
showRating(nameIDorTag?: string): void;
484+
}
485+
459486
/**
460487
* This function retrieves all associated widget information (IDs, type, name etc in an array/list of objects) of your app
461488
* @param {Function} callback - Callback function with two parameters, 1st for returned list, 2nd for error

0 commit comments

Comments
 (0)