@govtechsg/oobee 0.10.84 → 0.10.86

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/.github/workflows/image.yml +3 -2
  2. package/.github/workflows/publish.yml +10 -0
  3. package/DETAILS.md +29 -0
  4. package/dist/cli.js +7 -6
  5. package/dist/combine.js +1 -1
  6. package/dist/constants/common.js +15 -4
  7. package/dist/constants/constants.js +604 -1
  8. package/dist/crawlers/commonCrawlerFunc.js +3 -2
  9. package/dist/crawlers/crawlSitemap.js +98 -80
  10. package/dist/crawlers/custom/utils.js +218 -71
  11. package/dist/crawlers/guards/urlGuard.js +8 -15
  12. package/dist/crawlers/runCustom.js +24 -15
  13. package/dist/generateOobeeClientScanner.js +570 -0
  14. package/dist/mergeAxeResults.js +49 -29
  15. package/dist/npmIndex.js +10 -2
  16. package/dist/proxyService.js +18 -3
  17. package/dist/services/s3Uploader.js +21 -10
  18. package/dist/static/ejs/partials/scripts/header/aboutScanModal/ScanConfiguration.ejs +2 -2
  19. package/dist/static/ejs/partials/scripts/ruleModal/constants.ejs +1 -761
  20. package/dist/static/ejs/summary.ejs +10 -5
  21. package/oobee-client-scanner.js +34992 -0
  22. package/package.json +3 -3
  23. package/src/cli.ts +20 -15
  24. package/src/combine.ts +3 -1
  25. package/src/constants/common.ts +22 -10
  26. package/src/constants/constants.ts +602 -1
  27. package/src/crawlers/commonCrawlerFunc.ts +4 -3
  28. package/src/crawlers/crawlSitemap.ts +116 -98
  29. package/src/crawlers/custom/utils.ts +244 -84
  30. package/src/crawlers/guards/urlGuard.ts +24 -31
  31. package/src/crawlers/runCustom.ts +38 -15
  32. package/src/generateOobeeClientScanner.ts +591 -0
  33. package/src/mergeAxeResults.ts +48 -29
  34. package/src/npmIndex.ts +12 -2
  35. package/src/proxyService.ts +25 -4
  36. package/src/services/s3Uploader.ts +23 -11
  37. package/src/static/ejs/partials/scripts/header/aboutScanModal/ScanConfiguration.ejs +2 -2
  38. package/src/static/ejs/partials/scripts/ruleModal/constants.ejs +1 -761
  39. package/src/static/ejs/summary.ejs +10 -5
  40. package/testStaticJSScanner.html +534 -0
@@ -1,8 +1,8 @@
1
- /* eslint-disable no-shadow */
2
1
  /* eslint-disable no-alert */
3
2
  /* eslint-disable no-param-reassign */
4
3
  /* eslint-env browser */
5
4
  import path from 'path';
5
+ import { getDomain } from 'tldts';
6
6
  import { runAxeScript } from '../commonCrawlerFunc.js';
7
7
  import { consoleLogger, guiInfoLog, silentLogger } from '../../logs.js';
8
8
  import { guiInfoStatusTypes } from '../../constants/constants.js';
@@ -19,6 +19,44 @@ declare global {
19
19
  }
20
20
  }
21
21
 
