@@ -11,6 +11,8 @@ import {
1111import { takeAndAttachScreenshot } from "../utils/screenshotUtils" ;
1212import { BasePage } from "./base-page" ;
1313import { Edit } from "../utils/types/json-edit.types" ;
14+ import { SpecEditorPage } from "./spec-editor-page" ;
15+
1416
1517export class ExampleGenerationPage extends BasePage {
1618 readonly openApiTabPage : OpenAPISpecTabPage ;
@@ -30,6 +32,8 @@ export class ExampleGenerationPage extends BasePage {
3032 private readonly specSection : Locator ;
3133 private readonly specEditorSection : Locator ;
3234 private readonly specTabLocator : Locator ;
35+ private readonly specEditorHelper : SpecEditorPage ;
36+
3337
3438 constructor ( page : Page , testInfo : TestInfo , eyes : any , specName : string ) {
3539 super ( page , testInfo , eyes , specName ) ;
@@ -62,8 +66,10 @@ export class ExampleGenerationPage extends BasePage {
6266 this . bulkValidateBtnSelector = "button#bulk-validate" ;
6367 this . inlineBtnSelector = "button#import" ;
6468 this . bulkFixBtnSelector = "button#bulk-fix" ;
69+ this . specEditorHelper = new SpecEditorPage ( page ) ;
6570 }
6671
72+
6773 private async openExampleGenerationTab ( ) {
6874 console . log ( "Opening Example Generation tab" ) ;
6975 return this . openApiTabPage . openExampleGenerationTab ( ) ;
@@ -1134,7 +1140,7 @@ export class ExampleGenerationPage extends BasePage {
11341140 await expect ( editorContext . content ) . toBeVisible ( { timeout : 15000 } ) ;
11351141 await editorContext . content . click ( ) ;
11361142
1137- await this . loadFullEditorDocument ( editorContext . scroller ) ;
1143+ await this . specEditorHelper . loadFullEditorDocument ( editorContext . scroller ) ;
11381144 await editorContext . scroller . evaluate ( ( el ) => {
11391145 el . scrollTop = 0 ;
11401146 } ) ;
@@ -1145,7 +1151,7 @@ export class ExampleGenerationPage extends BasePage {
11451151 : [ `${ exampleName } _response` ] ;
11461152
11471153 for ( const searchTerm of targets ) {
1148- const foundByEditorApi = await this . focusTermUsingCodeMirrorApi (
1154+ const foundByEditorApi = await this . specEditorHelper . focusTermUsingCodeMirrorApi (
11491155 editorContext . content ,
11501156 searchTerm ,
11511157 ) ;
@@ -1157,12 +1163,18 @@ export class ExampleGenerationPage extends BasePage {
11571163 ) ;
11581164
11591165 if ( ! foundByWindowFind ) {
1160- await this . scrollToEditorSearchTerm (
1166+ await this . specEditorHelper . scrollEditorToFindTerm (
11611167 editorContext . content ,
11621168 editorContext . scroller ,
11631169 editorContext . lines ,
11641170 searchTerm ,
11651171 ) ;
1172+ // Click the matched line for visual cursor placement
1173+ const match = editorContext . lines . filter ( { hasText : searchTerm } ) . first ( ) ;
1174+ if ( ( await match . count ( ) ) > 0 ) {
1175+ await match . scrollIntoViewIfNeeded ( ) ;
1176+ await match . click ( ) ;
1177+ }
11661178 }
11671179
11681180 await this . page . waitForTimeout ( 250 ) ;
@@ -1238,113 +1250,4 @@ export class ExampleGenerationPage extends BasePage {
12381250 return win . find ( term , false , false , true , false , false , false ) ;
12391251 } , searchTerm ) ;
12401252 }
1241-
1242- private async focusTermUsingCodeMirrorApi (
1243- content : Locator ,
1244- searchTerm : string ,
1245- ) : Promise < boolean > {
1246- return await content . evaluate ( ( el , term ) => {
1247- const cmEditor = el . closest ( ".cm-editor" ) as any ;
1248- const view = cmEditor ?. cmView ?. view ;
1249- if ( ! view ) return false ;
1250-
1251- const fullText = view . state . doc . toString ( ) as string ;
1252- const index = fullText . indexOf ( term ) ;
1253- if ( index === - 1 ) return false ;
1254-
1255- view . dispatch ( {
1256- selection : { anchor : index , head : index + term . length } ,
1257- scrollIntoView : true ,
1258- } ) ;
1259- return true ;
1260- } , searchTerm ) ;
1261- }
1262-
1263- private async loadFullEditorDocument ( scroller : Locator ) : Promise < void > {
1264- await expect ( scroller ) . toBeVisible ( { timeout : 10000 } ) ;
1265-
1266- let unchangedCount = 0 ;
1267- let previousScrollHeight = - 1 ;
1268-
1269- for ( let i = 0 ; i < 60 ; i ++ ) {
1270- const metrics = await scroller . evaluate ( ( el ) => {
1271- el . scrollTop = el . scrollHeight ;
1272- return {
1273- scrollTop : el . scrollTop ,
1274- scrollHeight : el . scrollHeight ,
1275- clientHeight : el . clientHeight ,
1276- } ;
1277- } ) ;
1278-
1279- if ( metrics . scrollHeight === previousScrollHeight ) {
1280- unchangedCount += 1 ;
1281- } else {
1282- unchangedCount = 0 ;
1283- }
1284-
1285- previousScrollHeight = metrics . scrollHeight ;
1286-
1287- const atBottom =
1288- metrics . scrollTop + metrics . clientHeight >= metrics . scrollHeight - 2 ;
1289- if ( atBottom && unchangedCount >= 2 ) {
1290- break ;
1291- }
1292-
1293- await this . page . waitForTimeout ( 120 ) ;
1294- }
1295- }
1296-
1297- private async scrollToEditorSearchTerm (
1298- content : Locator ,
1299- scroller : Locator ,
1300- lines : Locator ,
1301- searchTerm : string ,
1302- ) : Promise < void > {
1303- await scroller . evaluate ( ( el ) => {
1304- el . scrollTop = 0 ;
1305- } ) ;
1306- await this . page . waitForTimeout ( 120 ) ;
1307-
1308- for ( let i = 0 ; i < 250 ; i ++ ) {
1309- const match = lines . filter ( { hasText : searchTerm } ) . first ( ) ;
1310- const count = await match . count ( ) ;
1311-
1312- if ( count > 0 ) {
1313- await match . scrollIntoViewIfNeeded ( ) ;
1314- await match . click ( ) ;
1315- return ;
1316- }
1317-
1318- const moved = await scroller . evaluate ( ( el ) => {
1319- const prev = el . scrollTop ;
1320- el . scrollTop = Math . min (
1321- el . scrollTop + Math . max ( el . clientHeight * 0.85 , 120 ) ,
1322- el . scrollHeight ,
1323- ) ;
1324- return el . scrollTop > prev ;
1325- } ) ;
1326-
1327- if ( ! moved ) {
1328- break ;
1329- }
1330-
1331- await this . page . waitForTimeout ( 80 ) ;
1332- }
1333-
1334- // Fallback: some editor layouts scroll via outer containers, not .cm-scroller.
1335- await content . hover ( ) ;
1336- for ( let i = 0 ; i < 280 ; i ++ ) {
1337- const visible = await lines . evaluateAll (
1338- ( els , term ) => els . some ( ( el ) => el . textContent ?. includes ( term ) ) ,
1339- searchTerm ,
1340- ) ;
1341- if ( visible ) {
1342- return ;
1343- }
1344- await this . page . mouse . wheel ( 0 , 900 ) ;
1345- await this . page . waitForTimeout ( 60 ) ;
1346- }
1347-
1348- throw new Error ( `Could not find '${ searchTerm } ' in the spec editor` ) ;
1349- }
13501253}
0 commit comments