@@ -197,4 +197,91 @@ describe("basic polling sdk works as expected", () => {
197197 expect ( counter ) . toBe ( 2 ) ;
198198 } ) ;
199199 } ) ;
200+
201+ describe ( "attributeHeader hashing" , ( ) => {
202+ const TEST_HASH = "n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg" ;
203+ const USER_ID_HASH = "F7827sASf1GewZfMvDzBlYpLnaFcKM0xchzNEElvh94" ;
204+ const SESSION_HASH = "ZJ2mGsLI7CqpUgmQqueaBudcjnxW6SZ9uVuwMWASoe4" ;
205+
206+ it ( "should produce consistent hash results for context headers" , async ( ) => {
207+ class TestPoller extends PollingBase {
208+ constructor ( ) {
209+ super ( "" , 0 , ( ) => { } ) ;
210+ }
211+
212+ poll ( ) : Promise < void > {
213+ return Promise . resolve ( ) ;
214+ }
215+
216+ // Expose the protected _shaHeader for testing
217+ get shaHeader ( ) : string {
218+ return this . _shaHeader ;
219+ }
220+ }
221+
222+ const testPoller = new TestPoller ( ) ;
223+
224+ // Test known hash values to ensure consistency
225+ await testPoller . attributeHeader ( "" ) ;
226+ expect ( testPoller . shaHeader ) . toBe ( "0" ) ;
227+
228+ await testPoller . attributeHeader ( "test" ) ;
229+ expect ( testPoller . shaHeader ) . toBe ( TEST_HASH ) ;
230+
231+ await testPoller . attributeHeader ( "user-id:12345" ) ;
232+ expect ( testPoller . shaHeader ) . toBe ( USER_ID_HASH ) ;
233+
234+ await testPoller . attributeHeader ( "user-id:12345,session:abcdef" ) ;
235+ expect ( testPoller . shaHeader ) . toBe ( SESSION_HASH ) ;
236+ } ) ;
237+
238+ it ( "produces same hash results in browser environment as node environment" , async ( ) => {
239+ // Create JSDOM environment to simulate browser
240+ const { JSDOM } = await import ( "jsdom" ) ;
241+ const dom = new JSDOM ( "" , {
242+ url : "https://localhost" ,
243+ pretendToBeVisual : true ,
244+ resources : "usable" ,
245+ } ) ;
246+
247+ // Store original window
248+ const originalWindow = ( globalThis as any ) . window ;
249+
250+ try {
251+ // Set up browser-like environment
252+ ( globalThis as any ) . window = dom . window ;
253+
254+ Object . defineProperty ( globalThis , "window" , {
255+ value : dom . window ,
256+ writable : true ,
257+ configurable : true ,
258+ } ) ;
259+
260+ const { webcrypto } = await import ( "crypto" ) ;
261+ Object . defineProperty ( globalThis . window , "crypto" , {
262+ value : {
263+ ...webcrypto ,
264+ subtle : webcrypto . subtle ,
265+ } ,
266+ writable : true ,
267+ configurable : true ,
268+ } ) ;
269+
270+ const { createBase64UrlSafeHash } = await import ( "../crypto/crypto-browser" ) ;
271+
272+ const testHash = await createBase64UrlSafeHash ( "sha256" , "test" ) ;
273+ expect ( testHash ) . toBe ( TEST_HASH ) ;
274+
275+ const userIdHash = await createBase64UrlSafeHash ( "sha256" , "user-id:12345" ) ;
276+ expect ( userIdHash ) . toBe ( USER_ID_HASH ) ;
277+
278+ const sessionHash = await createBase64UrlSafeHash ( "sha256" , "user-id:12345,session:abcdef" ) ;
279+ expect ( sessionHash ) . toBe ( SESSION_HASH ) ;
280+ } finally {
281+ // Restore original window
282+ ( globalThis as any ) . window = originalWindow ;
283+ dom . window . close ( ) ;
284+ }
285+ } ) ;
286+ } ) ;
200287} ) ;
0 commit comments