2025-03-21 10:58:58 -07:00
/ * *
* Copyright ( c ) Microsoft Corporation .
*
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
2025-04-30 23:06:56 +02:00
import { test , expect } from './fixtures.js' ;
2025-03-21 10:58:58 -07:00
2025-05-08 17:02:09 -07:00
test ( 'browser_navigate' , async ( { client , server } ) = > {
2025-03-27 16:50:43 -07:00
expect ( await client . callTool ( {
name : 'browser_navigate' ,
2025-05-08 17:02:09 -07:00
arguments : { url : server.HELLO_WORLD } ,
2025-03-27 16:50:43 -07:00
} ) ) . toHaveTextContent ( `
2025-04-16 17:18:40 +02:00
- Ran Playwright code :
2025-04-15 12:54:45 -07:00
\ ` \` \` js
2025-05-08 17:02:09 -07:00
// Navigate to ${server.HELLO_WORLD}
await page . goto ( '${server.HELLO_WORLD}' ) ;
2025-04-15 12:54:45 -07:00
\ ` \` \`
2025-04-15 19:55:20 +02:00
2025-05-08 17:02:09 -07:00
- Page URL : $ { server . HELLO_WORLD }
2025-03-21 10:58:58 -07:00
- Page Title : Title
- Page Snapshot
\ ` \` \` yaml
2025-07-14 09:53:33 +02:00
- generic [ active ] [ ref = e1 ] : Hello , world !
2025-03-21 10:58:58 -07:00
\ ` \` \`
2025-03-27 23:47:15 +01:00
`
2025-03-27 16:50:43 -07:00
) ;
2025-03-21 10:58:58 -07:00
} ) ;
2025-07-14 09:53:33 +02:00
test ( 'browser_click' , async ( { client , server , mcpBrowser } ) = > {
2025-05-08 17:02:09 -07:00
server . setContent ( '/' , `
< title > Title < / title >
< button > Submit < / button >
` , 'text/html');
2025-03-27 16:50:43 -07:00
await client . callTool ( {
name : 'browser_navigate' ,
2025-05-08 17:02:09 -07:00
arguments : { url : server.PREFIX } ,
2025-03-27 16:50:43 -07:00
} ) ;
2025-03-21 10:58:58 -07:00
2025-03-27 16:50:43 -07:00
expect ( await client . callTool ( {
name : 'browser_click' ,
arguments : {
element : 'Submit button' ,
2025-05-09 18:01:17 -07:00
ref : 'e2' ,
2025-03-27 16:50:43 -07:00
} ,
2025-04-15 19:55:20 +02:00
} ) ) . toHaveTextContent ( `
2025-04-16 17:18:40 +02:00
- Ran Playwright code :
2025-04-15 12:54:45 -07:00
\ ` \` \` js
// Click Submit button
await page . getByRole ( 'button' , { name : 'Submit' } ) . click ( ) ;
\ ` \` \`
2025-03-21 10:58:58 -07:00
2025-05-08 17:02:09 -07:00
- Page URL : $ { server . PREFIX }
2025-03-21 10:58:58 -07:00
- Page Title : Title
- Page Snapshot
\ ` \` \` yaml
2025-07-14 09:51:14 -07:00
- button "Submit" $ { mcpBrowser !== 'webkit' || process . platform === 'linux' ? '[active] ' : '' } [ ref = e2 ]
2025-03-21 10:58:58 -07:00
\ ` \` \`
2025-03-27 16:50:43 -07:00
` );
2025-03-21 10:58:58 -07:00
} ) ;
2025-03-25 13:05:28 -07:00
2025-07-11 16:45:39 -07:00
test ( 'browser_click (double)' , async ( { client , server } ) = > {
server . setContent ( '/' , `
< title > Title < / title >
< script >
function handle() {
document . querySelector ( 'h1' ) . textContent = 'Double clicked' ;
}
< / script >
< h1 ondblclick = "handle()" > Click me < / h1 >
` , 'text/html');
await client . callTool ( {
name : 'browser_navigate' ,
arguments : { url : server.PREFIX } ,
} ) ;
expect ( await client . callTool ( {
name : 'browser_click' ,
arguments : {
element : 'Click me' ,
ref : 'e2' ,
doubleClick : true ,
} ,
} ) ) . toHaveTextContent ( `
- Ran Playwright code :
\ ` \` \` js
// Double click Click me
await page . getByRole ( 'heading' , { name : 'Click me' } ) . dblclick ( ) ;
\ ` \` \`
- Page URL : $ { server . PREFIX }
- Page Title : Title
- Page Snapshot
\ ` \` \` yaml
- heading "Double clicked" [ level = 1 ] [ ref = e3 ]
\ ` \` \`
` );
} ) ;
2025-05-08 17:02:09 -07:00
test ( 'browser_select_option' , async ( { client , server } ) = > {
server . setContent ( '/' , `
< title > Title < / title >
< select >
< option value = "foo" > Foo < / option >
< option value = "bar" > Bar < / option >
< / select >
` , 'text/html');
2025-03-27 16:50:43 -07:00
await client . callTool ( {
name : 'browser_navigate' ,
2025-05-08 17:02:09 -07:00
arguments : { url : server.PREFIX } ,
2025-03-27 16:50:43 -07:00
} ) ;
2025-03-26 13:53:56 +09:00
2025-03-27 16:50:43 -07:00
expect ( await client . callTool ( {
name : 'browser_select_option' ,
arguments : {
element : 'Select' ,
2025-05-09 18:01:17 -07:00
ref : 'e2' ,
2025-03-27 16:50:43 -07:00
values : [ 'bar' ] ,
} ,
2025-04-15 19:55:20 +02:00
} ) ) . toHaveTextContent ( `
2025-04-16 17:18:40 +02:00
- Ran Playwright code :
2025-04-15 12:54:45 -07:00
\ ` \` \` js
// Select options [bar] in Select
await page . getByRole ( 'combobox' ) . selectOption ( [ 'bar' ] ) ;
\ ` \` \`
2025-03-26 13:53:56 +09:00
2025-05-08 17:02:09 -07:00
- Page URL : $ { server . PREFIX }
2025-03-26 13:53:56 +09:00
- Page Title : Title
- Page Snapshot
\ ` \` \` yaml
2025-05-09 18:01:17 -07:00
- combobox [ ref = e2 ] :
2025-04-22 16:04:50 -07:00
- option "Foo"
- option "Bar" [ selected ]
2025-03-26 13:53:56 +09:00
\ ` \` \`
2025-03-27 16:50:43 -07:00
` );
} ) ;
2025-03-26 13:53:56 +09:00
2025-05-08 17:02:09 -07:00
test ( 'browser_select_option (multiple)' , async ( { client , server } ) = > {
server . setContent ( '/' , `
< title > Title < / title >
< select multiple >
< option value = "foo" > Foo < / option >
< option value = "bar" > Bar < / option >
< option value = "baz" > Baz < / option >
< / select >
` , 'text/html');
2025-03-27 16:50:43 -07:00
await client . callTool ( {
name : 'browser_navigate' ,
2025-05-08 17:02:09 -07:00
arguments : { url : server.PREFIX } ,
2025-03-27 16:50:43 -07:00
} ) ;
2025-03-26 13:53:56 +09:00
2025-03-27 16:50:43 -07:00
expect ( await client . callTool ( {
name : 'browser_select_option' ,
arguments : {
element : 'Select' ,
2025-05-09 18:01:17 -07:00
ref : 'e2' ,
2025-03-27 16:50:43 -07:00
values : [ 'bar' , 'baz' ] ,
} ,
2025-04-15 19:55:20 +02:00
} ) ) . toHaveTextContent ( `
2025-04-16 17:18:40 +02:00
- Ran Playwright code :
2025-04-15 12:54:45 -07:00
\ ` \` \` js
// Select options [bar, baz] in Select
await page . getByRole ( 'listbox' ) . selectOption ( [ 'bar' , 'baz' ] ) ;
\ ` \` \`
2025-03-26 13:53:56 +09:00
2025-05-08 17:02:09 -07:00
- Page URL : $ { server . PREFIX }
2025-03-26 13:53:56 +09:00
- Page Title : Title
- Page Snapshot
\ ` \` \` yaml
2025-05-09 18:01:17 -07:00
- listbox [ ref = e2 ] :
- option "Foo" [ ref = e3 ]
- option "Bar" [ selected ] [ ref = e4 ]
- option "Baz" [ selected ] [ ref = e5 ]
2025-03-26 13:53:56 +09:00
\ ` \` \`
2025-03-27 16:50:43 -07:00
` );
2025-03-26 13:53:56 +09:00
} ) ;
2025-03-26 16:27:55 +01:00
2025-05-08 17:02:09 -07:00
test ( 'browser_type' , async ( { client , server } ) = > {
server . setContent ( '/' , `
< ! DOCTYPE html >
< html >
< input type = 'keypress' onkeypress = "console.log('Key pressed:', event.key, ', Text:', event.target.value)" > < / input >
< / html >
` , 'text/html');
2025-04-02 14:36:30 -07:00
await client . callTool ( {
name : 'browser_navigate' ,
arguments : {
2025-05-08 17:02:09 -07:00
url : server.PREFIX ,
2025-04-02 14:36:30 -07:00
} ,
} ) ;
await client . callTool ( {
name : 'browser_type' ,
arguments : {
element : 'textbox' ,
2025-05-09 18:01:17 -07:00
ref : 'e2' ,
2025-04-02 14:36:30 -07:00
text : 'Hi!' ,
submit : true ,
} ,
} ) ;
2025-04-15 18:01:59 -07:00
expect ( await client . callTool ( {
name : 'browser_console_messages' ,
} ) ) . toHaveTextContent ( '[LOG] Key pressed: Enter , Text: Hi!' ) ;
2025-04-02 14:36:30 -07:00
} ) ;
2025-05-08 17:02:09 -07:00
test ( 'browser_type (slowly)' , async ( { client , server } ) = > {
server . setContent ( '/' , `
< input type = 'text' onkeydown = "console.log('Key pressed:', event.key, 'Text:', event.target.value)" > < / input >
` , 'text/html');
2025-04-02 14:36:30 -07:00
await client . callTool ( {
name : 'browser_navigate' ,
arguments : {
2025-05-08 17:02:09 -07:00
url : server.PREFIX ,
2025-04-02 14:36:30 -07:00
} ,
} ) ;
await client . callTool ( {
name : 'browser_type' ,
arguments : {
element : 'textbox' ,
2025-05-09 18:01:17 -07:00
ref : 'e2' ,
2025-04-02 14:36:30 -07:00
text : 'Hi!' ,
submit : true ,
slowly : true ,
} ,
} ) ;
2025-04-15 18:01:59 -07:00
expect ( await client . callTool ( {
name : 'browser_console_messages' ,
} ) ) . toHaveTextContent ( [
'[LOG] Key pressed: H Text: ' ,
'[LOG] Key pressed: i Text: H' ,
'[LOG] Key pressed: ! Text: Hi' ,
'[LOG] Key pressed: Enter Text: Hi!' ,
] . join ( '\n' ) ) ;
2025-04-02 14:36:30 -07:00
} ) ;
2025-04-15 01:09:48 +02:00
2025-05-08 17:02:09 -07:00
test ( 'browser_resize' , async ( { client , server } ) = > {
server . setContent ( '/' , `
< title > Resize Test < / title >
< body >
< div id = "size" > Waiting for resize . . . < / div >
< script > new ResizeObserver ( ( ) = > { document . getElementById ( "size" ) . textContent = \ ` Window size: \ ${ window . innerWidth } x \ ${ window . innerHeight } \` ; }).observe(document.body);
< / script >
< / body >
` , 'text/html');
2025-04-15 01:09:48 +02:00
await client . callTool ( {
name : 'browser_navigate' ,
2025-05-08 17:02:09 -07:00
arguments : { url : server.PREFIX } ,
2025-04-15 01:09:48 +02:00
} ) ;
const response = await client . callTool ( {
name : 'browser_resize' ,
arguments : {
width : 390 ,
height : 780 ,
} ,
} ) ;
2025-04-16 17:18:40 +02:00
expect ( response ) . toContainTextContent ( ` - Ran Playwright code:
2025-04-15 12:54:45 -07:00
\ ` \` \` js
// Resize browser window to 390x780
await page . setViewportSize ( { width : 390 , height : 780 } ) ;
\ ` \` \` ` ) ;
2025-05-12 09:35:33 -07:00
await expect . poll ( ( ) = > client . callTool ( { name : 'browser_snapshot' } ) ) . toContainTextContent ( 'Window size: 390x780' ) ;
2025-04-15 01:09:48 +02:00
} ) ;
2025-06-17 14:09:29 +02:00
test ( 'old locator error message' , async ( { client , server } ) = > {
server . setContent ( '/' , `
< button > Button 1 < / button >
< button > Button 2 < / button >
< script >
document . querySelector ( 'button' ) . addEventListener ( 'click' , ( ) = > {
document . querySelectorAll ( 'button' ) [ 1 ] . remove ( ) ;
} ) ;
< / script >
` , 'text/html');
expect ( await client . callTool ( {
name : 'browser_navigate' ,
arguments : {
url : server.PREFIX ,
} ,
} ) ) . toContainTextContent ( `
- button "Button 1" [ ref = e2 ]
- button "Button 2" [ ref = e3 ]
` .trim());
await client . callTool ( {
name : 'browser_click' ,
arguments : {
element : 'Button 1' ,
ref : 'e2' ,
} ,
} ) ;
expect ( await client . callTool ( {
name : 'browser_click' ,
arguments : {
element : 'Button 2' ,
ref : 'e3' ,
} ,
} ) ) . toContainTextContent ( 'Ref not found' ) ;
} ) ;
2025-07-14 09:53:33 +02:00
test ( 'visibility: hidden > visible should be shown' , { annotation : { type : 'issue' , description : 'https://github.com/microsoft/playwright-mcp/issues/535' } } , async ( { client , server } ) = > {
server . setContent ( '/' , `
< div style = "visibility: hidden;" >
< div style = "visibility: visible;" >
< button > Button < / button >
< / div >
< / div >
` , 'text/html');
await client . callTool ( {
name : 'browser_navigate' ,
arguments : { url : server.PREFIX } ,
} ) ;
expect ( await client . callTool ( {
name : 'browser_snapshot'
} ) ) . toContainTextContent ( '- button "Button"' ) ;
} ) ;