22
+ const sameRegistrableDomain = (hostA: string, hostB: string) => {
23
+ const domainA = getDomain(hostA);
24
+ const domainB = getDomain(hostB);
25
+
26
+ if (!domainA || !domainB) return hostA === hostB;
27
+
28
+ return domainA === domainB;
29
+ };
30
+
31
+ const parseBoolEnv = (val: string | undefined, defaultVal: boolean) => {
32
+ if (val == null) return defaultVal;
33
+ const v = String(val).trim().toLowerCase();
34
+ if (['1', 'true', 'yes', 'y', 'on'].includes(v)) return true;
35
+ if (['0', 'false', 'no', 'n', 'off'].includes(v)) return false;
36
+ return defaultVal;
37
+ };
38
+
39
+ const RESTRICT_OVERLAY_TO_ENTRY_DOMAIN = parseBoolEnv(
40
+ process.env.RESTRICT_OVERLAY_TO_ENTRY_DOMAIN,
41
+ false,
42
+ );
43
+
44
+ const isOverlayAllowed = (currentUrl: string, entryUrl: string) => {
45
+ try {
46
+ const cur = new URL(currentUrl);
47
+
48
+ if (cur.protocol !== 'http:' && cur.protocol !== 'https:') return false;
49
+
50
+ if (!RESTRICT_OVERLAY_TO_ENTRY_DOMAIN) return true;
51
+
52
+ const base = new URL(entryUrl);
53
+
54
+ return sameRegistrableDomain(cur.hostname, base.hostname);
55
+ } catch {
56
+ return false;
57
+ }
58
+ };
59
+
22
60
  //! For Cypress Test
23
61
  // env to check if Cypress test is running
24
62
  const isCypressTest = process.env.IS_CYPRESS_TEST === 'true';
@@ -62,20 +100,17 @@ export const screenshotFullPage = async (page, screenshotsDir: string, screensho
62
100
  window.scrollTo(0, document.body.scrollHeight);
63
101
  });
64
102
 
65
- const isLoadMoreContent = async () =>
66
- new Promise(resolve => {
67
- setTimeout(async () => {
68
- await page.waitForLoadState('domcontentloaded');
69
-
70
- const newHeight = await page.evaluate(
71
- // eslint-disable-next-line no-shadow
72
- () => document.body.scrollHeight,
73
- );
74
- const result = newHeight > prevHeight;
75
-
76
- resolve(result);
77
- }, 2500);
78
- });
103
+ const isLoadMoreContent = async () => {
104
+ await new Promise(resolve => setTimeout(resolve, 2500));
105
+ if (page.isClosed()) return false;
106
+ try {
107
+ await page.waitForLoadState('domcontentloaded');
108
+ const newHeight = await page.evaluate(() => document.body.scrollHeight);
109
+ return newHeight > prevHeight;
110
+ } catch {
111
+ return false;
112
+ }
113
+ };
79
114
 
80
115
  const result = await isLoadMoreContent();
81
116
  return result;
