Skip to content

Commit 743a2f4

Browse files
[Feature] Event ID implementation (#374)
* event id implementation * removed unused var * removed polyfill * event id logic change * omitting internal event keys from truncation * scroll fix and tests * Update CHANGELOG.md * eventIDoverride --------- Co-authored-by: ArtursKadikis <kadikis.arturs@gmail.com>
1 parent 0934bff commit 743a2f4

20 files changed

+296
-128
lines changed

CHANGELOG.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
## 23.02.0
2-
- Fixed a bug where previous session cookie persisted even when the 'clear_stored_id' flag was set to true
2+
- Events are now recorded with an internal ID.
3+
- Mitigated an issue where users could have truncate an internal event key
4+
- Mitigated an issue where SDK was reporting empty scroll values
35
- Mitigated an issue that caused the device changes, after init, to not reflect on memory
6+
- Fixed a bug where previous session cookie persisted even when the 'clear_stored_id' flag was set to true
47

58
## 22.06.5
69
- SDK now adds userAgent string to each request to prevent proxy related issues

cypress/integration/events.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ describe("Events tests ", () => {
5353
Countly.add_event(eventObj);
5454
cy.fetch_local_event_queue().then((eq) => {
5555
expect(eq.length).to.equal(1);
56-
cy.check_event(eq[0], eventObj);
56+
cy.check_event(eq[0], eventObj, undefined, false);
5757
});
5858
});
5959
});
@@ -74,7 +74,7 @@ describe("Events tests ", () => {
7474
cy.fetch_local_event_queue().then((eq) => {
7575
expect(eq.length).to.equal(1);
7676
// we waited 3000 milliseconds so duration must be 3 to 4
77-
cy.check_event(eq[0], timedEventObj, 4);
77+
cy.check_event(eq[0], timedEventObj, 4, false);
7878
});
7979
});
8080
});
@@ -97,7 +97,7 @@ describe("Events tests ", () => {
9797
cy.fetch_local_event_queue().then((eq) => {
9898
expect(eq.length).to.equal(1);
9999
// we waited 3000 milliseconds so duration must be 3 to 4
100-
cy.check_event(eq[0], timedEventObjLong, 4);
100+
cy.check_event(eq[0], timedEventObjLong, 4, false);
101101
});
102102
});
103103
});
@@ -150,7 +150,7 @@ describe("Events tests ", () => {
150150
cy.fetch_local_event_queue().then((eq) => {
151151
expect(eq.length).to.equal(1);
152152
// we waited 3000 milliseconds so duration must be 3 to 4
153-
cy.check_event(eq[0], timedEventObj, 3);
153+
cy.check_event(eq[0], timedEventObj, 3, false);
154154
});
155155
});
156156
});
@@ -168,7 +168,7 @@ describe("Events tests ", () => {
168168
cy.fetch_local_event_queue().then((eq) => {
169169
expect(eq.length).to.equal(1);
170170
// we waited 3000 milliseconds so duration must be 3 to 4
171-
cy.check_event(eq[0], timedEventObj, 3);
171+
cy.check_event(eq[0], timedEventObj, 3, false);
172172
});
173173
});
174174
});
@@ -202,7 +202,7 @@ describe("Events tests ", () => {
202202
cy.fetch_local_event_queue().then((eq) => {
203203
expect(eq.length).to.equal(1);
204204
// we waited 3000 milliseconds so duration must be 3 to 4
205-
cy.check_event(eq[0], timedEventObjLong, 3);
205+
cy.check_event(eq[0], timedEventObjLong, 3, false);
206206
});
207207
});
208208
});

cypress/integration/heatmaps.js

