1- import { AnyBrowserAction } from '@/main/runner/schema'
21import {
32 Assertion ,
43 BrowserEvent ,
54 BrowserEventTarget ,
65} from '@/schemas/recording'
76import { exhaustive } from '@/utils/typescript'
7+ import {
8+ BrowserActionInstance ,
9+ LocatorOptions ,
10+ } from '@/views/BrowserTestEditor/types'
811
9- import { isSelectorEqual , getNodeSelector } from './selectors'
12+ import { isSelectorEqual , getNodeSelector , toNodeSelector } from './selectors'
1013import {
1114 TestNode ,
1215 PageNode ,
@@ -287,8 +290,11 @@ function buildBrowserNodeGraphFromEvents(events: BrowserEvent[]) {
287290 return nodes
288291}
289292
290- function buildBrowserNodeGraphFromActions ( browserActions : AnyBrowserAction [ ] ) {
293+ function buildBrowserNodeGraphFromActions (
294+ browserActions : BrowserActionInstance [ ]
295+ ) {
291296 const nodes : TestNode [ ] = [ ]
297+ let previousLocatorNode : LocatorNode | null = null
292298
293299 let currentPage : PageNode | undefined = undefined
294300
@@ -307,7 +313,46 @@ function buildBrowserNodeGraphFromActions(browserActions: AnyBrowserAction[]) {
307313 return toNodeRef ( currentPage )
308314 }
309315
310- function toNode ( action : AnyBrowserAction ) : TestNode {
316+ function getLocator ( { current, values } : LocatorOptions ) : NodeRef {
317+ const currentLocator = values [ current ]
318+ if ( ! currentLocator ) {
319+ throw new Error (
320+ `Current locator of type "${ current } " not found in locator values.`
321+ )
322+ }
323+
324+ // Group sequential locators together, so that we reuse the same locator
325+ // multiple actions have occurred on the same element, e.g:
326+ // ```
327+ // const input = page.locator("input")
328+ //
329+ // await input.focus()
330+ // await input.type("Hello")
331+ // await input.press("Enter")
332+
333+ const selector = toNodeSelector ( currentLocator )
334+
335+ if (
336+ previousLocatorNode === null ||
337+ ! isSelectorEqual ( selector , previousLocatorNode . selector ) ||
338+ previousLocatorNode . inputs . page . nodeId !== getPage ( ) . nodeId
339+ ) {
340+ previousLocatorNode = {
341+ type : 'locator' ,
342+ nodeId : crypto . randomUUID ( ) ,
343+ selector,
344+ inputs : {
345+ page : getPage ( ) ,
346+ } ,
347+ }
348+
349+ nodes . push ( previousLocatorNode )
350+ }
351+
352+ return toNodeRef ( previousLocatorNode )
353+ }
354+
355+ function toNode ( action : BrowserActionInstance ) : TestNode {
311356 switch ( action . method ) {
312357 case 'page.goto' :
313358 return {
@@ -320,6 +365,22 @@ function buildBrowserNodeGraphFromActions(browserActions: AnyBrowserAction[]) {
320365 } ,
321366 }
322367 case 'page.reload' :
368+ return {
369+ type : 'reload' ,
370+ nodeId : crypto . randomUUID ( ) ,
371+ inputs : {
372+ page : getPage ( ) ,
373+ } ,
374+ }
375+ case 'locator.waitFor' :
376+ return {
377+ type : 'wait-for' ,
378+ nodeId : crypto . randomUUID ( ) ,
379+ inputs : {
380+ locator : getLocator ( action . locator ) ,
381+ } ,
382+ options : action . options ,
383+ }
323384 case 'page.waitForNavigation' :
324385 case 'page.close' :
325386 case 'page.*' :
@@ -330,7 +391,6 @@ function buildBrowserNodeGraphFromActions(browserActions: AnyBrowserAction[]) {
330391 case 'locator.check' :
331392 case 'locator.uncheck' :
332393 case 'locator.selectOption' :
333- case 'locator.waitFor' :
334394 case 'locator.hover' :
335395 case 'locator.setChecked' :
336396 case 'locator.tap' :
@@ -366,7 +426,7 @@ export function convertEventsToTest({ browserEvents }: Recording): Test {
366426export function convertActionsToTest ( {
367427 browserActions,
368428} : {
369- browserActions : AnyBrowserAction [ ]
429+ browserActions : BrowserActionInstance [ ]
370430} ) : Test {
371431 return {
372432 defaultScenario : {
0 commit comments