Skip to content

Commit 3fc9a7d

Browse files
jjl014sblaurock
andauthored
[NOCI] Update bot checking logic (#347)
* Update isBot logic and humanity check tests * Update failing tests * Attempt to simplify humanity check code for future understandability * Update failing tests and remove unnecessary ones * Update formatting on lint overrides --------- Co-authored-by: Steve Blaurock <[email protected]>
1 parent b362818 commit 3fc9a7d

File tree

5 files changed

+174
-63
lines changed

5 files changed

+174
-63
lines changed

cspell.json

+1
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,6 @@
4747
"rerank",
4848
"atcs",
4949
"testdata",
50+
"Bytespider"
5051
]
5152
}

spec/src/utils/humanity-check.js

+53-20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
/* eslint-disable import/no-unresolved */
1+
/* eslint-disable
2+
no-underscore-dangle,
3+
no-restricted-properties,
4+
import/no-unresolved
5+
*/
26
const dotenv = require('dotenv');
37
const chai = require('chai');
48
const chaiAsPromised = require('chai-as-promised');
@@ -15,7 +19,7 @@ const bundled = process.env.BUNDLED === 'true';
1519
describe('ConstructorIO - Utils - Humanity Check', () => {
1620
// Don't run tests in bundle context, as these tests are for library internals
1721
if (!bundled) {
18-
describe('isHuman', () => {
22+
describe('constructor', () => {
1923
const storageKey = '_constructorio_is_human';
2024
let cleanup;
2125

@@ -35,61 +39,90 @@ describe('ConstructorIO - Utils - Humanity Check', () => {
3539
it('Should not have isHuman flag set on initial instantiation', () => {
3640
const humanity = new HumanityCheck();
3741

38-
expect(humanity.isHuman()).to.equal(false);
42+
expect(humanity.hasPerformedHumanEvent).to.equal(false);
3943
expect(store.session.get(storageKey)).to.equal(null);
4044
});
4145

4246
it('Should have isHuman flag set if human-like actions are detected', () => {
4347
const humanity = new HumanityCheck();
4448

45-
expect(humanity.isHuman()).to.equal(false);
49+
expect(humanity.hasPerformedHumanEvent).to.equal(false);
4650
helpers.triggerResize();
47-
expect(humanity.isHuman()).to.equal(true);
48-
expect(store.session.get(storageKey)).to.equal(true);
49-
});
50-
51-
it('Should have isHuman flag set if session variable is set', () => {
52-
const humanity = new HumanityCheck();
53-
54-
expect(humanity.isHuman()).to.equal(false);
55-
store.session.set(storageKey, true);
56-
expect(humanity.isHuman()).to.equal(true);
51+
expect(humanity.hasPerformedHumanEvent).to.equal(true);
5752
expect(store.session.get(storageKey)).to.equal(true);
5853
});
5954
});
55+
6056
describe('isBot', () => {
6157
const storageKey = '_constructorio_is_human';
6258
let cleanup;
59+
let defaultAgent;
6360

6461
beforeEach(() => {
6562
global.CLIENT_VERSION = 'cio-mocha';
66-
6763
cleanup = jsdom();
68-
window.navigator.webdriver = true;
64+
65+
defaultAgent = window.navigator.userAgent;
6966
});
7067

7168
afterEach(() => {
7269
delete global.CLIENT_VERSION;
70+
delete window.navigator.webdriver;
71+
window.navigator.__defineGetter__('userAgent', () => defaultAgent);
7372
cleanup();
7473

7574
helpers.clearStorage();
7675
});
7776

78-
it('Should have isBot flag set on initial instantiation', () => {
77+
it('Should return true if it detects a webdriver', () => {
78+
window.navigator.webdriver = true;
7979
const humanity = new HumanityCheck();
8080

8181
expect(humanity.isBot()).to.equal(true);
8282
expect(store.session.get(storageKey)).to.equal(null);
8383
});
8484

85-
it('Should have isBot flag set to false if session variable is set', () => {
85+
it('Should return true if it detects a webdriver and the session variable is set via human-like action', () => {
86+
window.navigator.webdriver = true;
8687
const humanity = new HumanityCheck();
8788

8889
expect(humanity.isBot()).to.equal(true);
89-
store.session.set(storageKey, true);
90-
expect(humanity.isBot()).to.equal(false);
90+
helpers.triggerResize();
91+
expect(humanity.isBot()).to.equal(true);
92+
expect(store.session.get(storageKey)).to.equal(true);
93+
});
94+
95+
it('Should return true if it detects a bot user agent', () => {
96+
window.navigator.__defineGetter__('userAgent', () => 'Mozilla/5.0 (Linux; Android 5.0) AppleWebKit/537.36 (KHTML, like Gecko) Mobile Safari/537.36 (compatible; Bytespider; [email protected])');
97+
const humanity = new HumanityCheck();
98+
99+
expect(humanity.isBot()).to.equal(true);
100+
expect(store.session.get(storageKey)).to.equal(null);
101+
});
102+
103+
it('Should return true if it detects a bot user agent and the session variable is set via human-like action', () => {
104+
window.navigator.__defineGetter__('userAgent', () => 'Mozilla/5.0 (Linux; Android 5.0) AppleWebKit/537.36 (KHTML, like Gecko) Mobile Safari/537.36 (compatible; Bytespider; [email protected])');
105+
const humanity = new HumanityCheck();
106+
107+
expect(humanity.isBot()).to.equal(true);
108+
helpers.triggerResize();
109+
expect(humanity.isBot()).to.equal(true);
91110
expect(store.session.get(storageKey)).to.equal(true);
92111
});
112+
113+
it('Should return true if it does not detect the user is a bot user nor webdriver and the session variable has not been set yet', () => {
114+
const humanity = new HumanityCheck();
115+
116+
expect(humanity.isBot()).to.equal(true);
117+
});
118+
119+
it('Should return false if it does not detect the user is a bot/webdriver and the session variable is set via human-like action', () => {
120+
const humanity = new HumanityCheck();
121+
122+
expect(humanity.isBot()).to.equal(true);
123+
helpers.triggerResize();
124+
expect(humanity.isBot()).to.equal(false);
125+
});
93126
});
94127
}
95128
});

spec/src/utils/request-queue.js

+98-23
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ describe('ConstructorIO - Utils - Request Queue', function utilsRequestQueue() {
3131
this.timeout(3000);
3232

3333
const storageKey = '_constructorio_requests';
34+
const humanityStorageKey = '_constructorio_is_human';
3435
const waitInterval = 2000;
3536
let requestQueueOptions = {};
3637
const piiExamples = [
@@ -179,7 +180,8 @@ describe('ConstructorIO - Utils - Request Queue', function utilsRequestQueue() {
179180
helpers.clearStorage();
180181
});
181182

182-
it('Should add url requests to the queue', () => {
183+
it('Should add url requests to the queue if the user is human', async () => {
184+
store.session.set(humanityStorageKey, true);
183185
const requests = new RequestQueue(requestQueueOptions);
184186

185187
requests.queue('https://ac.cnstrc.com/behavior?action=session_start');
@@ -191,7 +193,8 @@ describe('ConstructorIO - Utils - Request Queue', function utilsRequestQueue() {
191193
expect(store.local.get(storageKey)).to.be.an('array').length(3);
192194
});
193195

194-
it('Should add object requests to the queue - POST with body', () => {
196+
it('Should add object requests to the queue - POST with body if the user is human', () => {
197+
store.session.set(humanityStorageKey, true);
195198
const requests = new RequestQueue(requestQueueOptions);
196199

197200
requests.queue('https://ac.cnstrc.com/behavior', 'POST', { action: 'session_start' });
@@ -218,6 +221,7 @@ describe('ConstructorIO - Utils - Request Queue', function utilsRequestQueue() {
218221
});
219222

220223
it('Should obfuscate requests if PII is detected', () => {
224+
store.session.set(humanityStorageKey, true); // Enabled for the test to run
221225
const requests = new RequestQueue(requestQueueOptions);
222226
const allExamples = [];
223227

@@ -252,6 +256,7 @@ describe('ConstructorIO - Utils - Request Queue', function utilsRequestQueue() {
252256
});
253257

254258
it('Should not obfuscate requests if no PII is detected', () => {
259+
store.session.set(humanityStorageKey, true); // Enabled for the test to run
255260
const requests = new RequestQueue(requestQueueOptions);
256261

257262
notPiiExamples.forEach((query) => {
@@ -343,12 +348,13 @@ describe('ConstructorIO - Utils - Request Queue', function utilsRequestQueue() {
343348
it('Should send all url tracking requests if queue is populated and user is human', (done) => {
344349
const requests = new RequestQueue(requestQueueOptions);
345350

351+
helpers.triggerResize(); // Human-like action
352+
346353
requests.queue('https://ac.cnstrc.com/behavior?action=session_start');
347354
requests.queue('https://ac.cnstrc.com/behavior?action=focus');
348355
requests.queue('https://ac.cnstrc.com/behavior?action=magic_number_three');
349356

350357
expect(RequestQueue.get()).to.be.an('array').length(3);
351-
helpers.triggerResize();
352358
requests.send();
353359

354360
setTimeout(() => {
@@ -359,6 +365,7 @@ describe('ConstructorIO - Utils - Request Queue', function utilsRequestQueue() {
359365
});
360366

361367
it('Should send all object tracking requests if queue is populated and user is human - POST with body', (done) => {
368+
store.session.set(humanityStorageKey, true);
362369
const requests = new RequestQueue(requestQueueOptions);
363370

364371
requests.queue('https://ac.cnstrc.com/behavior', 'POST', { action: 'session_start' });
@@ -376,14 +383,26 @@ describe('ConstructorIO - Utils - Request Queue', function utilsRequestQueue() {
376383
}, waitInterval);
377384
});
378385

379-
it('Should not send tracking requests if queue is populated and user is not human', (done) => {
386+
it('Should not send tracking requests if queue was populated and user is not human', (done) => {
380387
const requests = new RequestQueue(requestQueueOptions);
381388

382-
requests.queue('https://ac.cnstrc.com/behavior?action=session_start');
383-
requests.queue('https://ac.cnstrc.com/behavior?action=focus');
384-
requests.queue('https://ac.cnstrc.com/behavior?action=magic_number_three');
389+
store.local.set(storageKey, [
390+
{
391+
url: 'https://ac.cnstrc.com/behavior?action=session_start',
392+
method: 'GET',
393+
},
394+
{
395+
url: 'https://ac.cnstrc.com/behavior?action=focus',
396+
method: 'GET',
397+
},
398+
{
399+
url: 'https://ac.cnstrc.com/behavior?action=magic_number_three',
400+
method: 'GET',
401+
},
402+
]);
385403

386404
expect(RequestQueue.get()).to.be.an('array').length(3);
405+
387406
requests.send();
388407

389408
setTimeout(() => {
@@ -395,9 +414,20 @@ describe('ConstructorIO - Utils - Request Queue', function utilsRequestQueue() {
395414
it('Should not send tracking requests if queue is populated and user is human and page is unloading', (done) => {
396415
const requests = new RequestQueue(requestQueueOptions);
397416

398-
requests.queue('https://ac.cnstrc.com/behavior?action=session_start');
399-
requests.queue('https://ac.cnstrc.com/behavior?action=focus');
400-
requests.queue('https://ac.cnstrc.com/behavior?action=magic_number_three');
417+
store.local.set(storageKey, [
418+
{
419+
url: 'https://ac.cnstrc.com/behavior?action=session_start',
420+
method: 'GET',
421+
},
422+
{
423+
url: 'https://ac.cnstrc.com/behavior?action=focus',
424+
method: 'GET',
425+
},
426+
{
427+
url: 'https://ac.cnstrc.com/behavior?action=magic_number_three',
428+
method: 'GET',
429+
},
430+
]);
401431

402432
expect(RequestQueue.get()).to.be.an('array').length(3);
403433
helpers.triggerResize();
@@ -413,9 +443,20 @@ describe('ConstructorIO - Utils - Request Queue', function utilsRequestQueue() {
413443
it('Should not send tracking requests if queue is populated and user is human and page is unloading and send was called before unload', (done) => {
414444
const requests = new RequestQueue(requestQueueOptions);
415445

416-
requests.queue('https://ac.cnstrc.com/behavior?action=session_start');
417-
requests.queue('https://ac.cnstrc.com/behavior?action=focus');
418-
requests.queue('https://ac.cnstrc.com/behavior?action=magic_number_three');
446+
store.local.set(storageKey, [
447+
{
448+
url: 'https://ac.cnstrc.com/behavior?action=session_start',
449+
method: 'GET',
450+
},
451+
{
452+
url: 'https://ac.cnstrc.com/behavior?action=focus',
453+
method: 'GET',
454+
},
455+
{
456+
url: 'https://ac.cnstrc.com/behavior?action=magic_number_three',
457+
method: 'GET',
458+
},
459+
]);
419460

420461
expect(RequestQueue.get()).to.be.an('array').length(3);
421462
helpers.triggerResize();
@@ -728,11 +769,28 @@ describe('ConstructorIO - Utils - Request Queue', function utilsRequestQueue() {
728769
const sendSpy1 = sinon.spy(requests1, 'send');
729770
const sendSpy2 = sinon.spy(requests2, 'send');
730771

731-
requests1.queue('https://ac.cnstrc.com/behavior', 'POST', { action: 'number_one' });
732-
requests1.queue('https://ac.cnstrc.com/behavior', 'POST', { action: 'number_two' });
733-
requests1.queue('https://ac.cnstrc.com/behavior', 'POST', { action: 'number_three' });
734-
requests1.queue('https://ac.cnstrc.com/behavior', 'POST', { action: 'number_four' });
735-
requests1.queue('https://ac.cnstrc.com/behavior', 'POST', { action: 'number_five' });
772+
store.local.set(storageKey, [
773+
{
774+
url: 'https://ac.cnstrc.com/behavior?action=session_start',
775+
method: 'GET',
776+
},
777+
{
778+
url: 'https://ac.cnstrc.com/behavior?action=focus',
779+
method: 'GET',
780+
},
781+
{
782+
url: 'https://ac.cnstrc.com/behavior?action=magic_number_three',
783+
method: 'GET',
784+
},
785+
{
786+
url: 'https://ac.cnstrc.com/behavior?action=magic_number_four',
787+
method: 'GET',
788+
},
789+
{
790+
url: 'https://ac.cnstrc.com/behavior?action=magic_number_five',
791+
method: 'GET',
792+
},
793+
]);
736794

737795
helpers.triggerResize();
738796
requests1.send();
@@ -754,11 +812,28 @@ describe('ConstructorIO - Utils - Request Queue', function utilsRequestQueue() {
754812
const sendSpy1 = sinon.spy(requests1, 'send');
755813
const sendSpy2 = sinon.spy(requests2, 'send');
756814

757-
requests1.queue('https://ac.cnstrc.com/behavior', 'POST', { action: 'number_one' });
758-
requests2.queue('https://ac.cnstrc.com/behavior', 'POST', { action: 'number_two' });
759-
requests1.queue('https://ac.cnstrc.com/behavior', 'POST', { action: 'number_three' });
760-
requests2.queue('https://ac.cnstrc.com/behavior', 'POST', { action: 'number_four' });
761-
requests1.queue('https://ac.cnstrc.com/behavior', 'POST', { action: 'number_five' });
815+
store.local.set(storageKey, [
816+
{
817+
url: 'https://ac.cnstrc.com/behavior?action=session_start',
818+
method: 'GET',
819+
},
820+
{
821+
url: 'https://ac.cnstrc.com/behavior?action=focus',
822+
method: 'GET',
823+
},
824+
{
825+
url: 'https://ac.cnstrc.com/behavior?action=magic_number_three',
826+
method: 'GET',
827+
},
828+
{
829+
url: 'https://ac.cnstrc.com/behavior?action=magic_number_four',
830+
method: 'GET',
831+
},
832+
{
833+
url: 'https://ac.cnstrc.com/behavior?action=magic_number_five',
834+
method: 'GET',
835+
},
836+
]);
762837

763838
helpers.triggerResize();
764839
requests1.send();

0 commit comments

Comments
 (0)