+24-18
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ describe("Browser heatmap tests, scrolls", () => {
2626
expect(rq.length).to.equal(4);
2727
// first object of the queue should be about begin session, second is orientation
2828
cy.check_session(rq[0], undefined, undefined, hp.appKey);
29+
cy.check_view_event(JSON.parse(rq[1].events)[1], "/cypress/fixtures/scroll_test.html", undefined, false);
2930
// third object of the queue should be about session extension, also input the expected duration range, we expect 0 here so we enter a value lower than that but not deviated more than 1
3031
cy.check_session(rq[2], -0.5, undefined);
3132
// fourth object of the queue should be events in the queue, there must be 4 of them
32-
cy.check_view_event(JSON.parse(rq[3].events)[0], "/cypress/fixtures/scroll_test.html", 0);
33+
cy.check_view_event(JSON.parse(rq[3].events)[0], "/cypress/fixtures/scroll_test.html", 0, false);
3334
cy.check_scroll_event(JSON.parse(rq[3].events)[1]);
3435
// number 3 is orientation
35-
cy.check_view_event(JSON.parse(rq[3].events)[3], "/cypress/fixtures/scroll_test_2.html");
36+
cy.check_view_event(JSON.parse(rq[3].events)[3], "/cypress/fixtures/scroll_test_2.html", undefined, false); // new page not new view
3637
});
3738
});
3839
it("Check if scrolls are sent if for single page apps/sites", () => {
@@ -44,21 +45,26 @@ describe("Browser heatmap tests, scrolls", () => {
4445
cy.scrollTo("bottom");
4546
// click button that triggers view change
4647
cy.get("#b2").click();
47-
// 2 request with 1 session and 1 events
48-
cy.fetch_local_request_queue(hp.appKey).then((rq) => {
49-
cy.log(rq);
50-
expect(rq.length).to.equal(2);
51-
cy.check_session(rq[0], undefined, undefined, hp.appKey);
52-
});
53-
// 6 events with 4 views and 2 scrolls must be here
54-
cy.fetch_local_event_queue(hp.appKey).then((eq) => {
55-
cy.log(eq);
56-
cy.check_scroll_event(eq[0]);
57-
cy.check_view_event(eq[1], "/cypress/fixtures/scroll_test_3.html", 0);
58-
cy.check_view_event(eq[2], "v1");
59-
cy.check_scroll_event(eq[3]);
60-
cy.check_view_event(eq[4], "v1", 0);
61-
cy.check_view_event(eq[5], "v2");
48+
// There should be 3 requests: session -> event batch 1 -> event batch 2
49+
hp.waitFunction(hp.getTimestampMs(), 1000, 100, () => {
50+
cy.fetch_local_request_queue(hp.appKey).then((rq) => {
51+
expect(rq.length).to.equal(3);
52+
53+
cy.check_session(rq[0], undefined, undefined, hp.appKey);
54+
55+
const eventBatch1 = JSON.parse(rq[1].events); // 0 is orientation, 1 is view
56+
expect(eventBatch1[0].key).to.equal("[CLY]_orientation");
57+
expect(eventBatch1[0].segmentation.mode).to.be.ok;
58+
cy.check_view_event(eventBatch1[1], "/cypress/fixtures/scroll_test_3.html", undefined, false);
59+
60+
const eventBatch2 = JSON.parse(rq[2].events); // 0 is view, 1 is scroll, 2 is view, 3 is scroll
61+
cy.check_scroll_event(eventBatch2[0]);
62+
cy.check_view_event(eventBatch2[1], "/cypress/fixtures/scroll_test_3.html", 0, false);
63+
cy.check_view_event(eventBatch2[2], "v1", undefined, true);
64+
cy.check_scroll_event(eventBatch2[3]);
65+
cy.check_view_event(eventBatch2[4], "v1", 0, true);
66+
cy.check_view_event(eventBatch2[5], "v2", undefined, true);
67+
});
6268
});
6369
});
6470
});
@@ -116,7 +122,7 @@ describe("Browser heatmap tests, clicks", () => {
116122
cy.check_commons(clickEv[0]);
117123

118124
const seg = clickEv[0].segmentation;
119-
click_check(seg, 80, 8);
125+
click_check(seg, 79, 8);
120126
});
121127
});
122128
});

