@@ -8,32 +8,28 @@ import { assertEquals } from "@std/assert";
88import { handleXMigration , ClientTransaction } from "./mod.ts" ;
99
1010/**
11- * Test to verify the transaction ID generation process with default keys
11+ * Test to verify the transaction ID generation process
1212 *
1313 * This test performs the following steps:
14- * 1. Fetches the X homepage and extracts guest token
15- * 2. Creates a ClientTransaction instance
16- * 3. Generates a transaction ID for a specific API endpoint using default keys
14+ * 1. Fetches the X homepage and extracts guest token for each request
15+ * 2. Creates a new ClientTransaction instance for each request
16+ * 3. Generates a transaction ID for a specific API endpoint
1717 * 4. Makes 25 API requests and verifies all of them are successful (100% success rate)
18+ *
19+ * Note: Rate limiting may occur. Rate limiting produces the same 404 errors
20+ * as an invalid x-client-transaction-id. If more than 50% of requests return 404
21+ * or if all requests fail with 404, try opening any user profile page in Chrome
22+ * in private to check. If rate limiting is in effect, Chrome will also show errors.
1823 */
1924Deno . test (
20- "Generate and verify transaction ID for X API UserByScreenName endpoint with default keys " ,
25+ "Generate and verify transaction ID for X API UserByScreenName endpoint" ,
2126 async ( ) => {
22- // Arrange: Set up necessary data and objects
23- const document = await handleXMigration ( ) ;
24- const guestToken =
25- document . documentElement . outerHTML . match ( / g t = ( [ 0 - 9 ] + ) ; / ) ?. [ 1 ] || null ;
26-
27- if ( ! guestToken ) {
28- throw new Error ( "Failed to extract guest token from the document" ) ;
29- }
30-
31- const ct = await ClientTransaction . create ( document ) ;
3227 const totalRequests = 25 ;
3328 let successfulRequests = 0 ;
29+ let notFoundErrors = 0 ;
3430
35- // Create a base request
36- const createRequest = ( ) =>
31+ // Create a base request function
32+ const createRequest = ( guestToken : string ) =>
3733 new Request (
3834 "https://api.x.com/graphql/1VOOyvKkiI3FMmkeDNxM9A/UserByScreenName?variables=%7B%22screen_name%22%3A%22elonmusk%22%7D&features=%7B%22hidden_profile_subscriptions_enabled%22%3Atrue%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22subscriptions_verification_info_is_identity_verified_enabled%22%3Atrue%2C%22subscriptions_verification_info_verified_since_enabled%22%3Atrue%2C%22highlights_tweets_tab_ui_enabled%22%3Atrue%2C%22responsive_web_twitter_article_notes_tab_enabled%22%3Atrue%2C%22subscriptions_feature_can_gift_premium%22%3Atrue%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%7D&fieldToggles=%7B%22withAuxiliaryUserLabels%22%3Atrue%7D" ,
3935 {
@@ -65,10 +61,30 @@ Deno.test(
6561 ) ;
6662
6763 // Act: Generate multiple transaction IDs and test them
68- console . log ( `Running ${ totalRequests } API requests with default keys ...` ) ;
64+ console . log ( `Running ${ totalRequests } API requests...` ) ;
6965
7066 for ( let i = 0 ; i < totalRequests ; i ++ ) {
71- const request = createRequest ( ) ;
67+ console . log ( `Request ${ i + 1 } /${ totalRequests } : Fetching X homepage...` ) ;
68+
69+ // Create new document and ClientTransaction instance for each request
70+ const document = await handleXMigration ( ) ;
71+ const guestToken =
72+ document . documentElement . outerHTML . match ( / g t = ( [ 0 - 9 ] + ) ; / ) ?. [ 1 ] || null ;
73+
74+ if ( ! guestToken ) {
75+ console . error (
76+ `Request ${ i + 1 } : Failed to extract guest token from the document`
77+ ) ;
78+ continue ;
79+ }
80+
81+ // Create a new ClientTransaction instance
82+ const ct = await ClientTransaction . create ( document ) ;
83+
84+ // Create request with fresh guest token
85+ const request = createRequest ( guestToken ) ;
86+
87+ // Generate transaction ID with the fresh ClientTransaction instance
7288 const transactionId = await ct . generateTransactionId (
7389 request . method ,
7490 new URL ( request . url ) . pathname
@@ -77,22 +93,29 @@ Deno.test(
7793
7894 // Execute the request
7995 try {
96+ console . log ( `Request ${ i + 1 } /${ totalRequests } : Executing API call...` ) ;
8097 const response = await fetch ( request ) ;
8198 await response . text ( ) ;
8299
83100 if ( response . ok ) {
84101 successfulRequests ++ ;
102+ console . log ( `Request ${ i + 1 } /${ totalRequests } : Success` ) ;
85103 } else {
86104 console . error (
87- `Request ${ i + 1 } failed with status: ${ response . status } `
105+ `Request ${ i + 1 } /${ totalRequests } : Failed with status: ${
106+ response . status
107+ } `
88108 ) ;
109+ if ( response . status === 404 ) {
110+ notFoundErrors ++ ;
111+ }
89112 }
90113 } catch ( error ) {
91- console . error ( `Request ${ i + 1 } error :` , error ) ;
114+ console . error ( `Request ${ i + 1 } / ${ totalRequests } : Error :` , error ) ;
92115 }
93116
94117 // Small delay between requests to avoid rate limiting
95- await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) ) ;
118+ await new Promise ( ( resolve ) => setTimeout ( resolve , 200 ) ) ;
96119 }
97120
98121 console . log (
@@ -101,6 +124,24 @@ Deno.test(
101124 100
102125 ) . toFixed ( 2 ) } %)`
103126 ) ;
127+ console . log (
128+ `404 Not Found errors: ${ notFoundErrors } /${ totalRequests } (${ (
129+ ( notFoundErrors / totalRequests ) *
130+ 100
131+ ) . toFixed ( 2 ) } %)`
132+ ) ;
133+
134+ if (
135+ notFoundErrors > totalRequests / 2 ||
136+ notFoundErrors === totalRequests
137+ ) {
138+ console . warn (
139+ "Possible rate limiting detected. Try opening any user profile page in Chrome to verify."
140+ ) ;
141+ console . warn (
142+ "If rate limiting is occurring, errors will also appear in the browser."
143+ ) ;
144+ }
104145
105146 // Assert: Verify all requests were successful (100% success rate)
106147 assertEquals (
0 commit comments