Skip to content

Commit 144858f

Browse files
authored
Merge pull request #598 from Countly/staging
Staging 25.4.3
2 parents a8f0309 + 9470148 commit 144858f

File tree

12 files changed

+531
-397
lines changed

12 files changed

+531
-397
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 25.4.3
2+
3+
- Added filtering capability to `content` interface through `enterContentZone(contentFilterCallback)`.
4+
15
## 25.4.2
26

37
- Mitigated an issue where manual feedback reporting could have failed

cypress.config.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,32 @@ module.exports = defineConfig({
2727
req.on('data', chunk => { body += chunk; });
2828
req.on('end', () => {
2929
requests.push({ method: req.method, url: req.url, headers: req.headers, body });
30+
31+
let payload = { result: 'Success' };
32+
33+
if (req.url && req.url.indexOf('/o/sdk/content') !== -1) {
34+
payload = {
35+
html: 'http://test/_external/content?id=111&uid=tester&app_id=222',
36+
geo: {
37+
l: {
38+
x: 282,
39+
y: 56,
40+
w: 303,
41+
h: 300
42+
},
43+
p: {
44+
x: 62,
45+
y: 325.5,
46+
w: 288,
47+
h: 216
48+
}
49+
}
50+
};
51+
}
52+
3053
setTimeout(() => {
3154
res.writeHead(200, { 'Content-Type': 'application/json' });
32-
res.end(JSON.stringify({ result: 'Success' }));
55+
res.end(JSON.stringify(payload));
3356
}, responseDelay);
3457
});
3558
});

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 = "25.4.2";
18+
const SDK_VERSION = "25.4.3";
1919

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

cypress/e2e/content_filter.cy.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/* eslint-disable cypress/no-unnecessary-waiting */
2+
/* eslint-disable require-jsdoc */
3+
var Countly = require("../../lib/countly");
4+
// import * as Countly from "../../dist/countly_umd.js";
5+
var hp = require("../support/helper.js");
6+
7+
function initMain() {
8+
Countly.init({
9+
app_key: "YOUR_APP_KEY",
10+
url: "http://localhost:9000",
11+
debug: true
12+
});
13+
}
14+
15+
describe("Content Filter Tests", () => {
16+
beforeEach(() => {
17+
cy.wait(1000);
18+
});
19+
20+
afterEach(() => {
21+
cy.task("stopServer");
22+
});
23+
24+
it("Correctly provides params", () => {
25+
hp.haltAndClearStorage(() => {
26+
cy.task("setResponseDelay", 0);
27+
cy.task("startServer");
28+
const filterParams = [];
29+
initMain();
30+
31+
function filter(params) {
32+
filterParams.push(params);
33+
return false;
34+
}
35+
36+
Countly.content.enterContentZone(filter);
37+
38+
cy.wait(5000).then(() => {
39+
expect(filterParams.length).to.be.greaterThan(0);
40+
expect(filterParams[0]).to.have.property("id");
41+
expect(filterParams[0]["id"]).to.equal("111");
42+
expect(filterParams[0]).to.have.property("uid");
43+
expect(filterParams[0]["uid"]).to.equal("tester");
44+
expect(filterParams[0]).to.have.property("app_id");
45+
expect(filterParams[0]["app_id"]).to.equal("222");
46+
cy.task("stopServer");
47+
});
48+
});
49+
});
50+
it("Correctly provides params_async", () => {
51+
hp.haltAndClearStorage(() => {
52+
cy.task("setResponseDelay", 0);
53+
cy.task("startServer");
54+
const filterParams = [];
55+
Countly.q = Countly.q || [];
56+
initMain();
57+
58+
function filter(params) {
59+
filterParams.push(params);
60+
return false;
61+
}
62+
63+
Countly.q.push(["content.enterContentZone", filter]);
64+
65+
cy.wait(5000).then(() => {
66+
expect(filterParams.length).to.be.greaterThan(0);
67+
expect(filterParams[0]).to.have.property("id");
68+
expect(filterParams[0]["id"]).to.equal("111");
69+
expect(filterParams[0]).to.have.property("uid");
70+
expect(filterParams[0]["uid"]).to.equal("tester");
71+
expect(filterParams[0]).to.have.property("app_id");
72+
expect(filterParams[0]["app_id"]).to.equal("222");
73+
cy.task("stopServer");
74+
});
75+
});
76+
});
77+
});