@@ -248,7 +283,7 @@ export const updateMenu = async (page, urlsCrawled) => {
248
283
  log(`Overlay menu: updating: ${page.url()}`);
249
284
  await page.evaluate(
250
285
  vars => {
251
- const shadowHost = document.querySelector('#oobee-shadow-host');
286
+ const shadowHost = document.querySelector('#oobeeShadowHost');
252
287
  if (shadowHost) {
253
288
  const p = shadowHost.shadowRoot.querySelector('#oobee-p-pages-scanned');
254
289
  if (p) {
@@ -262,7 +297,6 @@ export const updateMenu = async (page, urlsCrawled) => {
262
297
  consoleLogger.info(`Overlay menu updated`);
263
298
  };
264
299
 
265
-
266
300
  export const addOverlayMenu = async (
267
301
  page,
268
302
  urlsCrawled,
@@ -307,7 +341,7 @@ export const addOverlayMenu = async (
307
341
  `;
308
342
  minBtn.innerHTML = MINBTN_SVG;
309
343
 
310
- let currentPos: 'LEFT' | 'RIGHT' = (vars.menuPos || 'RIGHT');
344
+ let currentPos: 'LEFT' | 'RIGHT' = vars.menuPos || 'RIGHT';
311
345
  const isCollapsed = () => panel.classList.contains('collapsed');
312
346
 
313
347
  const setPosClass = (pos: 'LEFT' | 'RIGHT') => {
@@ -325,7 +359,7 @@ export const addOverlayMenu = async (
325
359
  };
326
360
 
327
361
  const toggleCollapsed = (force?: boolean) => {
328
- const willCollapse = (typeof force === 'boolean') ? force : !isCollapsed();
362
+ const willCollapse = typeof force === 'boolean' ? force : !isCollapsed();
329
363
  if (willCollapse) {
330
364
  panel.classList.add('collapsed');
331
365
  localStorage.setItem('oobee:overlay-collapsed', '1');
@@ -375,25 +409,72 @@ export const addOverlayMenu = async (
375
409
  const h2 = document.createElement('h2');
376
410
  h2.id = 'oobeeHPagesScanned';
377
411
  h2.className = 'oobee-section-title';
378
- h2.textContent = 'Pages Scanned';
379
-
412
+ h2.textContent = `Pages Scanned (${vars.urlsCrawled.scanned.length || 0})`;
413
+
414
+ const scanIcon = document.createElement('span');
415
+ scanIcon.className = 'oobee-btn-icon';
416
+
417
+ const SCAN_SVG = `
418
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
419
+ <g clip-path="url(#clip0_1421_431)">
420
+ <path d="M12.5763 11.5472L12.2958 11.2857L12.1037 11.1005C12.776 10.3183 12.9194 9.56432 12.9194 8.45969C12.9194 5.99657 10.9228 4 8.45969 4C5.99657 4 4 5.99657 4 8.45969C4 10.9228 5.99657 12.9194 8.45969 12.9194C9.56432 12.9194 10.3183 12.776 11.1005 12.1037L11.2857 12.2958L11.5472 12.5763L14.9777 16L16 14.9777L12.5763 11.5472ZM8.45969 11.5472C6.75129 11.5472 5.37221 10.1681 5.37221 8.45969C5.37221 6.75129 6.75129 5.37221 8.45969 5.37221C10.1681 5.37221 11.5472 6.75129 11.5472 8.45969C11.5472 10.1681 10.1681 11.5472 8.45969 11.5472Z" fill="white"/>
421
+ <path d="M18.5 0H19.5C19.7761 0 20 0.223858 20 0.5V5H18.5V0Z" fill="white"/>
422
+ <path d="M19.5 2.18552e-08L19.5 1.5L15 1.5L15 -2.18556e-07L19.5 2.18552e-08Z" fill="white"/>
423
+ <path d="M1.5 0H0.5C0.223858 0 0 0.223858 0 0.5V5H1.5V0Z" fill="white"/>
424
+ <path d="M0.5 2.18552e-08L0.5 1.5L5 1.5L5 -2.18556e-07L0.5 2.18552e-08Z" fill="white"/>
425
+ <path d="M1.5 20H0.5C0.223858 20 0 19.7761 0 19.5V15H1.5V20Z" fill="white"/>
426
+ <path d="M0.5 20L0.5 18.5L5 18.5L5 20L0.5 20Z" fill="white"/>
427
+ <path d="M18.5 20H19.5C19.7761 20 20 19.7761 20 19.5V15H18.5V20Z" fill="white"/>
428
+ <path d="M19.5 20L19.5 18.5L15 18.5L15 20L19.5 20Z" fill="white"/>
429
+ </g>
430
+ <defs>
431
+ <clipPath id="clip0_1421_431">
432
+ <rect width="20" height="20" fill="white"/>
433
+ </clipPath>
434
+ </defs>
435
+ </svg>
436
+ `;
437
+
438
+ scanIcon.innerHTML = SCAN_SVG;
380
439
  const scanBtn = document.createElement('button');
381
440
  scanBtn.id = 'oobeeBtnScan';
382
441
  scanBtn.className = 'oobee-btn oobee-btn-primary';
383
- scanBtn.innerText = 'Scan this page';
384
442
  scanBtn.disabled = inProgress;
443
+ scanBtn.appendChild(scanIcon);
444
+
445
+ const scanText = document.createElement('span');
446
+ scanText.className = 'oobee-btn-text';
447
+ scanText.innerText = 'Scan page';
448
+ scanBtn.appendChild(scanText);
449
+
385
450
  scanBtn.addEventListener('click', async () => customWindow.handleOnScanClick?.());
386
451
 
387
- const stopBtn = document.createElement('button');
388
- stopBtn.id = 'oobeeBtnStop';
389
- stopBtn.className = 'oobee-btn oobee-btn-secondary';
390
- stopBtn.innerText = 'Stop scan';
391
- stopBtn.addEventListener('click', async () => customWindow.handleOnStopClick?.());
452
+ const endScanIcon = document.createElement('span');
453
+ endScanIcon.className = 'oobee-btn-icon';
454
+
455
+ const ENDSCAN_SVG =
456
+ `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
457
+ <path d="M10 0C4.47 0 0 4.47 0 10C0 15.53 4.47 20 10 20C15.53 20 20 15.53 20 10C20 4.47 15.53 0 10 0ZM10 18C5.59 18 2 14.41 2 10C2 5.59 5.59 2 10 2C14.41 2 18 5.59 18 10C18 14.41 14.41 18 10 18ZM13.59 5L10 8.59L6.41 5L5 6.41L8.59 10L5 13.59L6.41 15L10 11.41L13.59 15L15 13.59L11.41 10L15 6.41L13.59 5Z" fill="#9021A6"/>
458
+ </svg>
459
+ `;
460
+
461
+ endScanIcon.innerHTML = ENDSCAN_SVG;
462
+ const endScanBtn = document.createElement('button');
463
+ endScanBtn.id = 'oobeeBtnEndScan';
464
+ endScanBtn.className = 'oobee-btn oobee-btn-secondary';
465
+ endScanBtn.appendChild(endScanIcon);
466
+
467
+ const endScanText = document.createElement('span');
468
+ endScanText.className = 'oobee-btn-text';
469
+ endScanText.innerText = 'End scan';
470
+ endScanBtn.appendChild(endScanText);
471
+
472
+ endScanBtn.addEventListener('click', async () => customWindow.handleOnStopClick?.());
392
473
 
393
474
  const btnGroup = document.createElement('div');
394
475
  btnGroup.className = 'oobee-actions';
395
476
  btnGroup.appendChild(scanBtn);
396
- btnGroup.appendChild(stopBtn);
477
+ btnGroup.appendChild(endScanBtn);
397
478
 
398
479
  const listWrap = document.createElement('div');
399
480
  listWrap.id = 'oobeeList';
@@ -414,13 +495,13 @@ export const addOverlayMenu = async (
414
495
  const ol = document.createElement('ol');
415
496
  ol.className = 'oobee-ol';
416
497
 
417
- scanned.forEach((item) => {
498
+ scanned.forEach(item => {
418
499
  const li = document.createElement('li');
419
500
  li.className = 'oobee-li';
420
501
 
421
502
  const title = document.createElement('div');
422
503
  title.className = 'oobee-item-title';
423
- title.textContent = (item.pageTitle && item.pageTitle.trim()) ? item.pageTitle : item.url;
504
+ title.textContent = item.pageTitle && item.pageTitle.trim() ? item.pageTitle : item.url;
424
505
 
425
506
  const url = document.createElement('div');
426
507
  url.className = 'oobee-item-url';
@@ -469,7 +550,7 @@ export const addOverlayMenu = async (
469
550
  border-right: 1px solid rgba(0,0,0,.08)
470
551
  }
471
552
  .oobee-panel.collapsed {
472
- width: 56px;
553
+ width: 58px;
473
554
  overflow: hidden
474
555
  }
475
556
 
@@ -546,6 +627,12 @@ export const addOverlayMenu = async (
546
627
  padding: 1rem;
547
628
  }
548
629
 
630
+ .oobee-panel.collapsed .oobee-actions {
631
+ display: flex;
632
+ justify-content: center;
633
+ padding: 1rem 0.7rem;
634
+ }
635
+
549
636
  /* Base button */
550
637
  .oobee-btn {
551
638
  width: 100%;
@@ -556,6 +643,10 @@ export const addOverlayMenu = async (
556
643
  line-height: 1.2;
557
644
  font-weight: 400;
558
645
  cursor: pointer;
646
+ display: flex;
647
+ align-items: center;
648
+ justify-content: center;
649
+ gap: 10px;
559
650
  transition: {
560
651
  box-shadow .12s ease,
561
652
  transform .02s ease,
@@ -569,6 +660,19 @@ export const addOverlayMenu = async (
569
660
  cursor:not-allowed
570
661
  }
571
662
 
663
+ .oobee-panel.collapsed .oobee-btn {
664
+ width: 44px !important;
665
+ height: 44px !important;
666
+ min-width: 44px !important;
667
+ min-height: 44px !important;
668
+ max-width: 44px !important;
669
+ max-height: 44px !important;
670
+ border-radius: 50% !important;
671
+ padding: 0 !important;
672
+ justify-content: center;
673
+ gap: 0;
674
+ }
675
+
572
676
  /* Primary (filled) */
573
677
  .oobee-btn-primary {
574
678
  background: #9021a6;
@@ -624,6 +728,25 @@ export const addOverlayMenu = async (
624
728
  display: none;
625
729
  }
626
730
 
731
+ .oobee-btn-icon {
732
+ display: inline-flex;
733
+ align-items: center;
734
+ justify-content: center;
735
+ width: 20px;
736
+ height: 20px;
737
+ vertical-align: middle;
738
+ }
739
+
740
+ .oobee-btn-text {
741
+ display: inline;
742
+ white-space: nowrap;
743
+ vertical-align: middle;
744
+ }
745
+
746
+ .oobee-panel.collapsed .oobee-btn-text {
747
+ display: none;
748
+ }
749
+
627
750
  #oobeeStopOverlay[hidden] {
628
751
  display:none !important;
629
752
  }
@@ -641,7 +764,10 @@ export const addOverlayMenu = async (
641
764
  }
642
765
 
643
766
  .oobee-panel.collapsed .oobee-section-title {
644
- display: none;
767
+ font-size: 14px;
768
+ display: flex;
769
+ justify-content: center;
770
+ text-align: center;
645
771
  }
646
772
 
647
773
  .oobee-ol {
@@ -730,8 +856,7 @@ export const addOverlayMenu = async (
730
856
 
731
857
  const closed = isCollapsed();
732
858
  const arrowPointsRight =
733
- (currentPos === 'RIGHT' && !closed) ||
734
- (currentPos === 'LEFT' && closed);
859
+ (currentPos === 'RIGHT' && !closed) || (currentPos === 'LEFT' && closed);
735
860
 
736
861
  icon.classList.toggle('is-left', !arrowPointsRight);
737
862
  minBtn.setAttribute('aria-label', closed ? 'Expand panel' : 'Collapse panel');
@@ -761,11 +886,11 @@ export const addOverlayMenu = async (
761
886
 
762
887
  grip.addEventListener('pointerdown', (e: PointerEvent) => {
763
888
  startX = e.clientX;
764
- grip.setPointerCapture(e.pointerId); // <-- use the button
889
+ grip.setPointerCapture(e.pointerId); // <-- use the button
765
890
  });
766
891
 
767
892
  grip.addEventListener('pointermove', (e: PointerEvent) => {
768
- if (!grip.hasPointerCapture?.(e.pointerId)) return; // <-- check the button
893
+ if (!grip.hasPointerCapture?.(e.pointerId)) return; // <-- check the button
769
894
  const dx = e.clientX - startX;
770
895
  if (Math.abs(dx) >= THRESH) {
771
896
  const nextPos: 'LEFT' | 'RIGHT' = dx < 0 ? 'LEFT' : 'RIGHT';
@@ -779,7 +904,9 @@ export const addOverlayMenu = async (
779
904
  });
780
905
 
781
906
  grip.addEventListener('pointerup', (e: PointerEvent) => {
782
- try { grip.releasePointerCapture(e.pointerId); } catch {}
907
+ try {
908
+ grip.releasePointerCapture(e.pointerId);
909
+ } catch {}
783
910
  });
784
911
 
785
912
  const stopDialog = document.createElement('dialog');
@@ -791,7 +918,7 @@ export const addOverlayMenu = async (
791
918
  borderRadius: '16px',
792
919
  overflow: 'hidden',
793
920
  boxShadow: '0 10px 40px rgba(0,0,0,.35)',
794
- fontFamily: 'system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif'
921
+ fontFamily: 'system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif',
795
922
  });
796
923
  const dialogSheet = new CSSStyleSheet();
797
924
  dialogSheet.replaceSync(`
@@ -829,13 +956,18 @@ export const addOverlayMenu = async (
829
956
  display: 'flex',
830
957
  alignItems: 'center',
831
958
  justifyContent: 'space-between',
832
- gap: '8px'
959
+ gap: '8px',
833
960
  });
834
961
 
835
962
  const title = document.createElement('h2');
836
963
  title.id = 'oobee-stop-title';
837
964
  title.textContent = 'Are you sure you want to stop this scan?';
838
- Object.assign(title.style, { margin: '0', fontSize: '22px', fontWeight: '700', lineHeight: '1.25' });
965
+ Object.assign(title.style, {
966
+ margin: '0',
967
+ fontSize: '22px',
968
+ fontWeight: '700',
969
+ lineHeight: '1.25',
970
+ });
839
971
 
840
972
  const closeX = document.createElement('button');
841
973
  closeX.type = 'button';
@@ -853,14 +985,14 @@ export const addOverlayMenu = async (
853
985
  height: '36px',
854
986
  borderRadius: '12px',
855
987
  display: 'grid',
856
- placeItems: 'center'
988
+ placeItems: 'center',
857
989
  });
858
990
  head.appendChild(title);
859
991
  head.appendChild(closeX);
860
992
 
861
993
  const bodyWrap = document.createElement('div');
862
994
  Object.assign(bodyWrap.style, {
863
- padding: '12px 20px 20px 20px'
995
+ padding: '12px 20px 20px 20px',
864
996
  });
865
997
 
866
998
  const form = document.createElement('form');
@@ -869,7 +1001,7 @@ export const addOverlayMenu = async (
869
1001
  Object.assign(form.style, {
870
1002
  display: 'grid',
871
1003
  gridTemplateColumns: '1fr',
872
- rowGap: '12px'
1004
+ rowGap: '12px',
873
1005
  });
874
1006
 
875
1007
  const label = document.createElement('label');
@@ -887,7 +1019,7 @@ export const addOverlayMenu = async (
887
1019
  padding: '12px 14px',
888
1020
  fontSize: '14px',
889
1021
  outline: 'none',
890
- boxSizing: 'border-box'
1022
+ boxSizing: 'border-box',
891
1023
  });
892
1024
  input.addEventListener('focus', () => {
893
1025
  input.style.borderColor = '#7b4dff';
@@ -913,7 +1045,7 @@ export const addOverlayMenu = async (
913
1045
  fontWeight: '600',
914
1046
  color: '#fff',
915
1047
  background: '#9021A6',
916
- cursor: 'pointer'
1048
+ cursor: 'pointer',
917
1049
  });
918
1050
 
919
1051
  const cancel = document.createElement('button');
@@ -926,7 +1058,7 @@ export const addOverlayMenu = async (
926
1058
  fontSize: '14px',
927
1059
  justifySelf: 'center',
928
1060
  cursor: 'pointer',
929
- padding: '6px'
1061
+ padding: '6px',
930
1062
  });
931
1063
 
932
1064
  actions.appendChild(primary);
@@ -936,7 +1068,7 @@ export const addOverlayMenu = async (
936
1068
  form.appendChild(label);
937
1069
  form.appendChild(input);
938
1070
  }
939
- form.appendChild(actions);
1071
+ form.appendChild(actions);
940
1072
  bodyWrap.appendChild(form);
941
1073
 
942
1074
  stopDialog.appendChild(head);
@@ -944,17 +1076,27 @@ export const addOverlayMenu = async (
944
1076
  shadowRoot.appendChild(stopDialog);
945
1077
 
946
1078
  let stopResolver: null | ((v: { confirmed: boolean; label: string }) => void) = null;
947
- const hideStop = () => { try { stopDialog.close(); } catch {} stopResolver = null; };
1079
+ const hideStop = () => {
1080
+ try {
1081
+ stopDialog.close();
1082
+ } catch {}
1083
+ stopResolver = null;
1084
+ };
948
1085
  const showStop = () => {
949
1086
  if (!shouldHideInput) input.value = '';
950
- try { stopDialog.showModal(); } catch {}
1087
+ try {
1088
+ stopDialog.showModal();
1089
+ } catch {}
951
1090
  if (!shouldHideInput) {
952
1091
  requestAnimationFrame(() => {
953
- try { input.focus({ preventScroll: true }); input.select(); } catch {}
1092
+ try {
1093
+ input.focus({ preventScroll: true });
1094
+ input.select();
1095
+ } catch {}
954
1096
  });
955
1097
  }
956
1098
  };
957
- form.addEventListener('submit', (e) => {
1099
+ form.addEventListener('submit', e => {
958
1100
  e.preventDefault();
959
1101
  const v = (input.value || '').trim();
960
1102
  if (stopResolver) stopResolver({ confirmed: true, label: v });
@@ -968,13 +1110,13 @@ export const addOverlayMenu = async (
968
1110
  if (stopResolver) stopResolver({ confirmed: false, label: '' });
969
1111
  hideStop();
970
1112
  });
971
- stopDialog.addEventListener('cancel', (e) => {
1113
+ stopDialog.addEventListener('cancel', e => {
972
1114
  e.preventDefault();
973
1115
  if (stopResolver) stopResolver({ confirmed: false, label: '' });
974
1116
  hideStop();
975
1117
  });
976
1118
  (customWindow as Window).oobeeShowStopModal = () =>
977
- new Promise<{ confirmed: boolean; label: string }>((resolve) => {
1119
+ new Promise<{ confirmed: boolean; label: string }>(resolve => {
978
1120
  stopResolver = resolve;
979
1121
  showStop();
980
1122
  });
@@ -1000,7 +1142,7 @@ export const addOverlayMenu = async (
1000
1142
  log('Overlay menu: successfully added');
1001
1143
  })
1002
1144
  .catch(error => {
1003
- error('Overlay menu: failed to add', error);
1145
+ consoleLogger.error('Overlay menu: failed to add', error);
1004
1146
  });
1005
1147
  };
1006
1148
 
@@ -1027,7 +1169,13 @@ export const initNewPage = async (page, pageClosePromises, processPageParams, pa
1027
1169
  // eslint-disable-next-line no-underscore-dangle
1028
1170
  const pageId = page._guid;
1029
1171
 
1030
- page.on('dialog', () => { });
1172
+ page.on('dialog', async dialog => {
1173
+ try {
1174
+ await dialog.dismiss();
1175
+ } catch {
1176
+ // dialog may already be closed
1177
+ }
1178
+ });
1031
1179
 
1032
1180
  const pageClosePromise = new Promise(resolve => {
1033
1181
  page.on('close', () => {
@@ -1058,11 +1206,19 @@ export const initNewPage = async (page, pageClosePromises, processPageParams, pa
1058
1206
  await processPage(page, processPageParams);
1059
1207
  log('Scan: success');
1060
1208
  pagesDict[pageId].isScanning = false;
1061
- await addOverlayMenu(page, processPageParams.urlsCrawled, menuPos, {
1062
- inProgress: false,
1063
- collapsed: !!pagesDict[pageId]?.collapsed,
1064
- hideStopInput: !!processPageParams.customFlowLabel,
1065
- });
1209
+
1210
+ if (page.isClosed()) return;
1211
+ const allowed = isOverlayAllowed(page.url(), processPageParams.entryUrl);
1212
+
1213
+ if (allowed) {
1214
+ await addOverlayMenu(page, processPageParams.urlsCrawled, menuPos, {
1215
+ inProgress: false,
1216
+ collapsed: !!pagesDict[pageId]?.collapsed,
1217
+ hideStopInput: !!processPageParams.customFlowLabel,
1218
+ });
1219
+ } else {
1220
+ await removeOverlayMenu(page);
1221
+ }
1066
1222
  } catch (error) {
1067
1223
  log(`Scan failed ${error}`);
1068
1224
  }
@@ -1093,10 +1249,10 @@ export const initNewPage = async (page, pageClosePromises, processPageParams, pa
1093
1249
 
1094
1250
  if (!inputValue?.confirmed) {
1095
1251
  await page.evaluate(() => {
1096
- const stopBtn = document.getElementById('oobeeBtnStop') as HTMLButtonElement | null;
1097
- if (stopBtn) {
1098
- stopBtn.disabled = false;
1099
- stopBtn.textContent = 'Stop';
1252
+ const endScanBtn = document.getElementById('oobeeBtnEndScan') as HTMLButtonElement | null;
1253
+ if (endScanBtn) {
1254
+ endScanBtn.disabled = false;
1255
+ endScanBtn.textContent = 'Stop';
1100
1256
  }
1101
1257
  });
1102
1258
  return;
@@ -1125,7 +1281,15 @@ export const initNewPage = async (page, pageClosePromises, processPageParams, pa
1125
1281
  };
1126
1282
 
1127
1283
  page.on('domcontentloaded', async () => {
1284
+ if (page.isClosed()) return;
1128
1285
  try {
1286
+ const allowed = isOverlayAllowed(page.url(), processPageParams.entryUrl);
1287
+
1288
+ if (!allowed) {
1289
+ await removeOverlayMenu(page);
1290
+ return;
1291
+ }
1292
+
1129
1293
  const existingOverlay = await page.evaluate(() => {
1130
1294
  return document.querySelector('#oobeeShadowHost');
1131
1295
  });
@@ -1141,12 +1305,6 @@ export const initNewPage = async (page, pageClosePromises, processPageParams, pa
1141
1305
  });
1142
1306
  }
1143
1307
 
1144
- setTimeout(() => {
1145
- // Timeout here to slow things down a little
1146
- }, 1000);
1147
-
1148
- //! For Cypress Test
1149
- // Auto-clicks 'Scan this page' button only once
1150
1308
  if (isCypressTest) {
1151
1309
  try {
1152
1310
  await handleOnScanClick();
@@ -1155,27 +1313,29 @@ export const initNewPage = async (page, pageClosePromises, processPageParams, pa
1155
1313
  consoleLogger.info(`Error in calling handleOnScanClick, isCypressTest: ${isCypressTest}`);
1156
1314
  }
1157
1315
  }
1158
-
1159
- consoleLogger.info(`Overlay state: ${existingOverlay}`);
1160
1316
  } catch {
1161
1317
  consoleLogger.info('Error in adding overlay menu to page');
1162
- consoleLogger.info('Error in adding overlay menu to page');
1163
1318
  }
1164
1319
  });
1165
1320
 
1166
- await page.exposeFunction('handleOnScanClick', handleOnScanClick);
1167
- await page.exposeFunction('handleOnStopClick', handleOnStopClick);
1321
+ try {
1322
+ if (page.isClosed()) return page;
1323
+ await page.exposeFunction('handleOnScanClick', handleOnScanClick);
1324
+ await page.exposeFunction('handleOnStopClick', handleOnStopClick);
1168
1325
 
1169
- type UpdateMenuPosFunction = (newPos: any) => void;
1326
+ type UpdateMenuPosFunction = (newPos: any) => void;
1170
1327
 
1171
- // Define the updateMenuPos function
1172
- const updateMenuPos: UpdateMenuPosFunction = newPos => {
1173
- const prevPos = menuPos;
1174
- if (prevPos !== newPos) {
1175
- menuPos = newPos;
1176
- }
1177
- };
1178
- await page.exposeFunction('updateMenuPos', updateMenuPos);
1328
+ // Define the updateMenuPos function
1329
+ const updateMenuPos: UpdateMenuPosFunction = newPos => {
1330
+ const prevPos = menuPos;
1331
+ if (prevPos !== newPos) {
1332
+ menuPos = newPos;
1333
+ }
1334
+ };
1335
+ await page.exposeFunction('updateMenuPos', updateMenuPos);
1336
+ } catch (e) {
1337
+ log(`Error exposing functions on page: ${e}`);
1338
+ }
1179
1339
 
1180
1340
  return page;
1181
1341
  };