77 "encoding/json"
88 "errors"
99 "regexp"
10+ "strings"
1011 "sync"
1112 "testing"
1213 "time"
@@ -58,14 +59,26 @@ func TestAnalyze_FindingFound(t *testing.T) {
5859 // --- Mocks ---
5960 mockBrowserManager .On ("NewAnalysisContext" , ctx , cfg , schemas.Persona {}, "" , "" , (chan <- schemas.Finding )(nil )).Return (mockSession , nil ).Once ()
6061
61- mockSession .On ("ExposeFunction" , ctx , jsCallbackName , mock .AnythingOfType ("func(proto.PollutionProofEvent)" )).Return (nil ).Once ()
62+ // The callback name is now randomized, so we need to capture it.
63+ var capturedCallbackName string
64+ mockSession .On ("ExposeFunction" , ctx , mock .MatchedBy (func (name string ) bool {
65+ return strings .HasPrefix (name , "sclp_cb_" )
66+ }), mock .AnythingOfType ("func(proto.PollutionProofEvent)" )).Return (nil ).Once ().Run (func (args mock.Arguments ) {
67+ capturedCallbackName = args .String (1 )
68+ })
6269
6370 mockSession .On ("InjectScriptPersistently" , ctx , mock .AnythingOfType ("string" )).Return (nil ).Once ().Run (func (args mock.Arguments ) {
6471 script := args .String (1 )
65- re := regexp .MustCompile (`let pollutionCanary = '([^']+)';` )
66- matches := re .FindStringSubmatch (script )
67- require .Len (t , matches , 2 , "Could not find canary in injected script." )
68- capturedCanary = matches [1 ]
72+ canaryRe := regexp .MustCompile (`let pollutionCanary = '([^']+)';` )
73+ canaryMatches := canaryRe .FindStringSubmatch (script )
74+ require .Len (t , canaryMatches , 2 , "Could not find canary in injected script." )
75+ capturedCanary = canaryMatches [1 ]
76+
77+ callbackRe := regexp .MustCompile (`let detectionCallbackName = '([^']+)';` )
78+ callbackMatches := callbackRe .FindStringSubmatch (script )
79+ require .Len (t , callbackMatches , 2 , "Could not find callback name in injected script." )
80+ // We assert that the callback name in the script matches the one passed to ExposeFunction.
81+ assert .Equal (t , capturedCallbackName , callbackMatches [1 ])
6982 })
7083
7184 mockSession .On ("AddFinding" , ctx , mock .AnythingOfType ("schemas.Finding" )).Return (nil ).Once ().Run (func (args mock.Arguments ) {
@@ -78,9 +91,10 @@ func TestAnalyze_FindingFound(t *testing.T) {
7891 go func () {
7992 time .Sleep (20 * time .Millisecond )
8093 require .NotEmpty (t , capturedCanary , "Canary was not captured before navigation simulation" )
94+ require .NotEmpty (t , capturedCallbackName , "Callback name was not captured before navigation simulation" )
8195
8296 // Use the mock's helper to get the function and call it.
83- fn , ok := mockSession .GetExposedFunction (jsCallbackName )
97+ fn , ok := mockSession .GetExposedFunction (capturedCallbackName )
8498 require .True (t , ok , "Callback function was not set via ExposeFunction" )
8599 callback , ok := fn .(func (PollutionProofEvent ))
86100 require .True (t , ok , "Exposed function has the wrong signature" )
@@ -141,7 +155,7 @@ func TestAnalyze_NoFinding(t *testing.T) {
141155 ctx := context .Background ()
142156
143157 mockBrowserManager .On ("NewAnalysisContext" , ctx , cfg , schemas.Persona {}, "" , "" , (chan <- schemas.Finding )(nil )).Return (mockSession , nil )
144- mockSession .On ("ExposeFunction" , ctx , jsCallbackName , mock .AnythingOfType ("func(proto.PollutionProofEvent)" )).Return (nil ).Once ()
158+ mockSession .On ("ExposeFunction" , ctx , mock . AnythingOfType ( "string" ) , mock .AnythingOfType ("func(proto.PollutionProofEvent)" )).Return (nil ).Once ()
145159 mockSession .On ("InjectScriptPersistently" , ctx , mock .AnythingOfType ("string" )).Return (nil )
146160 mockSession .On ("Navigate" , ctx , "http://clean.example.com" ).Return (nil )
147161 mockSession .On ("Close" , mock .Anything ).Return (nil )
@@ -183,7 +197,7 @@ func TestAnalyze_ContextCancellation(t *testing.T) {
183197 ctx , cancel := context .WithCancel (context .Background ())
184198
185199 mockBrowserManager .On ("NewAnalysisContext" , mock .Anything , cfg , schemas.Persona {}, "" , "" , (chan <- schemas.Finding )(nil )).Return (mockSession , nil )
186- mockSession .On ("ExposeFunction" , mock .Anything , jsCallbackName , mock .AnythingOfType ("func(proto.PollutionProofEvent)" )).Return (nil )
200+ mockSession .On ("ExposeFunction" , mock .Anything , mock . AnythingOfType ( "string" ) , mock .AnythingOfType ("func(proto.PollutionProofEvent)" )).Return (nil )
187201 mockSession .On ("InjectScriptPersistently" , mock .Anything , mock .AnythingOfType ("string" )).Return (nil )
188202 mockSession .On ("Navigate" , mock .Anything , "http://slow.example.com" ).Return (nil ).Run (func (args mock.Arguments ) {
189203 go func () {
@@ -216,7 +230,7 @@ func TestAnalyze_InstrumentationError(t *testing.T) {
216230 expectedErr := errors .New ("browser disconnected" )
217231
218232 mockBrowserManager .On ("NewAnalysisContext" , ctx , cfg , schemas.Persona {}, "" , "" , (chan <- schemas.Finding )(nil )).Return (mockSession , nil )
219- mockSession .On ("ExposeFunction" , ctx , jsCallbackName , mock .Anything ).Return (expectedErr )
233+ mockSession .On ("ExposeFunction" , ctx , mock . AnythingOfType ( "string" ) , mock .Anything ).Return (expectedErr )
220234 mockSession .On ("Close" , ctx ).Return (nil )
221235
222236 err := analyzer .Analyze (ctx , "task-instrument-fail" , "http://example.com" )
@@ -237,14 +251,18 @@ func TestAnalyze_MismatchedCanary(t *testing.T) {
237251 analyzer := NewAnalyzer (logger , mockBrowserManager , cfg )
238252 ctx := context .Background ()
239253
254+ var capturedCallbackName string
240255 mockBrowserManager .On ("NewAnalysisContext" , ctx , cfg , schemas.Persona {}, "" , "" , (chan <- schemas.Finding )(nil )).Return (mockSession , nil )
241- mockSession .On ("ExposeFunction" , ctx , jsCallbackName , mock .AnythingOfType ("func(proto.PollutionProofEvent)" )).Return (nil )
256+ mockSession .On ("ExposeFunction" , ctx , mock .AnythingOfType ("string" ), mock .AnythingOfType ("func(proto.PollutionProofEvent)" )).Return (nil ).Run (func (args mock.Arguments ) {
257+ capturedCallbackName = args .String (1 )
258+ })
242259 mockSession .On ("InjectScriptPersistently" , ctx , mock .AnythingOfType ("string" )).Return (nil )
243260 mockSession .On ("Navigate" , ctx , "http://example.com" ).Return (nil ).Run (func (args mock.Arguments ) {
244261 go func () {
245262 time .Sleep (10 * time .Millisecond )
263+ require .NotEmpty (t , capturedCallbackName )
246264 // Use the mock's helper to get the function and call it.
247- fn , ok := mockSession .GetExposedFunction (jsCallbackName )
265+ fn , ok := mockSession .GetExposedFunction (capturedCallbackName )
248266 require .True (t , ok , "Callback function was not set via ExposeFunction" )
249267 callback , ok := fn .(func (PollutionProofEvent ))
250268 require .True (t , ok , "Exposed function has the wrong signature" )
0 commit comments