๐Ÿ”ท Core

bx-playwright-network

Use this skill when working with the network in bx-playwright: mocking and blocking requests with page.intercept() (respondJson, respond, abort, resume, handle), listening to console, requests, responses, page errors and dialogs, HTTP API testing with playwright().request(), cookies and permissions, and saving/reusing logged-in sessions with playwright().session().

$ npx skills add ortus-boxlang/skills/boxlang-modules/bx-playwright/bx-playwright-network
$ coldbox ai skills install ortus-boxlang/skills/boxlang-modules/bx-playwright/bx-playwright-network
๐Ÿ”— https://skills.boxlang.io/skills/raw/ortus-boxlang/skills/boxlang-modules~bx-playwright~bx-playwright-network

bx-playwright: Network, APIs and Sessions

BoxLang is the AI-native software productivity platform for building, modernizing and running applications, with developers and AI agents working together.

Mock, Block, Modify

page.intercept( "**/api/users" ).respondJson( [ "Luis", "Brad" ] )          // status 200
page.intercept( "**/api/users" ).respondJson( { error : "no" }, 500 )
page.intercept( "**/api/fail" ).respond( 500, "Boom", { "content-type" : "text/plain" } )
page.intercept( "**/*.{png,jpg}" ).abort()
page.intercept( "**/api/**" ).resume( { headers : { "X-Test" : "1" } } )
page.intercept( "**/api/**" ).handle( ( route ) => route.fallback() )     // raw Playwright Route
ctx.intercept( "**/ads/**" ).abort()                                      // every page of a context

Terminal methods return the page (or context), so the chain continues: page.intercept( ... ).respondJson( ... ).visit( "/" ). Register intercepts before navigating. Patterns: glob, full URL or page.regex().

Listen

page.onConsole( ( message ) => println( message.type & ": " & message.text ) )   // { type, text, location }
	.onRequest( ( request ) => println( request.method & " " & request.url ) )  // { url, method, resourceType }
	.onResponse( ( response ) => println( response.status ) )                  // { url, status, ok }
	.onPageError( ( error ) => println( error.message ) )                      // { message, stack }
	.onDialog( ( dialog ) => dialog.accept() )                                 // raw Playwright Dialog

API Testing

api = playwright().request( { baseURL : "http://localhost:8080" } )
try {
	response = api.post( "/api/login", { json : { user : "luis" }, headers : { "X-Token" : "abc" }, params : { v : 2 } } )
	api.expect( response ).toBeOK()
	data = response.json()
	missing = api.get( "/api/nope" )          // status 404 does not throw; use failOnStatusCode : true to throw
	println( missing.status() & " " & missing.ok() )
} finally {
	api.close()
}

Verbs: get, post, put, patch, delete. Options: json, form, data, params, headers, timeout, failOnStatusCode, maxRedirects. Response: status(), ok(), url(), headers(), text(), json(). context.request() shares the context cookies.

Cookies and State

ctx.addCookies( [ { name : "auth", value : "token", url : "http://localhost:8080/" } ] )
ctx.cookies()                     // array of structs
ctx.clearCookies()
ctx.grantPermissions( [ "geolocation" ] )
ctx.setOffline( true )
ctx.saveStorageState( "state.json" )
pw.newPage( { storageState : "state.json" } )

Saved Sessions (log in once)

pw = playwright( { baseURL : "http://localhost:8080" } )
pw.session( "admin", ( page ) => {
	page.visit( "/login" ).fill( "Email", "[email protected]" ).fill( "Password", "secret" ).click( "Sign in" ).assertPathIs( "/dashboard" )
} )
pw.newPage( { session : "admin" } ).visit( "/admin" ).assertSee( "Admin" )
  • The setup runs only when the session file is missing, older than maxAge minutes, or refresh : true.
  • Sessions are stored in {home}/sessions (they hold cookies; keep them out of the project).
  • Using a session that does not exist throws Playwright.InvalidOption.