cypress/integration/internal_limits.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,13 @@ describe("Internal limit tests ", () => {
9999
hp.haltAndClearStorage(() => {
100100
initMain();
101101
Countly.track_pageview(viewName);
102-
cy.fetch_local_event_queue().then((eq) => {
102+
cy.fetch_local_event_queue().then((eq) => { // TODO: when view event is truncated we provide cvid instead of pvid. fix this
103+
cy.log(eq);
103104
expect(eq.length).to.equal(1);
104105
cy.check_view_event_limit(eq[0], viewName, limits);
106+
expect(eq[0].id).to.be.ok;
107+
expect(eq[0].id.length).to.equal(21);
108+
expect(eq[0].pvid).to.equal("");
105109
});
106110
});
107111
});

cypress/integration/sessions.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ describe("Browser session tests, auto", () => {
8888
// third object of the queue should be about session extension, also input the expected duration
8989
cy.check_session(rq[2], 5, undefined, app_key);
9090
// fourth object of the queue should be about event sent
91-
cy.check_event(JSON.parse(rq[3].events)[0], eventObj);
91+
cy.check_event(JSON.parse(rq[3].events)[0], eventObj, undefined, false);
9292
// fifth object of the queue should be about session extension, also input the expected duration
9393
cy.check_session(rq[4], 1, undefined, app_key);
9494
});
@@ -110,7 +110,7 @@ describe("Browser session tests, manual 1", () => {
110110
// third object of the queue should be about session extension, also input the expected duration
111111
cy.check_session(rq[2], 5, undefined, app_key);
112112
// fourth object of the queue should be about event sent
113-
cy.check_event(JSON.parse(rq[3].events)[0], eventObj);
113+
cy.check_event(JSON.parse(rq[3].events)[0], eventObj, undefined, false);
114114
// fifth object of the queue should be about session extension, also input the expected duration
115115
cy.check_session(rq[4], 1, undefined, app_key);
116116
});
@@ -130,7 +130,7 @@ describe("Browser session tests, manual 2", () => {
130130
// third object of the queue should be about session extension, also input the expected duration
131131
cy.check_session(rq[2], 5, undefined, app_key);
132132
// fourth object of the queue should be about event sent
133-
cy.check_event(JSON.parse(rq[3].events)[0], eventObj);
133+
cy.check_event(JSON.parse(rq[3].events)[0], eventObj, undefined, false);
134134
// fifth object of the queue should be about session extension, also input the expected duration
135135
cy.check_session(rq[4], 1, undefined, app_key);
136136
});
@@ -151,7 +151,7 @@ describe("Browser session tests, auto, no cookie", () => {
151151
// third object of the queue should be about session extension, also input the expected duration
152152
cy.check_session(rq[2], 5, undefined, app_key);
153153
// fourth object of the queue should be about event sent
154-
cy.check_event(JSON.parse(rq[3].events)[0], eventObj);
154+
cy.check_event(JSON.parse(rq[3].events)[0], eventObj, undefined, false);
155155
// fifth object of the queue should be about session extension, also input the expected duration
156156
cy.check_session(rq[4], 1, true, app_key);
157157
});
@@ -173,7 +173,7 @@ describe("Browser session tests, manual 1, no cookie", () => {
173173
// third object of the queue should be about session extension, also input the expected duration
174174
cy.check_session(rq[2], 5, undefined, app_key);
175175
// fourth object of the queue should be about event sent
176-
cy.check_event(JSON.parse(rq[3].events)[0], eventObj);
176+
cy.check_event(JSON.parse(rq[3].events)[0], eventObj, undefined, false);
177177
// fifth object of the queue should be about session extension, also input the expected duration
178178
cy.check_session(rq[4], 1, true, app_key);
179179
});
@@ -193,7 +193,7 @@ describe("Browser session tests, manual 2, no cookie", () => {
193193
// third object of the queue should be about session extension, also input the expected duration
194194
cy.check_session(rq[2], 5, undefined, app_key);
195195
// fourth object of the queue should be about event sent
196-
cy.check_event(JSON.parse(rq[3].events)[0], eventObj);
196+
cy.check_event(JSON.parse(rq[3].events)[0], eventObj, undefined, false);
197197
// fifth object of the queue should be about session extension, also input the expected duration
198198
cy.check_session(rq[4], 1, true, app_key);
199199
});

cypress/integration/user_details.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,13 @@ describe("User details tests ", () => {
5555
Countly.add_event(eventObj);
5656
cy.fetch_local_event_queue().then((eq) => { // event should be in event queue
5757
expect(eq.length).to.equal(1);
58-
cy.check_event(eq[0], eventObj);
58+
cy.check_event(eq[0], eventObj, undefined, false);
5959
});
6060
cy.wait(1000).then(() => {
6161
Countly.user_details(userDetailObj);
6262
cy.fetch_local_request_queue().then((rq) => { // events and user details must be here
6363
expect(rq.length).to.equal(2);
64-
cy.check_event(JSON.parse(rq[0].events)[0], eventObj);
64+
cy.check_event(JSON.parse(rq[0].events)[0], eventObj, undefined, false);
6565
cy.check_user_details(rq[1], userDetailObj);
6666
});
6767
cy.fetch_local_event_queue().then((eq) => { // event queue should be empty
@@ -427,7 +427,7 @@ describe("User details tests ", () => {
427427
Countly.add_event(eventObj);
428428
cy.fetch_local_event_queue().then((eq) => { // event should be in event queue
429429
expect(eq.length).to.equal(1);
430-
cy.check_event(eq[0], eventObj);
430+
cy.check_event(eq[0], eventObj, undefined, false);
431431
});
432432
cy.wait(1000).then(() => {
433433
Countly.userData.set("key", "value");
@@ -436,7 +436,7 @@ describe("User details tests ", () => {
436436
});
437437
cy.fetch_local_event_queue().then((eq) => { // event should be in event queue
438438
expect(eq.length).to.equal(1);
439-
cy.check_event(eq[0], eventObj);
439+
cy.check_event(eq[0], eventObj, undefined, false);
440440
});
441441
});
442442
});
@@ -447,15 +447,15 @@ describe("User details tests ", () => {
447447
Countly.add_event(eventObj);
448448
cy.fetch_local_event_queue().then((eq) => { // event should be in event queue
449449
expect(eq.length).to.equal(1);
450-
cy.check_event(eq[0], eventObj);
450+
cy.check_event(eq[0], eventObj, undefined, false);
451451
});
452452
cy.wait(1000).then(() => {
453453
Countly.userData.set("key", "value");
454454
Countly.userData.save();
455455

456456
cy.fetch_local_request_queue().then((rq) => {
457457
expect(rq.length).to.equal(2);
458-
cy.check_event(JSON.parse(rq[0].events)[0], eventObj);
458+
cy.check_event(JSON.parse(rq[0].events)[0], eventObj, undefined, false);
459459
const custom = JSON.parse(rq[1].user_details).custom;
460460
expect(Object.keys(custom).length).to.equal(1);
461461
expect(custom.key).to.equal("value");

cypress/integration/views.js

+85-12
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,29 @@ function initMain() {
1515
var pageNameOne = "test view page name1";
1616
var pageNameTwo = "test view page name2";
1717

18-
describe("Views tests ", () => {
18+
describe("View ID tests ", () => {
19+
it("Checks if UUID and secureRandom works as intended", () => {
20+
hp.haltAndClearStorage(() => {
21+
initMain();
22+
const uuid = Countly._internals.generateUUID();
23+
const id = Countly._internals.secureRandom();
24+
assert.equal(uuid.length, 36);
25+
assert.equal(id.length, 21);
26+
const uuid2 = Countly._internals.generateUUID();
27+
const id2 = Countly._internals.secureRandom();
28+
assert.equal(uuid2.length, 36);
29+
assert.equal(id2.length, 21);
30+
assert.notEqual(uuid, uuid2);
31+
assert.notEqual(id, id2);
32+
});
33+
});
1934
it("Checks if recording page view works", () => {
2035
hp.haltAndClearStorage(() => {
2136
initMain();
2237
Countly.track_view(pageNameOne);
2338
cy.fetch_local_event_queue().then((eq) => {
2439
expect(eq.length).to.equal(1);
25-
cy.check_view_event(eq[0], pageNameOne);
40+
cy.check_view_event(eq[0], pageNameOne, undefined, false);
2641
});
2742
});
2843
});
@@ -33,10 +48,20 @@ describe("Views tests ", () => {
3348
cy.wait(3000).then(() => {
3449
Countly.track_view(pageNameOne);
3550
cy.fetch_local_event_queue().then((eq) => {
51+
cy.log(eq);
3652
expect(eq.length).to.equal(3);
37-
cy.check_view_event(eq[0], pageNameOne);
38-
cy.check_view_event(eq[1], pageNameOne, 3);
39-
cy.check_view_event(eq[2], pageNameOne);
53+
cy.check_view_event(eq[0], pageNameOne, undefined, false);
54+
const id1 = eq[0].id;
55+
56+
cy.check_view_event(eq[1], pageNameOne, 3, false);
57+
const id2 = eq[1].id;
58+
assert.equal(id1, id2);
59+
60+
cy.check_view_event(eq[2], pageNameOne, undefined, true);
61+
const id3 = eq[2].id;
62+
const pvid = eq[2].pvid;
63+
assert.equal(id1, pvid);
64+
assert.notEqual(id3, pvid);
4065
});
4166
});
4267
});
@@ -45,18 +70,66 @@ describe("Views tests ", () => {
4570
hp.haltAndClearStorage(() => {
4671
initMain();
4772
Countly.track_view(pageNameOne);
48-
var expectedDur = 4000;
49-
hp.waitFunction(hp.getTimestampMs(), expectedDur, 500, ()=>{
50-
// cy.wait(4000).then(() => {
73+
hp.waitFunction(hp.getTimestampMs(), 4000, 500, ()=>{
5174
Countly.track_view(pageNameTwo);
5275
cy.fetch_local_event_queue().then((eq) => {
5376
expect(eq.length).to.equal(3);
54-
cy.check_view_event(eq[0], pageNameOne);
77+
cy.check_view_event(eq[0], pageNameOne, undefined, false);
78+
const id1 = eq[0].id;
79+
5580
// this test is flaky we are expecting 3 and +1 (4) to make test more reliable
56-
cy.check_view_event(eq[1], pageNameOne, expectedDur / 1000);
57-
cy.check_view_event(eq[2], pageNameTwo);
81+
cy.check_view_event(eq[1], pageNameOne, 4, false);
82+
const id2 = eq[1].id;
83+
assert.equal(id1, id2);
84+
85+
cy.check_view_event(eq[2], pageNameTwo, undefined, true);
86+
const id3 = eq[2].id;
87+
const pvid = eq[2].pvid;
88+
assert.equal(id1, pvid);
89+
assert.notEqual(id3, pvid);
5890
});
59-
// });
91+
});
92+
});
93+
});
94+
95+
// ===========================
96+
// Confirms:
97+
// view A's id and event A's cvid are same
98+
// view B's id and event B's cvid are same. Also view B's pvid and view A's id are same
99+
// view C's id and event C's cvid are same. Also view C's pvid and view B's id are same
100+
//
101+
// request order: view A start -> event A -> view A end -> view B start -> event B -> view B end -> view C start -> event C
102+
// ===========================
103+
it("Checks a sequence of events and page views", () => {
104+
hp.haltAndClearStorage(() => {
105+
initMain();
106+
Countly.track_view("A");
107+
Countly.add_event({ key: "A" });
108+
Countly.track_view("B");
109+
Countly.add_event({ key: "B" });
110+
Countly.track_view("C");
111+
Countly.add_event({ key: "C" });
112+
113+
cy.fetch_local_event_queue().then((eq) => {
114+
expect(eq.length).to.equal(8);
115+
cy.log(eq);
116+
117+
// event A and view A
118+
cy.check_view_event(eq[0], "A", undefined, false); // no pvid
119+
const idA = eq[0].id; // idA
120+
cy.check_event(eq[1], { key: "A" }, undefined, idA); // cvid should be idA
121+
cy.check_view_event(eq[2], "A", 0, false); // no pvid
122+
123+
// event B and view B
124+
cy.check_view_event(eq[3], "B", undefined, idA); // pvid is idA
125+
const idB = eq[3].id; // idB
126+
cy.check_event(eq[4], { key: "B" }, undefined, idB); // cvid should be idB
127+
cy.check_view_event(eq[5], "B", 0, idA); // pvid is idA
128+
129+
// event C and view C
130+
cy.check_view_event(eq[6], "C", undefined, idB); // pvid is idB
131+
const idC = eq[6].id; // idC
132+
cy.check_event(eq[7], { key: "C" }, undefined, idC); // cvid should be idC
60133
});
61134
});
62135
});

0 commit comments

Comments
 (0)