@@ -16,6 +16,19 @@ const FIXTURES_DIR = join(__dirname, '../../fixtures');
1616const REPORT_NAME =
1717 process . env . MIDSCENE_WEBP_REPORT_NAME || 'webp-model-input-validation' ;
1818
19+ interface ChatCompletionRequest {
20+ messages ?: Array < {
21+ content ?:
22+ | string
23+ | Array < {
24+ type ?: string ;
25+ image_url ?: {
26+ url ?: string ;
27+ } ;
28+ } > ;
29+ } > ;
30+ }
31+
1932vi . setConfig ( {
2033 testTimeout : 180 * 1000 ,
2134} ) ;
@@ -37,15 +50,75 @@ describe('WebP model input report', () => {
3750 { viewport : { width : 1120 , height : 700 } } ,
3851 ) ;
3952 reset = launched . reset ;
53+ const modelInputUrls : string [ ] = [ ] ;
54+ const createCompletion = vi . fn ( async ( request : unknown ) => {
55+ const { messages = [ ] } = request as ChatCompletionRequest ;
56+ for ( const message of messages ) {
57+ if ( ! Array . isArray ( message . content ) ) {
58+ continue ;
59+ }
60+ for ( const part of message . content ) {
61+ if (
62+ part . type === 'image_url' &&
63+ typeof part . image_url ?. url === 'string'
64+ ) {
65+ modelInputUrls . push ( part . image_url . url ) ;
66+ }
67+ }
68+ }
69+
70+ return {
71+ id : 'webp-report-test-completion' ,
72+ object : 'chat.completion' ,
73+ created : 0 ,
74+ model : 'webp-report-test-model' ,
75+ choices : [
76+ {
77+ index : 0 ,
78+ finish_reason : 'stop' ,
79+ message : {
80+ role : 'assistant' ,
81+ content :
82+ '<observation>The search controls are visible.</observation><data-json>{"StatementIsTruthy":true}</data-json>' ,
83+ } ,
84+ } ,
85+ ] ,
86+ usage : {
87+ prompt_tokens : 100 ,
88+ completion_tokens : 10 ,
89+ total_tokens : 110 ,
90+ } ,
91+ } ;
92+ } ) ;
4093 agent = new PuppeteerAgent ( launched . originPage , {
4194 generateReport : true ,
4295 reportFileName : REPORT_NAME ,
96+ modelConfig : {
97+ MIDSCENE_MODEL_NAME : 'webp-report-test-model' ,
98+ MIDSCENE_MODEL_API_KEY : 'webp-report-test-key' ,
99+ MIDSCENE_MODEL_BASE_URL : 'https://example.test/v1' ,
100+ MIDSCENE_MODEL_FAMILY : 'qwen3-vl' ,
101+ } ,
102+ createOpenAIClient : async ( ) => ( {
103+ chat : {
104+ completions : {
105+ create : createCompletion ,
106+ } ,
107+ } ,
108+ } ) ,
43109 } ) ;
44110
45111 const captured = await agent . interface . screenshotBase64 ( ) ;
46112 expect ( captured ) . toMatch ( / ^ d a t a : i m a g e \/ w e b p ; b a s e 6 4 , U k l G R / ) ;
47113
48114 await agent . aiAssert ( 'A search input box and a search button are visible' ) ;
115+ expect ( createCompletion ) . toHaveBeenCalledTimes ( 1 ) ;
116+ expect ( modelInputUrls ) . toHaveLength ( 1 ) ;
117+ expect ( modelInputUrls [ 0 ] ) . toMatch ( / ^ d a t a : i m a g e \/ w e b p ; b a s e 6 4 , U k l G R / ) ;
118+ const modelInputHash = createHash ( 'sha256' )
119+ . update ( Buffer . from ( modelInputUrls [ 0 ] . split ( ',' ) [ 1 ] , 'base64' ) )
120+ . digest ( 'hex' ) ;
121+
49122 await agent . destroy ( ) ;
50123 const reportFile = agent . reportFile ;
51124 agent = undefined ;
@@ -62,12 +135,6 @@ describe('WebP model input report', () => {
62135 const markdown = readFileSync ( markdownResult . markdownFiles [ 0 ] , 'utf8' ) ;
63136 expect ( markdown ) . not . toContain ( 'No model metadata recorded.' ) ;
64137 expect ( markdown ) . not . toContain ( 'No token usage recorded.' ) ;
65- expect ( markdown ) . toContain ( 'timing=model-input' ) ;
66-
67- const modelInputHash = markdown . match (
68- / M o d e l i n p u t \d + \( e x a c t b y t e s , s h a 2 5 6 : ( [ a - f 0 - 9 ] { 64 } ) \) / ,
69- ) ?. [ 1 ] ;
70- expect ( modelInputHash ) . toBeTruthy ( ) ;
71138 expect ( markdownResult . screenshotFiles . length ) . toBeGreaterThan ( 0 ) ;
72139 expect (
73140 markdownResult . screenshotFiles . every ( ( file ) => file . endsWith ( '.webp' ) ) ,
0 commit comments