1+ import type { PatternMapValue } from '../../src/runtime/types'
12import { describe , expect , it } from 'vitest'
2- import { isBotFromHeaders } from '../../src/util'
3+ import { createPatternMap , getBotDetection , isBotFromHeaders } from '../../src/util'
34
45const ValidHeaders = {
56 'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' ,
@@ -11,6 +12,12 @@ const ValidHeaders = {
1112}
1213
1314describe ( 'bot Detection from Headers' , ( ) => {
15+ it . each ( [ ...createPatternMap ( ) . keys ( ) ] ) ( 'matches the default %s pattern with reusable-map semantics' , ( pattern ) => {
16+ const headers = { 'user-agent' : `Mozilla/5.0 compatible ${ pattern } /1.0` }
17+
18+ expect ( isBotFromHeaders ( headers ) ) . toEqual ( isBotFromHeaders ( headers , createPatternMap ( ) ) )
19+ } )
20+
1421 // Test empty user agent handling
1522 it ( 'handles empty user agent properly' , ( ) => {
1623 const result = isBotFromHeaders ( { } )
@@ -103,6 +110,24 @@ describe('bot Detection from Headers', () => {
103110 expect ( result . data ?. trusted ) . toBe ( false )
104111 } )
105112
113+ it ( 'preserves definition priority over match position' , ( ) => {
114+ const result = isBotFromHeaders ( { 'user-agent' : 'SomeRandomBot/1.0 Googlebot/2.1' } )
115+
116+ expect ( result . data ?. botName ) . toBe ( 'googlebot' )
117+ } )
118+
119+ it ( 'preserves reusable-map priority for every pair of default patterns' , ( ) => {
120+ const patternMap = createPatternMap ( )
121+ const patterns = [ ...patternMap . keys ( ) ]
122+
123+ for ( const firstPattern of patterns ) {
124+ for ( const secondPattern of patterns ) {
125+ const headers = { 'user-agent' : `${ firstPattern } /${ secondPattern } ` }
126+ expect ( isBotFromHeaders ( headers ) ) . toEqual ( isBotFromHeaders ( headers , patternMap ) )
127+ }
128+ }
129+ } )
130+
106131 // Test human traffic
107132 it ( 'identifies likely human traffic' , ( ) => {
108133 const result = isBotFromHeaders ( ValidHeaders )
@@ -129,4 +154,49 @@ describe('bot Detection from Headers', () => {
129154
130155 expect ( result . isBot ) . toBe ( false )
131156 } )
157+
158+ it ( 'uses a caller-provided bot map' , ( ) => {
159+ const customMap = new Map < string , PatternMapValue > ( [
160+ [ 'private-crawler' , { botName : 'private' , botCategory : 'scraping' , trusted : false } ] ,
161+ ] )
162+
163+ const result = getBotDetection ( { 'user-agent' : 'Private-Crawler/1.0' } , customMap )
164+
165+ expect ( result ) . toEqual ( {
166+ isBot : true ,
167+ userAgent : 'Private-Crawler/1.0' ,
168+ detectionMethod : 'headers' ,
169+ botName : 'private' ,
170+ botCategory : 'scraping' ,
171+ trusted : false ,
172+ } )
173+ } )
174+
175+ it ( 'keeps caller-provided bot maps isolated' , async ( ) => {
176+ const firstMap = new Map < string , PatternMapValue > ( [
177+ [ 'first-crawler' , { botName : 'first' , botCategory : 'scraping' , trusted : false } ] ,
178+ ] )
179+ const secondMap = new Map < string , PatternMapValue > ( [
180+ [ 'second-crawler' , { botName : 'second' , botCategory : 'search-engine' , trusted : true } ] ,
181+ ] )
182+
183+ const [ firstResult , secondResult ] = await Promise . all ( [
184+ Promise . resolve ( isBotFromHeaders ( { 'user-agent' : 'First-Crawler/1.0' } , firstMap ) ) ,
185+ Promise . resolve ( isBotFromHeaders ( { 'user-agent' : 'Second-Crawler/1.0' } , secondMap ) ) ,
186+ ] )
187+
188+ expect ( firstResult . data ?. botName ) . toBe ( 'first' )
189+ expect ( secondResult . data ?. botName ) . toBe ( 'second' )
190+ expect ( isBotFromHeaders ( { 'user-agent' : 'First-Crawler/1.0' } , secondMap ) ) . toEqual ( { isBot : false } )
191+ } )
192+
193+ it ( 'returns independently mutable pattern maps' , ( ) => {
194+ const firstMap = createPatternMap ( )
195+ const secondMap = createPatternMap ( )
196+
197+ firstMap . clear ( )
198+
199+ expect ( isBotFromHeaders ( { 'user-agent' : 'Googlebot/2.1' } , firstMap ) ) . toEqual ( { isBot : false } )
200+ expect ( isBotFromHeaders ( { 'user-agent' : 'Googlebot/2.1' } , secondMap ) . data ?. botName ) . toBe ( 'googlebot' )
201+ } )
132202} )
0 commit comments