import assert from 'node:assert/strict'; import { beginSearchRequestPolicy, beginNoteOpenRequestPolicy, beginReadonlyRequestPolicy, endPlatformRequestPolicy, matchPlatformRequest, SEARCH_POLICY_VERSION, NOTE_POLICY_VERSION, READONLY_POLICY_VERSION, SEARCH_SCROLL_POLICY_VERSION } from './platform-policy.mjs'; const official = 'https://www.xiaohongshu.com'; const observed = { kind: 'fill', tag: 'input', unique: true, search_input: true, sensitive: false }; const actual = { tag: 'input', search_input: true, sensitive: false, visible: true, in_viewport: true, unobscured: true }; const action = { sessionOrigin: official, pageUrl: `${official}/explore`, kind: 'fill', observed, actual, matchCount: 1 }; const policy = beginSearchRequestPolicy(action); assert.ok(policy); const request = { policy, automating: true, sessionOrigin: official, pageUrl: `${official}/search_result_ai?keyword=fixture`, activeMainFrame: true, method: 'POST', resourceType: 'xhr', url: 'https://so.xiaohongshu.com/api/sns/web/v2/search/notes' }; let assertions = 1; function check(value, expected = null) { assert.deepEqual(value, expected); assertions += 1; } for (const [rule, url, resourceType = 'xhr'] of [ ['collect', 'https://t2.xiaohongshu.com/api/v2/collect'], ['search_history', 'https://so.xiaohongshu.com/api/sns/web/search/history/sync'], ['search_notes', 'https://so.xiaohongshu.com/api/sns/web/v2/search/notes'], ['search_onebox', 'https://edith.xiaohongshu.com/api/sns/web/v1/search/onebox'], ['search_dqa', 'https://so.xiaohongshu.com/api/sns/web/v1/dqa/instant'], ['apm_data', 'https://apm-fe.xiaohongshu.com/api/data', 'fetch'], ['apm_data_xhr', 'https://apm-fe.xiaohongshu.com/api/data', 'xhr'], ]) check(matchPlatformRequest({ ...request, url, resourceType }), { policy_version: SEARCH_POLICY_VERSION, policy_rule: rule }); const enter = beginSearchRequestPolicy({ ...action, kind: 'press', key: 'Enter' }); check(matchPlatformRequest({ ...request, policy: enter }), { policy_version: SEARCH_POLICY_VERSION, policy_rule: 'search_notes' }); for (const changed of [ {sessionOrigin:'http://127.0.0.1'}, {sessionOrigin:'https://xiaohongshu.com'}, {pageUrl:'https://www.xiaohongshu.com.evil.test/explore'}, {pageUrl:'https://user:password@www.xiaohongshu.com/explore'}, {pageUrl:'http://www.xiaohongshu.com/explore'}, {pageUrl:'invalid'}, {kind:'click'}, {kind:'read'}, {kind:'extract'}, {kind:'wait'}, {kind:'scroll'}, {kind:'press',key:'Tab'}, {matchCount:0}, {matchCount:2}, {observed:{...observed,unique:false}}, {observed:{...observed,search_input:false}}, {observed:{...observed,sensitive:true}}, {observed:{...observed,tag:'button'}}, {observed:null}, {actual:{...actual,sensitive:true}}, {actual:{...actual,search_input:false}}, {actual:{...actual,visible:false}}, {actual:{...actual,in_viewport:false}}, {actual:{...actual,unobscured:false}}, {actual:null}, ]) check(beginSearchRequestPolicy({ ...action, ...changed })); for (const changed of [ {policy:null}, {policy:{version:SEARCH_POLICY_VERSION,expiresAt:Date.now()+15000}}, {automating:false}, {activeMainFrame:false}, {sessionOrigin:'https://xiaohongshu.com'}, {pageUrl:'https://example.com/'}, {pageUrl:'https://user:password@www.xiaohongshu.com/'}, {method:'GET'}, {method:'PUT'}, {method:'DELETE'}, {resourceType:'fetch'}, {resourceType:'document'}, {resourceType:'other'}, {url:'https://so.xiaohongshu.com.evil.test/api/sns/web/v2/search/notes'}, {url:'http://so.xiaohongshu.com/api/sns/web/v2/search/notes'}, {url:'https://user:password@so.xiaohongshu.com/api/sns/web/v2/search/notes'}, {url:'https://so.xiaohongshu.com:8443/api/sns/web/v2/search/notes'}, {url:'https://so.xiaohongshu.com/api/sns/web/v2/search/notes/'}, {url:'https://so.xiaohongshu.com/api/sns/web/v2/search/notes/delete'}, {url:'https://so.xiaohongshu.com/api/sns/web/v1/search/notes'}, {url:'https://edith.xiaohongshu.com/api/sns/web/v2/search/notes'}, {url:'https://so.xiaohongshu.com/api/sns/web/v2/comment/post'}, {url:'https://apm.xiaohongshu.com/api/data'}, {url:'invalid'}, {url:'https://apm-fe.xiaohongshu.com/api/data/',resourceType:'xhr'}, {url:'https://apm-fe.xiaohongshu.com.evil.test/api/data',resourceType:'xhr'}, {url:'https://apm-fe.xiaohongshu.com/api/data',resourceType:'xhr',method:'GET'}, {url:'https://edith.xiaohongshu.com/api/sns/web/v1/feed'}, ]) check(matchPlatformRequest({ ...request, ...changed })); const noteHref = `${official}/search_result/${'a'.repeat(24)}?xsec_token=FIXTURE-SECRET`; const noteObserved = { kind:'click', tag:'a', unique:true, sensitive:false }; const noteActual = { tag:'a', sensitive:false, visible:true, in_viewport:true, unobscured:true, href:noteHref }; const noteAction = { sessionOrigin:official, pageUrl:`${official}/search_result_ai?keyword=fixture`, kind:'click', observed:noteObserved, actual:noteActual, matchCount:1, href:noteHref }; const notePolicy = beginNoteOpenRequestPolicy(noteAction); assert.ok(notePolicy); assertions += 1; const noteRequest = { ...request, policy:notePolicy, url:'https://edith.xiaohongshu.com/api/sns/web/v1/feed' }; for (const [rule, url, resourceType = 'xhr'] of [ ['collect','https://t2.xiaohongshu.com/api/v2/collect'], ['note_share_code','https://edith.xiaohongshu.com/api/sns/web/share/code'], ['note_widgets','https://edith.xiaohongshu.com/api/sns/web/v2/widgets'], ['note_feed','https://edith.xiaohongshu.com/api/sns/web/v1/feed'], ['note_seo','https://edith.xiaohongshu.com/api/sns/web/worldcup/note/seo'], ['note_metrics','https://edith.xiaohongshu.com/api/sns/web/v1/note/metrics_report'], ['note_history_report','https://edith.xiaohongshu.com/api/sns/v1/history/report_web'], ['apm_data','https://apm-fe.xiaohongshu.com/api/data','fetch'], ]) check(matchPlatformRequest({ ...noteRequest, url, resourceType }), { policy_version:NOTE_POLICY_VERSION, policy_rule:rule }); const targetedCollectionPolicy = beginNoteOpenRequestPolicy({...noteAction,observed:{...noteObserved,unique:false},targetResolvedUnique:true}); check(matchPlatformRequest({...noteRequest,policy:targetedCollectionPolicy}), {policy_version:NOTE_POLICY_VERSION,policy_rule:'note_feed'}); check(beginNoteOpenRequestPolicy({...noteAction,observed:{...noteObserved,unique:false},targetResolvedUnique:true,matchCount:2})); check(matchPlatformRequest({...request,url:'https://edith.xiaohongshu.com/api/sns/v1/history/report_web'})); check(matchPlatformRequest({...noteRequest,url:'https://edith.xiaohongshu.com/api/sns/v1/history/report_web',resourceType:'fetch'})); const exploreHref = `${official}/explore/${'b'.repeat(24)}`; const explorePolicy = beginNoteOpenRequestPolicy({ ...noteAction, href:exploreHref, actual:{...noteActual,href:exploreHref} }); check(matchPlatformRequest({...noteRequest,policy:explorePolicy}), { policy_version:NOTE_POLICY_VERSION,policy_rule:'note_feed' }); for (const changed of [ {kind:'fill'}, {kind:'press'}, {kind:'read'}, {kind:'extract'}, {kind:'scroll'}, {kind:'wait'}, {sessionOrigin:'http://127.0.0.1'}, {pageUrl:'https://example.com/'}, {pageUrl:'https://user:pass@www.xiaohongshu.com/'}, {matchCount:0}, {matchCount:2}, {observed:{...noteObserved,unique:false}}, {observed:{...noteObserved,sensitive:true}}, {observed:{...noteObserved,tag:'button'}}, {observed:{...noteObserved,kind:'read'}}, {observed:null}, {actual:{...noteActual,tag:'button'}}, {actual:{...noteActual,sensitive:true}}, {actual:{...noteActual,visible:false}}, {actual:{...noteActual,in_viewport:false}}, {actual:{...noteActual,unobscured:false}}, {actual:{...noteActual,href:exploreHref}}, ]) check(beginNoteOpenRequestPolicy({...noteAction,...changed})); for (const href of [ `${official}/explore`, `${official}/explore/${'b'.repeat(23)}`, `${official}/explore/${'g'.repeat(24)}`, `${official}/Explore/${'b'.repeat(24)}`, `${official}/explore/${'b'.repeat(24)}/`, `${official}/explore/${'b'.repeat(24)}/delete`, `${official}/user/profile/${'b'.repeat(24)}`, `https://www.xiaohongshu.com.evil.test/explore/${'b'.repeat(24)}`, `https://user:pass@www.xiaohongshu.com/explore/${'b'.repeat(24)}`, `javascript:alert(1)`, ]) check(beginNoteOpenRequestPolicy({...noteAction,href,actual:{...noteActual,href}})); for (const changed of [ {automating:false}, {activeMainFrame:false}, {pageUrl:'https://example.com/'}, {sessionOrigin:'https://example.com'}, {method:'GET'}, {method:'DELETE'}, {resourceType:'fetch'}, {url:'https://edith.xiaohongshu.com/api/sns/web/v1/feed/delete'}, {url:'https://so.xiaohongshu.com/api/sns/web/v1/feed'}, {url:'https://edith.xiaohongshu.com.evil.test/api/sns/web/v1/feed'}, {url:'https://user:pass@edith.xiaohongshu.com/api/sns/web/v1/feed'}, {url:'https://so.xiaohongshu.com/api/sns/web/v2/search/notes'}, {url:'https://apm-fe.xiaohongshu.com/api/data',resourceType:'xhr'}, ]) check(matchPlatformRequest({...noteRequest,...changed})); const expired = beginSearchRequestPolicy({ ...action, now:Date.now()-16000 }); check(matchPlatformRequest({ ...request, policy:expired })); const expiredNote = beginNoteOpenRequestPolicy({...noteAction,now:Date.now()-16000}); check(matchPlatformRequest({...noteRequest,policy:expiredNote})); endPlatformRequestPolicy(policy); endPlatformRequestPolicy(enter); endPlatformRequestPolicy(notePolicy); endPlatformRequestPolicy(explorePolicy); endPlatformRequestPolicy(targetedCollectionPolicy); check(matchPlatformRequest(request)); check(matchPlatformRequest({ ...request, policy:enter })); check(matchPlatformRequest(noteRequest)); check(matchPlatformRequest({...noteRequest,policy:explorePolicy})); const readRoot = {tag:'div',readonly_root:true,sensitive:false,forbidden:false}; const readonlyAction = {sessionOrigin:official,pageUrl:`${official}/explore/${'a'.repeat(24)}`,kind:'scroll',selector:'#comments',selectorObserved:true,actualRoots:[readRoot]}; for (const kind of ['read','extract','scroll','wait']) { const cap = beginReadonlyRequestPolicy({...readonlyAction,kind}); const readRequest = {...request,policy:cap,url:'https://t2.xiaohongshu.com/api/v2/collect'}; check(matchPlatformRequest(readRequest),{policy_version:READONLY_POLICY_VERSION,policy_rule:'collect'}); check(matchPlatformRequest({...readRequest,url:'https://apm-fe.xiaohongshu.com/api/data',resourceType:'fetch'}),{policy_version:READONLY_POLICY_VERSION,policy_rule:'apm_data'}); for (const changed of [ {url:'https://so.xiaohongshu.com/api/sns/web/v2/search/notes'}, {url:'https://edith.xiaohongshu.com/api/sns/web/v1/feed'}, {url:'https://edith.xiaohongshu.com/api/sns/v1/history/report_web'}, {url:'https://so.xiaohongshu.com/api/sns/web/search/history/sync'}, {url:'https://t2.xiaohongshu.com/api/v2/collect/post'}, {method:'PUT'}, {resourceType:'fetch'}, {activeMainFrame:false}, {automating:false}, {pageUrl:'https://example.com/'}, {url:'https://apm-fe.xiaohongshu.com/api/data',resourceType:'xhr'}, ]) check(matchPlatformRequest({...readRequest,...changed})); endPlatformRequestPolicy(cap); check(matchPlatformRequest(readRequest)); } for (const changed of [ {kind:'click'}, {kind:'fill'}, {kind:'press'}, {selectorObserved:false}, {selector:''}, {selector:'body'}, {sessionOrigin:'http://127.0.0.1'}, {pageUrl:'https://example.com/'}, {pageUrl:'https://user:pass@www.xiaohongshu.com/'}, {actualRoots:[]}, {actualRoots:null}, {actualRoots:[{...readRoot,readonly_root:false}]}, {actualRoots:[{...readRoot,sensitive:true}]}, {actualRoots:[{...readRoot,forbidden:true}]}, ...['input','textarea','select','button','form','script','iframe','body'].map(tag=>({actualRoots:[{...readRoot,tag}]})), ]) check(beginReadonlyRequestPolicy({...readonlyAction,...changed})); for (const kind of ['scroll','wait']) { const cap = beginReadonlyRequestPolicy({...readonlyAction,kind,selector:'body',selectorObserved:false,actualRoots:[{...readRoot,tag:'body'}]}); check(matchPlatformRequest({...request,policy:cap,url:'https://t2.xiaohongshu.com/api/v2/collect'}),{policy_version:READONLY_POLICY_VERSION,policy_rule:'collect'}); endPlatformRequestPolicy(cap); } for (const kind of ['read','extract']) check(beginReadonlyRequestPolicy({...readonlyAction,kind,selector:'body',actualRoots:[{...readRoot,tag:'body'}]})); const expiredRead = beginReadonlyRequestPolicy({...readonlyAction,now:Date.now()-16000}); check(matchPlatformRequest({...request,policy:expiredRead,url:'https://t2.xiaohongshu.com/api/v2/collect'})); // A seek within a known search-results root receives only the pagination rule, // bound to the exact page and the finite action window. These tests make no // browser, API, model or network calls. check(SEARCH_SCROLL_POLICY_VERSION, 'xhs-search-scroll-experimental-v1'); const scrollNow = 10_000; const scrollPage = `${official}/search_result_ai?keyword=fixture&source=web`; const scrollObserved = {kind:'read',tag:'div',unique:true,sensitive:false}; const scrollRoot = {...readRoot,visible:true,in_viewport:true}; const untilTarget = {selector:'section.note-item a.title',field:'text',value:'准备开始装修了,主打一个听劝!'}; const scrollAction = {sessionOrigin:official,pageUrl:scrollPage,kind:'scroll',selector:'#search-results',selectorObserved:true, observed:scrollObserved,actualRoots:[scrollRoot],scrollScope:'viewport',untilTarget,now:scrollNow}; const scrollPolicy = beginReadonlyRequestPolicy(scrollAction); check(scrollPolicy, {version:SEARCH_SCROLL_POLICY_VERSION,scope:'search_scroll',expiresAt:25_000}); check(Object.isFrozen(scrollPolicy), true); check(Object.keys(scrollPolicy).sort(), ['expiresAt','scope','version']); const scrollRequest = {policy:scrollPolicy,automating:true,sessionOrigin:official,pageUrl:scrollPage,activeMainFrame:true, method:'POST',resourceType:'xhr',url:'https://so.xiaohongshu.com/api/sns/web/v2/search/notes',now:scrollNow}; for (const [pagePath,tag] of [['/search_result','section'],['/search_result_ai','div']]) { const pageUrl = `${official}${pagePath}?keyword=fixture&source=web`; const cap = beginReadonlyRequestPolicy({...scrollAction,pageUrl,observed:{...scrollObserved,tag},actualRoots:[{...scrollRoot,tag}]}); check(cap?.scope, 'search_scroll'); for (const [rule,url,resourceType] of [ ['collect','https://t2.xiaohongshu.com/api/v2/collect','xhr'], ['apm_data','https://apm-fe.xiaohongshu.com/api/data','fetch'], ['search_notes','https://so.xiaohongshu.com/api/sns/web/v2/search/notes','xhr'], ]) check(matchPlatformRequest({...scrollRequest,policy:cap,pageUrl,url,resourceType}), {policy_version:SEARCH_SCROLL_POLICY_VERSION,policy_rule:rule}); endPlatformRequestPolicy(cap); check(matchPlatformRequest({...scrollRequest,policy:cap,pageUrl})); } const boundedTextPolicy = beginReadonlyRequestPolicy({...scrollAction,untilTarget:{...untilTarget,value:'文'.repeat(2000)}}); check(boundedTextPolicy?.scope, 'search_scroll'); endPlatformRequestPolicy(boundedTextPolicy); // Invalid new-scope intent can legitimately retain the old readonly UI policy. // The invariant is that it cannot authorize search pagination. function noSearchScroll(changed, {fallback = false} = {}) { const cap = beginReadonlyRequestPolicy({...scrollAction,...changed}); check(cap?.scope === 'search_scroll', false); check(matchPlatformRequest({...scrollRequest,policy:cap})); if (fallback) { check(cap?.scope, 'readonly_ui'); check(matchPlatformRequest({...scrollRequest,policy:cap,url:'https://t2.xiaohongshu.com/api/v2/collect'}), {policy_version:READONLY_POLICY_VERSION,policy_rule:'collect'}); } endPlatformRequestPolicy(cap); } for (const changed of [ ...['read','extract','wait'].map(kind=>({kind})), {scrollScope:undefined}, {scrollScope:'container'}, {scrollScope:'Viewport'}, {observed:undefined}, {observed:null}, {observed:{...scrollObserved,kind:'scroll'}}, {observed:{...scrollObserved,kind:'click'}}, {observed:{...scrollObserved,unique:false}}, {observed:{...scrollObserved,unique:undefined}}, {observed:{...scrollObserved,sensitive:true}}, {observed:{...scrollObserved,sensitive:undefined}}, {observed:{...scrollObserved,tag:undefined}}, {observed:{...scrollObserved,tag:''}}, {observed:{...scrollObserved,tag:'DIV'}}, {observed:{...scrollObserved,tag:'section'}}, {actualRoots:[{...scrollRoot,visible:false}]}, {actualRoots:[{...scrollRoot,visible:undefined}]}, {actualRoots:[{...scrollRoot,in_viewport:false}]}, {actualRoots:[{...scrollRoot,in_viewport:undefined}]}, {actualRoots:[scrollRoot,{...scrollRoot}]}, {actualRoots:[{...scrollRoot,tag:'section'}]}, {observed:{...scrollObserved,tag:'a'},actualRoots:[{...scrollRoot,tag:'a'}]}, {untilTarget:undefined}, {untilTarget:null}, {untilTarget:[]}, {untilTarget:'title'}, {untilTarget:{...untilTarget,field:'href'}}, {untilTarget:{...untilTarget,field:'attribute'}}, {untilTarget:{...untilTarget,field:undefined}}, {untilTarget:{...untilTarget,value:''}}, {untilTarget:{...untilTarget,value:' \n\t '}}, {untilTarget:{...untilTarget,value:undefined}}, {untilTarget:{...untilTarget,value:42}}, {untilTarget:{...untilTarget,value:'文'.repeat(2001)}}, {untilTarget:{selector:untilTarget.selector,field:'text',parameter:'note_title'}}, {untilTarget:{...untilTarget,parameter:'note_title'}}, {untilTarget:{...untilTarget,attribute:'title'}}, {untilTarget:{...untilTarget,unexpected:true}}, ...['','body','html',':root','body .note','html > section','section, body','xpath=//a','text=title', 'role=link','section >> a','a:has-text("title")','javascript:alert(1)'].map(selector=>({untilTarget:{...untilTarget,selector}})), ...['html',':root','body .note','section, body','xpath=//section','text=results','css=#results', '#results >> section','section:has-text("results")','javascript:alert(1)'].map(selector=>({selector})), ...['/explore','/explore/'+ 'a'.repeat(24),'/search_result/','/search_result_ai/', '/search_result/'+ 'a'.repeat(24),'/search_result_ai/more','/Search_result','/user/profile', '/search_result_other'].map(path=>({pageUrl:`${official}${path}?keyword=fixture`})), ]) noSearchScroll(changed, {fallback:true}); for (const changed of [ ...['click','fill','press'].map(kind=>({kind})), {sessionOrigin:'http://127.0.0.1'}, {sessionOrigin:'https://xiaohongshu.com'}, {sessionOrigin:'https://www.xiaohongshu.com.evil.test'}, {pageUrl:'http://www.xiaohongshu.com/search_result?keyword=fixture'}, {pageUrl:'https://www.xiaohongshu.com.evil.test/search_result?keyword=fixture'}, {pageUrl:'https://user:password@www.xiaohongshu.com/search_result?keyword=fixture'}, {pageUrl:'https://www.xiaohongshu.com:8443/search_result?keyword=fixture'}, {pageUrl:'invalid'}, {selectorObserved:false}, {selectorObserved:undefined}, {selector:''}, {selector:null}, {selector:'x'.repeat(1001)}, {actualRoots:[]}, {actualRoots:null}, {actualRoots:[null]}, {actualRoots:[{...scrollRoot,readonly_root:false}]}, {actualRoots:[{...scrollRoot,sensitive:true}]}, {actualRoots:[{...scrollRoot,forbidden:true}]}, ...['input','textarea','select','button','form','script','style','noscript','iframe','body','html'].map(tag=> ({observed:{...scrollObserved,tag},actualRoots:[{...scrollRoot,tag}]})), {selector:'body',selectorObserved:false,observed:{...scrollObserved,tag:'body'},actualRoots:[{...scrollRoot,tag:'body'}]}, {now:NaN}, {now:Infinity}, ]) noSearchScroll(changed); for (const changed of [ {policy:null}, {policy:{}}, {policy:{...scrollPolicy}}, {policy:Object.freeze({version:SEARCH_SCROLL_POLICY_VERSION,scope:'search_scroll',expiresAt:25_000,pageUrl:scrollPage,startsAt:scrollNow})}, {automating:false}, {automating:undefined}, {activeMainFrame:false}, {activeMainFrame:undefined}, {sessionOrigin:'https://xiaohongshu.com'}, {sessionOrigin:'https://www.xiaohongshu.com.evil.test'}, {pageUrl:`${official}/search_result?keyword=fixture&source=web`}, {pageUrl:`${official}/search_result_ai?keyword=other&source=web`}, {pageUrl:`${official}/search_result_ai?source=web&keyword=fixture`}, {pageUrl:`${scrollPage}#results`}, {pageUrl:`${scrollPage}&page=2`}, {pageUrl:`${official}/explore?keyword=fixture&source=web`}, {pageUrl:'https://www.xiaohongshu.com.evil.test/search_result_ai?keyword=fixture&source=web'}, {pageUrl:'https://user:password@www.xiaohongshu.com/search_result_ai?keyword=fixture&source=web'}, {pageUrl:'http://www.xiaohongshu.com/search_result_ai?keyword=fixture&source=web'}, {pageUrl:'https://www.xiaohongshu.com:8443/search_result_ai?keyword=fixture&source=web'}, {method:'GET'}, {method:'PUT'}, {method:'DELETE'}, {method:'PATCH'}, {method:'post'}, {resourceType:'fetch'}, {resourceType:'document'}, {resourceType:'other'}, {url:'https://so.xiaohongshu.com/api/sns/web/v2/search/notes/'}, {url:'https://so.xiaohongshu.com/api/sns/web/v2/search/notes/delete'}, {url:'https://so.xiaohongshu.com/api/sns/web/v1/search/notes'}, {url:'https://edith.xiaohongshu.com/api/sns/web/v2/search/notes'}, {url:'https://so.xiaohongshu.com.evil.test/api/sns/web/v2/search/notes'}, {url:'https://user:password@so.xiaohongshu.com/api/sns/web/v2/search/notes'}, {url:'http://so.xiaohongshu.com/api/sns/web/v2/search/notes'}, {url:'https://so.xiaohongshu.com:8443/api/sns/web/v2/search/notes'}, {url:'https://so.xiaohongshu.com/api/sns/web/search/history/sync'}, {url:'https://edith.xiaohongshu.com/api/sns/web/v1/search/onebox'}, {url:'https://so.xiaohongshu.com/api/sns/web/v1/dqa/instant'}, {url:'https://edith.xiaohongshu.com/api/sns/web/v1/feed'}, {url:'https://edith.xiaohongshu.com/api/sns/v1/history/report_web'}, {url:'https://t2.xiaohongshu.com/api/v2/collect/post'}, {url:'https://apm-fe.xiaohongshu.com/api/data',resourceType:'xhr'}, {url:'https://so.xiaohongshu.com/api/sns/web/v2/comment/post'}, {url:'https://edith.xiaohongshu.com/api/sns/web/v1/user/follow'}, {url:'https://edith.xiaohongshu.com/api/sns/web/v1/im/message/send'}, {url:'https://so.xiaohongshu.com/api/sns/web/v2/unknown'}, {url:'https://so.xiaohongshu.com/api/security/verify'}, {url:'javascript:alert(1)'}, {url:'invalid'}, {now:scrollNow-1}, {now:25_000}, {now:25_001}, {now:NaN}, {now:Infinity}, ]) check(matchPlatformRequest({...scrollRequest,...changed})); for (const now of [scrollNow,24_999]) check(matchPlatformRequest({...scrollRequest,now}), {policy_version:SEARCH_SCROLL_POLICY_VERSION,policy_rule:'search_notes'}); // Mutating the caller's action after creation cannot move the internal page pin. const mutableAction = {...scrollAction}; const pinnedPolicy = beginReadonlyRequestPolicy(mutableAction); mutableAction.pageUrl = `${official}/search_result_ai?keyword=changed`; check(matchPlatformRequest({...scrollRequest,policy:pinnedPolicy,pageUrl:mutableAction.pageUrl})); check(matchPlatformRequest({...scrollRequest,policy:pinnedPolicy}), {policy_version:SEARCH_SCROLL_POLICY_VERSION,policy_rule:'search_notes'}); endPlatformRequestPolicy(pinnedPolicy); check(matchPlatformRequest({...scrollRequest,policy:pinnedPolicy})); endPlatformRequestPolicy(scrollPolicy); check(matchPlatformRequest(scrollRequest)); console.log(JSON.stringify({ result:'passed', assertions, search_rules:7, note_rules:8, readonly_rules:2, search_scroll_rules:3, scoped_page_binding:true, live_requests:0, localhost_exception:false, expiry_and_revocation:true }));