cypress/e2e/request_backoff.cy.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,9 @@ describe("Request Back-off Mechanism Tests", () => {
169169
Countly.attempt_to_send_stored_requests();
170170
cy.task("setResponseDelay", 0);
171171
cy.wait(8000).then(() => {
172-
cy.fetch_local_request_queue().then((rq) => {
173-
cy.log("Request Queue: " + JSON.stringify(rq));
174-
expect(rq.length).to.equal(0);
172+
cy.fetch_local_request_queue().then((rq2) => {
173+
cy.log("Request Queue: " + JSON.stringify(rq2));
174+
expect(rq2.length).to.equal(0);
175175
cy.task("stopServer");
176176
});
177177
});

examples/example_async.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@
2323
//track sessions automatically
2424
Countly.q.push(['track_sessions']);
2525

26+
//content filter example
27+
function filter(params) {
28+
var shouldContentBeShown = true;
29+
console.log("Content filter called with params:", params);
30+
// Add your content filtering logic here and determine whether to show content
31+
return shouldContentBeShown;
32+
}
33+
34+
//enter content zone with filter
35+
Countly.q.push(['content.enterContentZone', filter]);
36+
2637
//track sessions automatically
2738
Countly.q.push(['track_pageview']);
2839

examples/example_sync.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@
2727
Countly.track_pageview();
2828
Countly.track_errors();
2929

30+
//content filter example
31+
function filter(params) {
32+
var shouldContentBeShown = true;
33+
console.log("Content filter called with params:", params);
34+
// Add your content filtering logic here and determine whether to show content
35+
return shouldContentBeShown;
36+
}
37+
38+
//enter content zone with filter
39+
Countly.content.enterContentZone(filter);
40+
3041
document.getElementById("testButton").addEventListener("click", function () {
3142
Countly.add_event({
3243
key: "buttonClick",

lib/countly.d.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,16 +491,17 @@ declare module "countly-sdk-web" {
491491

492492
/**
493493
* Content interface with convenience methods for content zones:
494-
* - enterContentZone() - enters a content zone
494+
* - enterContentZone(contentFilterCallback) - enters a content zone
495495
* - refreshContentZone() - refreshes the content zone
496496
* - exitContentZone() - exits a content zone
497497
*/
498498
const content: Content;
499499
interface Content {
500500
/**
501501
* Enters content zone and checks and displays available content regularly
502+
* @param {Function} [contentFilterCallback] - Optional callback function to filter content based on URL parameters. Should return true to display content, false to ignore.
502503
*/
503-
enterContentZone(): void;
504+
enterContentZone(contentFilterCallback?: (contentURLParams: object) => boolean): void;
504505
/**
505506
* Refreshes content zone
506507
*/

lib/countly.js

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,14 @@
6666
function _classPrivateFieldSet2(s, a, r) {
6767
return s.set(_assertClassBrand(s, a), r), r;
6868
}
69+
function _defineProperties(e, r) {
70+
for (var t = 0; t < r.length; t++) {
71+
var o = r[t];
72+
o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o);
73+
}
74+
}
6975
function _createClass(e, r, t) {
70-
return Object.defineProperty(e, "prototype", {
76+
return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
7177
writable: !1
7278
}), e;
7379
}
@@ -211,7 +217,7 @@
211217
backoffCount: "cly_hc_backoff_count",
212218
consecutiveBackoffCount: "cly_hc_consecutive_backoff_count"
213219
});
214-
var SDK_VERSION = "25.4.2";
220+
var SDK_VERSION = "25.4.3";
215221
var SDK_NAME = "javascript_native_web";
216222

217223
// Using this on document.referrer would return an array with 17 elements in it. The 12th element (array[11]) would be the path we are looking for. Others would be things like password and such (use https://regex101.com/ to check more)
@@ -938,6 +944,7 @@
938944
var _lastRequestWasBackoff = /*#__PURE__*/new WeakMap();
939945
var _testModeTime = /*#__PURE__*/new WeakMap();
940946
var _requestTimeoutDuration = /*#__PURE__*/new WeakMap();
947+
var _contentFilterCallback = /*#__PURE__*/new WeakMap();
941948
var _getAndSetServerConfig = /*#__PURE__*/new WeakMap();
942949
var _populateServerConfig = /*#__PURE__*/new WeakMap();
943950
var _initialize = /*#__PURE__*/new WeakMap();
@@ -1093,6 +1100,7 @@
10931100
_classPrivateFieldInitSpec(this, _lastRequestWasBackoff, void 0);
10941101
_classPrivateFieldInitSpec(this, _testModeTime, void 0);
10951102
_classPrivateFieldInitSpec(this, _requestTimeoutDuration, void 0);
1103+
_classPrivateFieldInitSpec(this, _contentFilterCallback, void 0);
10961104
_classPrivateFieldInitSpec(this, _getAndSetServerConfig, function () {
10971105
if (_this.device_id === "[CLY]_temp_id") {
10981106
_classPrivateFieldGet2(_log, _this).call(_this, logLevelEnums.INFO, "server_config, Device ID is temporary, not fetching server config");
@@ -4602,8 +4610,8 @@
46024610
}
46034611
});
46044612
_defineProperty(this, "content", {
4605-
enterContentZone: function enterContentZone() {
4606-
_classPrivateFieldGet2(_enterContentZoneInternal, _this).call(_this);
4613+
enterContentZone: function enterContentZone(filter_callback) {
4614+
_classPrivateFieldGet2(_enterContentZoneInternal, _this).call(_this, undefined, filter_callback);
46074615
},
46084616
refreshContentZone: function refreshContentZone() {
46094617
_classPrivateFieldGet2(_refreshContentZoneInternal, _this).call(_this);
@@ -4612,7 +4620,7 @@
46124620
_classPrivateFieldGet2(_exitContentZoneInternal, _this).call(_this);
46134621
}
46144622
});
4615-
_classPrivateFieldInitSpec(this, _enterContentZoneInternal, function (forced) {
4623+
_classPrivateFieldInitSpec(this, _enterContentZoneInternal, function (forced, filter_callback) {
46164624
if (!isBrowser) {
46174625
_classPrivateFieldGet2(_log, _this).call(_this, logLevelEnums.WARNING, "content.enterContentZone, window object is not available. Not entering content zone.");
46184626
return;
@@ -4621,6 +4629,10 @@
46214629
_classPrivateFieldGet2(_log, _this).call(_this, logLevelEnums.DEBUG, "content.enterContentZone, Already in content zone");
46224630
return;
46234631
}
4632+
if (filter_callback && typeof filter_callback == "function") {
4633+
_classPrivateFieldGet2(_log, _this).call(_this, logLevelEnums.DEBUG, "content.enterContentZone, Content filter callback is provided");
4634+
_classPrivateFieldSet2(_contentFilterCallback, _this, filter_callback);
4635+
}
46244636
if (!_classPrivateFieldGet2(_initTimestamp, _this) || getMsTimestamp() - _classPrivateFieldGet2(_initTimestamp, _this) < 4000) {
46254637
// settimeout
46264638
_classPrivateFieldGet2(_log, _this).call(_this, logLevelEnums.DEBUG, "content.enterContentZone, Not enough time passed since initialization");
@@ -4711,6 +4723,22 @@
47114723
_classPrivateFieldGet2(_log, _this).call(_this, logLevelEnums.VERBOSE, "sendContentRequest, no html content or orientation to display");
47124724
return;
47134725
}
4726+
4727+
// Build query params
4728+
var queryParams = {};
4729+
var qIndex = response.html.indexOf("?");
4730+
if (qIndex !== -1) {
4731+
var search = response.html.slice(qIndex + 1);
4732+
new URLSearchParams(search).forEach(function (v, k) {
4733+
queryParams[k] = v;
4734+
});
4735+
}
4736+
4737+
// Filter check
4738+
if (_classPrivateFieldGet2(_contentFilterCallback, _this) && _classPrivateFieldGet2(_contentFilterCallback, _this).call(_this, queryParams) === false) {
4739+
_classPrivateFieldGet2(_log, _this).call(_this, logLevelEnums.VERBOSE, "sendContentRequest, Content was filtered out by the content filter");
4740+
return;
4741+
}
47144742
_classPrivateFieldGet2(_displayContent, _this).call(_this, response);
47154743
clearInterval(_classPrivateFieldGet2(_contentZoneTimer, _this)); // prevent multiple content requests while one is on
47164744
window.addEventListener('message', function (event) {
@@ -6487,6 +6515,7 @@
64876515
_classPrivateFieldSet2(_SCBackoffRequestAge, this, 24); // 24 hours
64886516
_classPrivateFieldSet2(_SCBackoffDuration, this, 60); // 60 seconds
64896517
_classPrivateFieldSet2(_requestTimeoutDuration, this, 30000); // 30 seconds
6518+
_classPrivateFieldSet2(_contentFilterCallback, this, null);
64906519
this.app_key = getConfig("app_key", _ob, null);
64916520
this.url = stripTrailingSlash(getConfig("url", _ob, ""));
64926521
this.serialize = getConfig("serialize", _ob, Countly.serialize);

0 commit comments

Comments
 (0)