@@ -22,6 +22,48 @@ import {
2222import { createInternalTransaction } from '../page-objects/flows/transaction' ;
2323import { Driver } from '../webdriver/driver' ;
2424
25+ /**
26+ * Core Web Vitals metrics from the web-vitals library.
27+ * INP (Interaction to Next Paint) requires actual user interactions to measure.
28+ */
29+ type WebVitalsMetrics = {
30+ inp : number | null ;
31+ lcp : number | null ;
32+ cls : number | null ;
33+ inpRating : 'good' | 'needs-improvement' | 'poor' | null ;
34+ lcpRating : 'good' | 'needs-improvement' | 'poor' | null ;
35+ clsRating : 'good' | 'needs-improvement' | 'poor' | null ;
36+ } ;
37+
38+ /**
39+ * Collect Core Web Vitals from stateHooks.
40+ * Must be called after user interactions for INP to have meaningful data.
41+ */
42+ async function collectWebVitals ( driver : Driver ) : Promise < WebVitalsMetrics > {
43+ return await driver . executeScript ( ( ) => {
44+ const stateHooks = (
45+ window as Window & {
46+ stateHooks ?: {
47+ getWebVitalsMetrics ?: ( ) => WebVitalsMetrics ;
48+ } ;
49+ }
50+ ) . stateHooks ;
51+
52+ if ( stateHooks ?. getWebVitalsMetrics ) {
53+ return stateHooks . getWebVitalsMetrics ( ) ;
54+ }
55+
56+ return {
57+ inp : null ,
58+ lcp : null ,
59+ cls : null ,
60+ inpRating : null ,
61+ lcpRating : null ,
62+ clsRating : null ,
63+ } ;
64+ } ) ;
65+ }
66+
2567async function mockTokensEthereum ( mockServer : Mockttp ) {
2668 return await mockServer . forPost ( / g e t T o k e n s \/ s e a r c h / u) . thenCallback ( ( ) => {
2769 return {
@@ -47,8 +89,17 @@ async function loadNewAccount(): Promise<{
4789 duration : number ;
4890 testTitle : string ;
4991 persona : string ;
92+ webVitals : WebVitalsMetrics ;
5093} > {
5194 let loadingTimes : number = 0 ;
95+ let webVitals : WebVitalsMetrics = {
96+ inp : null ,
97+ lcp : null ,
98+ cls : null ,
99+ inpRating : null ,
100+ lcpRating : null ,
101+ clsRating : null ,
102+ } ;
52103 const testTitle = 'benchmark-userActions-loadNewAccount' ;
53104
54105 await withFixtures (
@@ -73,17 +124,34 @@ async function loadNewAccount(): Promise<{
73124 const timestampAfterAction = new Date ( ) ;
74125 loadingTimes =
75126 timestampAfterAction . getTime ( ) - timestampBeforeAction . getTime ( ) ;
127+
128+ // Collect Core Web Vitals after user interactions
129+ webVitals = await collectWebVitals ( driver ) ;
76130 } ,
77131 ) ;
78- return { duration : loadingTimes , testTitle, persona : USER_ACTIONS_PERSONA } ;
132+ return {
133+ duration : loadingTimes ,
134+ testTitle,
135+ persona : USER_ACTIONS_PERSONA ,
136+ webVitals,
137+ } ;
79138}
80139
81140async function confirmTx ( ) : Promise < {
82141 duration : number ;
83142 testTitle : string ;
84143 persona : string ;
144+ webVitals : WebVitalsMetrics ;
85145} > {
86146 let loadingTimes : number = 0 ;
147+ let webVitals : WebVitalsMetrics = {
148+ inp : null ,
149+ lcp : null ,
150+ cls : null ,
151+ inpRating : null ,
152+ lcpRating : null ,
153+ clsRating : null ,
154+ } ;
87155 const testTitle = 'benchmark-userActions-confirmTx' ;
88156
89157 await withFixtures (
@@ -119,9 +187,17 @@ async function confirmTx(): Promise<{
119187 const timestampAfterAction = new Date ( ) ;
120188 loadingTimes =
121189 timestampAfterAction . getTime ( ) - timestampBeforeAction . getTime ( ) ;
190+
191+ // Collect Core Web Vitals after user interactions
192+ webVitals = await collectWebVitals ( driver ) ;
122193 } ,
123194 ) ;
124- return { duration : loadingTimes , testTitle, persona : USER_ACTIONS_PERSONA } ;
195+ return {
196+ duration : loadingTimes ,
197+ testTitle,
198+ persona : USER_ACTIONS_PERSONA ,
199+ webVitals,
200+ } ;
125201}
126202
127203async function bridgeUserActions ( ) : Promise < {
@@ -130,10 +206,19 @@ async function bridgeUserActions(): Promise<{
130206 searchToken : number ;
131207 testTitle : string ;
132208 persona : string ;
209+ webVitals : WebVitalsMetrics ;
133210} > {
134211 let loadPage : number = 0 ;
135212 let loadAssetPicker : number = 0 ;
136213 let searchToken : number = 0 ;
214+ let webVitals : WebVitalsMetrics = {
215+ inp : null ,
216+ lcp : null ,
217+ cls : null ,
218+ inpRating : null ,
219+ lcpRating : null ,
220+ clsRating : null ,
221+ } ;
137222 const testTitle = 'benchmark-userActions-bridgeUserActions' ;
138223
139224 const fixtureBuilder = new FixtureBuilder ( )
@@ -184,6 +269,9 @@ async function bridgeUserActions(): Promise<{
184269 searchToken =
185270 timestampAferTokenSearch . getTime ( ) -
186271 timestampBeforeTokenSearch . getTime ( ) ;
272+
273+ // Collect Core Web Vitals after user interactions
274+ webVitals = await collectWebVitals ( driver ) ;
187275 } ,
188276 ) ;
189277 return {
@@ -192,6 +280,7 @@ async function bridgeUserActions(): Promise<{
192280 searchToken,
193281 testTitle,
194282 persona : USER_ACTIONS_PERSONA ,
283+ webVitals,
195284 } ;
196285}
197286
@@ -208,7 +297,10 @@ async function main(): Promise<void> {
208297 } ) ,
209298 ) ;
210299
211- const results : Record < string , Record < string , string | number > > = { } ;
300+ const results : Record <
301+ string ,
302+ Record < string , string | number | WebVitalsMetrics | null >
303+ > = { } ;
212304
213305 results . loadNewAccount = await loadNewAccount ( ) ;
214306 results . confirmTx = await confirmTx ( ) ;
0 commit comments