@@ -15,6 +15,7 @@ const {
1515 isNil,
1616 getWindowLocation,
1717 getCanonicalUrl,
18+ getDocumentReferrer,
1819 dispatchEvent,
1920 createCustomEvent,
2021 hasOrderIdRecord,
@@ -23,6 +24,8 @@ const {
2324 stringify,
2425 convertResponseToJson,
2526 addHTTPSToString,
27+ trimUrl,
28+ cleanAndValidateUrl,
2629} = require ( '../../../test/utils/helpers' ) ; // eslint-disable-line import/extensions
2730const jsdom = require ( './jsdom-global' ) ;
2831const store = require ( '../../../test/utils/store' ) ; // eslint-disable-line import/extensions
@@ -215,6 +218,18 @@ describe('ConstructorIO - Utils - Helpers', () => {
215218 } ) ;
216219
217220 describe ( 'getCanonicalUrl' , ( ) => {
221+ it ( 'Should return android app referrers in a valid url structure' , ( ) => {
222+ const cleanup = jsdom ( ) ;
223+
224+ const canonicalUrl = 'android-app://com.google.android.googlequicksearchbox/' ;
225+ const canonicalEle = document . querySelector ( '[rel=canonical]' ) ;
226+ canonicalEle . setAttribute ( 'href' , canonicalUrl ) ;
227+
228+ expect ( getCanonicalUrl ( ) ) . to . equal ( 'https://com.google.android.googlequicksearchbox/' ) ;
229+
230+ cleanup ( ) ;
231+ } ) ;
232+
218233 it ( 'Should return the canonical URL from the DOM link element' , ( ) => {
219234 const cleanup = jsdom ( ) ;
220235
@@ -264,6 +279,67 @@ describe('ConstructorIO - Utils - Helpers', () => {
264279 } ) ;
265280 } ) ;
266281
282+ describe ( 'getDocumentReferrer' , ( ) => {
283+ it ( 'Should return android app referrers in a valid url structure' , ( ) => {
284+ const cleanup = jsdom ( ) ;
285+
286+ const referrerUrl = 'android-app://com.google.android.googlequicksearchbox/' ;
287+ Object . defineProperty ( document , 'referrer' , {
288+ value : referrerUrl ,
289+ configurable : true ,
290+ } ) ;
291+
292+ expect ( getDocumentReferrer ( ) ) . to . equal ( 'https://com.google.android.googlequicksearchbox/' ) ;
293+
294+ cleanup ( ) ;
295+ } ) ;
296+
297+ it ( 'Should return the referrer URL from the document' , ( ) => {
298+ const cleanup = jsdom ( ) ;
299+
300+ const referrerUrl = 'https://constructor.io/products/item' ;
301+ Object . defineProperty ( document , 'referrer' , {
302+ value : referrerUrl ,
303+ configurable : true ,
304+ } ) ;
305+
306+ expect ( getDocumentReferrer ( ) ) . to . equal ( referrerUrl ) ;
307+
308+ cleanup ( ) ;
309+ } ) ;
310+
311+ it ( 'Should return null for a relative url' , ( ) => {
312+ const cleanup = jsdom ( ) ;
313+
314+ const relativeUrl = '/products/item' ;
315+ Object . defineProperty ( document , 'referrer' , {
316+ value : relativeUrl ,
317+ configurable : true ,
318+ } ) ;
319+
320+ const result = getDocumentReferrer ( ) ;
321+ expect ( result ) . to . be . null ;
322+
323+ cleanup ( ) ;
324+ } ) ;
325+
326+ it ( 'Should return null when referrer is empty' , ( ) => {
327+ const cleanup = jsdom ( ) ;
328+
329+ Object . defineProperty ( document , 'referrer' , {
330+ value : '' ,
331+ configurable : true ,
332+ } ) ;
333+
334+ expect ( getDocumentReferrer ( ) ) . to . be . null ;
335+ cleanup ( ) ;
336+ } ) ;
337+
338+ it ( 'Should return null when not in a DOM context' , ( ) => {
339+ expect ( getDocumentReferrer ( ) ) . to . be . null ;
340+ } ) ;
341+ } ) ;
342+
267343 describe ( 'dispatchEvent' , ( ) => {
268344 it ( 'Should dispatch an event if in a DOM context' , ( ) => {
269345 const cleanup = jsdom ( ) ;
@@ -539,5 +615,88 @@ describe('ConstructorIO - Utils - Helpers', () => {
539615 expect ( addHTTPSToString ( testUrl ) ) . to . equal ( null ) ;
540616 } ) ;
541617 } ) ;
618+
619+ describe ( 'trimUrl' , ( ) => {
620+ it ( 'Should return the URL as-is if it is under the max length' , ( ) => {
621+ const testUrl = new URL ( 'https://www.constructor.io/search?q=test' ) ;
622+ const result = trimUrl ( testUrl ) ;
623+
624+ expect ( result ) . to . equal ( 'https://www.constructor.io/search?q=test' ) ;
625+ } ) ;
626+
627+ it ( 'Should remove the longest parameter when URL exceeds max length' , ( ) => {
628+ const longValue = 'a' . repeat ( 2000 ) ;
629+ const testUrl = new URL ( `https://www.constructor.io/search?short=b&long=${ longValue } ` ) ;
630+ const result = trimUrl ( testUrl , 100 ) ;
631+
632+ expect ( result ) . to . include ( 'short=b' ) ;
633+ expect ( result ) . to . not . include ( 'long=' ) ;
634+ expect ( result . length ) . to . be . at . most ( 100 ) ;
635+ } ) ;
636+
637+ it ( 'Should remove multiple parameters starting with the longest' , ( ) => {
638+ const testUrl = new URL ( 'https://www.constructor.io/search?a=1&b=22&c=333&d=4444' ) ;
639+ const result = trimUrl ( testUrl , 50 ) ;
640+
641+ expect ( result . length ) . to . be . at . most ( 50 ) ;
642+ } ) ;
643+
644+ it ( 'Should truncate URL if removing all parameters is not enough' , ( ) => {
645+ const longPath = 'a' . repeat ( 2000 ) ;
646+ const testUrl = new URL ( `https://www.constructor.io/${ longPath } ` ) ;
647+ const result = trimUrl ( testUrl , 100 ) ;
648+
649+ expect ( result . length ) . to . equal ( 100 ) ;
650+ } ) ;
651+
652+ it ( 'Should use custom maxLen parameter' , ( ) => {
653+ const testUrl = new URL ( 'https://www.constructor.io/search?param=value' ) ;
654+ const customMaxLen = 30 ;
655+ const result = trimUrl ( testUrl , customMaxLen ) ;
656+
657+ expect ( result . length ) . to . be . at . most ( customMaxLen ) ;
658+ } ) ;
659+ } ) ;
660+
661+ describe ( 'cleanAndValidateUrl' , ( ) => {
662+ it ( 'Should return a valid URL string' , ( ) => {
663+ const testUrl = 'https://www.constructor.io/search?q=test' ;
664+ const result = cleanAndValidateUrl ( testUrl ) ;
665+
666+ expect ( result ) . to . equal ( testUrl ) ;
667+ } ) ;
668+
669+ it ( 'Should handle android-app referrers by converting to https' , ( ) => {
670+ const androidUrl = 'android-app://com.google.android.googlequicksearchbox/path' ;
671+ const result = cleanAndValidateUrl ( androidUrl ) ;
672+
673+ expect ( result ) . to . include ( 'https://' ) ;
674+ expect ( result ) . to . include ( 'com.google.android.googlequicksearchbox' ) ;
675+ } ) ;
676+
677+ it ( 'Should return null for invalid URLs' , ( ) => {
678+ const invalidUrl = 'not a valid url' ;
679+ const result = cleanAndValidateUrl ( invalidUrl ) ;
680+
681+ expect ( result ) . to . be . null ;
682+ } ) ;
683+
684+ it ( 'Should handle relative URLs with baseUrl' , ( ) => {
685+ const relativeUrl = '/search?q=test' ;
686+ const baseUrl = 'https://www.constructor.io' ;
687+ const result = cleanAndValidateUrl ( relativeUrl , baseUrl ) ;
688+
689+ expect ( result ) . to . include ( 'https://www.constructor.io/search?q=test' ) ;
690+ } ) ;
691+
692+ it ( 'Should trim URLs that exceed max length' , ( ) => {
693+ const longValue = 'a' . repeat ( 2000 ) ;
694+ const testUrl = `https://www.constructor.io/search?param=${ longValue } ` ;
695+ const result = cleanAndValidateUrl ( testUrl ) ;
696+
697+ expect ( result ) . to . not . be . null ;
698+ expect ( result . length ) . to . be . at . most ( 2000 ) ;
699+ } ) ;
700+ } ) ;
542701 }
543702} ) ;
0 commit comments