@browserstack/mcp-server 2.3.0-beta.5 → 2.3.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/capability/devicecontrol.capability-index.json +153 -18
- package/capability/mobiledevicecontrol.capability-index.json +540 -76
- package/dist/tools/applive.js +10 -1
- package/dist/tools/capability-registry/fallback.d.ts +40 -0
- package/dist/tools/capability-registry/fallback.js +61 -0
- package/dist/tools/capability-registry/index-loader.js +46 -4
- package/dist/tools/capability-registry/register.js +21 -11
- package/dist/tools/capability-registry/search.js +2 -1
- package/dist/tools/capability-registry/types.d.ts +64 -20
- package/dist/tools/capability-registry/types.js +13 -0
- package/dist/tools/failurelogs-utils/app-automate.js +1 -1
- package/dist/tools/live.js +8 -1
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"version": "1.0",
|
|
4
4
|
"build_id": "8445466_2026-10-19T06:53:46Z",
|
|
5
5
|
"devicecontrol": {
|
|
6
|
-
"summary": "Device control: drive a real desktop or mobile browser page by page. The account side lists every operating system, browser and version combination available, reports parallel-session capacity, and keeps each session's record \u2014 status, shareable link, video, and console, network and profiling logs \u2014 after the browser is released. The session side opens a browser on a chosen combination and drives it: navigate, go back and forward, reload,
|
|
6
|
+
"summary": "Device control: drive a real desktop or mobile browser page by page. The account side lists every operating system, browser and version combination available, reports parallel-session capacity, and keeps each session's record \u2014 status, shareable link, video, and console, network and profiling logs \u2014 after the browser is released. The session side opens a browser on a chosen combination and drives it: navigate, go back and forward, reload, find elements by CSS or XPath, click, type, clear, screenshot the viewport, resize the window, and move between tabs and iframes. Web pages are RUN here \u2014 unlike Test Management, which authors cases, and Test Reporting, which records results pushed in from a runner. Mobile APPS are not here: those are mobile device control, which drives an installed app rather than a browser. Scrolling is done with scroll_to_element or scroll_page, there is no capability that waits, and element ids go stale as soon as the page navigates or re-renders. A session holds a browser until it is ended.",
|
|
7
7
|
"routing_terms": [
|
|
8
8
|
"automate",
|
|
9
9
|
"browser",
|
|
@@ -262,7 +262,8 @@
|
|
|
262
262
|
"The session ends itself after idle_timeout seconds without a command, and after 2 hours in total.",
|
|
263
263
|
"console_logs and network_logs must be asked for here; they cannot be turned on once the session is running, and get_session only links to them when they were.",
|
|
264
264
|
"Credentials belong in the Authorization header, never inside bstack:options: capabilities are echoed back in session-not-created errors.",
|
|
265
|
-
"resolution takes one of a fixed set of values per operating system, not any width and height: an unsupported pair is refused outright rather than rounded to the nearest one. The browser window is well short of the screen it sits on \u2014 1920x1080 gives a viewport around 930x860 \u2014 so measure it rather than assuming the request was honoured."
|
|
265
|
+
"resolution takes one of a fixed set of values per operating system, not any width and height: an unsupported pair is refused outright rather than rounded to the nearest one. The browser window is well short of the screen it sits on \u2014 1920x1080 gives a viewport around 930x860 \u2014 so measure it rather than assuming the request was honoured.",
|
|
266
|
+
"THIS CALL RETURNS NO LINK \u2014 only value.sessionId. Nothing here can open a browser for the user either: this surface makes HTTP requests, and on a remote server there is no browser to open. So never say a live view was opened. If the user may want to watch, call get_session straight after this and give them browser_url in the same reply, which is the session on the dashboard and needs a BrowserStack login. public_url needs no login but carries an auth token, so offer it only when they ask to share outside the team."
|
|
266
267
|
],
|
|
267
268
|
"body": [
|
|
268
269
|
{
|
|
@@ -499,7 +500,7 @@
|
|
|
499
500
|
"entity": "browser_session",
|
|
500
501
|
"intent": "Read the page title \u2014 the cheapest way to confirm which page is loaded.",
|
|
501
502
|
"guidance": [
|
|
502
|
-
"
|
|
503
|
+
"The cheapest way to confirm which page is showing, and enough on its own for most navigation checks."
|
|
503
504
|
],
|
|
504
505
|
"path_params": [
|
|
505
506
|
{
|
|
@@ -664,7 +665,8 @@
|
|
|
664
665
|
"404": {
|
|
665
666
|
"$response": "WebDriverError"
|
|
666
667
|
}
|
|
667
|
-
}
|
|
668
|
+
},
|
|
669
|
+
"disabled": true
|
|
668
670
|
},
|
|
669
671
|
{
|
|
670
672
|
"name": "find_element",
|
|
@@ -790,7 +792,7 @@
|
|
|
790
792
|
"intent": "Click an element \u2014 use this for buttons, links, checkboxes and anything else that responds to a click.",
|
|
791
793
|
"guidance": [
|
|
792
794
|
"Takes no parameters of its own.",
|
|
793
|
-
"The element must be in view and not covered. A click on something another element overlaps answers \"element click intercepted\" and names the element in the way \u2014 scroll it into view with
|
|
795
|
+
"The element must be in view and not covered. A click on something another element overlaps answers \"element click intercepted\" and names the element in the way \u2014 scroll it into view with scroll_to_element, or dismiss the overlay first.",
|
|
794
796
|
"An element that is not visible answers \"element not interactable\".",
|
|
795
797
|
"Success means the click was dispatched, not that the page has finished reacting: read the page or the URL afterwards to confirm."
|
|
796
798
|
],
|
|
@@ -835,7 +837,7 @@
|
|
|
835
837
|
"guidance": [
|
|
836
838
|
"APPENDS to whatever the field already holds. Call clear_element first to replace the value rather than adding to it.",
|
|
837
839
|
"Read the result back with get_element_property on \"value\": a field's current contents are a property, not text.",
|
|
838
|
-
"A \\n at the end submits the form on a desktop browser and on Chrome for Android, and is quicker than finding the submit button. IT DOES NOT SUBMIT ON SAFARI FOR iOS \u2014 the text lands in the field and the page stays where it is, whether the newline is sent with the text or on its own. There, click the form's submit button
|
|
840
|
+
"A \\n at the end submits the form on a desktop browser and on Chrome for Android, and is quicker than finding the submit button. IT DOES NOT SUBMIT ON SAFARI FOR iOS \u2014 the text lands in the field and the page stays where it is, whether the newline is sent with the text or on its own. There, click the form's submit button with click_element \u2014 scroll_to_element first if it sits below the fold.",
|
|
839
841
|
"The element must be editable; typing into anything else answers \"element not interactable\".",
|
|
840
842
|
"A site's own autocomplete or dropdown may swallow the keystrokes and require a click on a suggestion instead."
|
|
841
843
|
],
|
|
@@ -962,8 +964,7 @@
|
|
|
962
964
|
"404": {
|
|
963
965
|
"$response": "WebDriverError"
|
|
964
966
|
}
|
|
965
|
-
}
|
|
966
|
-
"disabled": true
|
|
967
|
+
}
|
|
967
968
|
},
|
|
968
969
|
{
|
|
969
970
|
"name": "get_element_property",
|
|
@@ -1061,8 +1062,7 @@
|
|
|
1061
1062
|
"404": {
|
|
1062
1063
|
"$response": "WebDriverError"
|
|
1063
1064
|
}
|
|
1064
|
-
}
|
|
1065
|
-
"disabled": true
|
|
1065
|
+
}
|
|
1066
1066
|
},
|
|
1067
1067
|
{
|
|
1068
1068
|
"name": "is_element_displayed",
|
|
@@ -1103,8 +1103,120 @@
|
|
|
1103
1103
|
"404": {
|
|
1104
1104
|
"$response": "WebDriverError"
|
|
1105
1105
|
}
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1106
|
+
}
|
|
1107
|
+
},
|
|
1108
|
+
{
|
|
1109
|
+
"name": "scroll_to_element",
|
|
1110
|
+
"method": "POST",
|
|
1111
|
+
"path": "/wd/hub/session/{session_id}/execute/sync",
|
|
1112
|
+
"mode": "write",
|
|
1113
|
+
"entity": "browser_session",
|
|
1114
|
+
"intent": "Bring an element into view \u2014 use this before clicking or screenshotting something below the fold, since both fail or miss when the target is off screen.",
|
|
1115
|
+
"guidance": [
|
|
1116
|
+
"THE RELIABLE FORM ON EVERY PLATFORM. Prefer this to scrolling the page by a distance: it works out where the element is for you, and it does not depend on the page reporting its height correctly, which scroll_page does.",
|
|
1117
|
+
"The element_id goes in args as {\"element-6066-11e4-a52e-4f735466cecf\": \"<id>\"} and arrives in the script as arguments[0]; find_element gives you the id.",
|
|
1118
|
+
"Returns the element's position after scrolling, so a caller can confirm it really is in view rather than trusting the status.",
|
|
1119
|
+
"A click on a covered element answers \"element click intercepted\" \u2014 scroll it into view with this first."
|
|
1120
|
+
],
|
|
1121
|
+
"path_params": [
|
|
1122
|
+
{
|
|
1123
|
+
"name": "session_id",
|
|
1124
|
+
"type": "string",
|
|
1125
|
+
"required": true,
|
|
1126
|
+
"example": "0123456789abcdef0123456789abcdef01234567"
|
|
1127
|
+
}
|
|
1128
|
+
],
|
|
1129
|
+
"body": [
|
|
1130
|
+
{
|
|
1131
|
+
"name": "script",
|
|
1132
|
+
"type": "string",
|
|
1133
|
+
"required": true,
|
|
1134
|
+
"example": "arguments[0].scrollIntoView({block:'center'}); var r=arguments[0].getBoundingClientRect(); return {top:r.top,bottom:r.bottom,innerHeight:window.innerHeight};",
|
|
1135
|
+
"values": [
|
|
1136
|
+
"arguments[0].scrollIntoView({block:'center'}); var r=arguments[0].getBoundingClientRect(); return {top:r.top,bottom:r.bottom,innerHeight:window.innerHeight};"
|
|
1137
|
+
]
|
|
1138
|
+
},
|
|
1139
|
+
{
|
|
1140
|
+
"name": "args",
|
|
1141
|
+
"type": "array",
|
|
1142
|
+
"required": true,
|
|
1143
|
+
"description": "Exactly one object holding the element reference.",
|
|
1144
|
+
"example": [
|
|
1145
|
+
{
|
|
1146
|
+
"element-6066-11e4-a52e-4f735466cecf": "<element_id>"
|
|
1147
|
+
}
|
|
1148
|
+
]
|
|
1149
|
+
}
|
|
1150
|
+
],
|
|
1151
|
+
"returns": [
|
|
1152
|
+
"value"
|
|
1153
|
+
],
|
|
1154
|
+
"responses": {
|
|
1155
|
+
"200": {
|
|
1156
|
+
"description": "Whatever the script returned.",
|
|
1157
|
+
"schema": {
|
|
1158
|
+
"$schema": "AnyValueResponse"
|
|
1159
|
+
}
|
|
1160
|
+
},
|
|
1161
|
+
"404": {
|
|
1162
|
+
"$response": "WebDriverError"
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
},
|
|
1166
|
+
{
|
|
1167
|
+
"name": "scroll_page",
|
|
1168
|
+
"method": "POST",
|
|
1169
|
+
"path": "/wd/hub/session/{session_id}/execute/sync",
|
|
1170
|
+
"mode": "write",
|
|
1171
|
+
"entity": "browser_session",
|
|
1172
|
+
"intent": "Scroll the page itself by a distance or to the bottom \u2014 use this when there is no element to aim at, such as reaching a footer or loading more of an infinite list.",
|
|
1173
|
+
"guidance": [
|
|
1174
|
+
"PREFER scroll_to_element when you have an element: it works out where the target is for you. Use this form only when there is nothing to aim at.",
|
|
1175
|
+
"Choose what it does with args: \"bottom\", \"top\", or a pixel count.",
|
|
1176
|
+
"Returns the scroll position and the page height, so a caller can tell whether it actually reached the end: at rest at the bottom, scrollY + innerHeight equals scrollHeight within a couple of pixels \u2014 a scaled phone screen reports fractional positions, so do not demand exact equality. ON SAFARI THE POSITION IN THE \"bottom\" CALL'S OWN RESPONSE IS WHERE IT WAS ASKED TO GO, NOT WHERE IT STOPPED \u2014 it comes back equal to scrollHeight, which no resting position can be. Call again with args 0 to read the real position; that second reading is the one to check."
|
|
1177
|
+
],
|
|
1178
|
+
"path_params": [
|
|
1179
|
+
{
|
|
1180
|
+
"name": "session_id",
|
|
1181
|
+
"type": "string",
|
|
1182
|
+
"required": true,
|
|
1183
|
+
"example": "0123456789abcdef0123456789abcdef01234567"
|
|
1184
|
+
}
|
|
1185
|
+
],
|
|
1186
|
+
"body": [
|
|
1187
|
+
{
|
|
1188
|
+
"name": "script",
|
|
1189
|
+
"type": "string",
|
|
1190
|
+
"required": true,
|
|
1191
|
+
"example": "var a=arguments[0]; var h=Math.max(document.body.scrollHeight,document.documentElement.scrollHeight); if(a==='bottom'){window.scrollTo(0,h);} else if(a==='top'){window.scrollTo(0,0);} else {window.scrollBy(0,Number(a));} return {scrollY:window.scrollY, innerHeight:window.innerHeight, scrollHeight:Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)};",
|
|
1192
|
+
"values": [
|
|
1193
|
+
"var a=arguments[0]; var h=Math.max(document.body.scrollHeight,document.documentElement.scrollHeight); if(a==='bottom'){window.scrollTo(0,h);} else if(a==='top'){window.scrollTo(0,0);} else {window.scrollBy(0,Number(a));} return {scrollY:window.scrollY, innerHeight:window.innerHeight, scrollHeight:Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)};"
|
|
1194
|
+
]
|
|
1195
|
+
},
|
|
1196
|
+
{
|
|
1197
|
+
"name": "args",
|
|
1198
|
+
"type": "array",
|
|
1199
|
+
"required": true,
|
|
1200
|
+
"description": "Exactly one value: \"bottom\", \"top\", or a number of pixels to scroll by (negative scrolls up).",
|
|
1201
|
+
"example": [
|
|
1202
|
+
"bottom"
|
|
1203
|
+
]
|
|
1204
|
+
}
|
|
1205
|
+
],
|
|
1206
|
+
"returns": [
|
|
1207
|
+
"value"
|
|
1208
|
+
],
|
|
1209
|
+
"responses": {
|
|
1210
|
+
"200": {
|
|
1211
|
+
"description": "Whatever the script returned.",
|
|
1212
|
+
"schema": {
|
|
1213
|
+
"$schema": "AnyValueResponse"
|
|
1214
|
+
}
|
|
1215
|
+
},
|
|
1216
|
+
"404": {
|
|
1217
|
+
"$response": "WebDriverError"
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1108
1220
|
},
|
|
1109
1221
|
{
|
|
1110
1222
|
"name": "execute_script",
|
|
@@ -1114,7 +1226,8 @@
|
|
|
1114
1226
|
"entity": "browser_session",
|
|
1115
1227
|
"intent": "Run JavaScript in the page \u2014 use this to scroll, read something the element readers cannot reach, or drive a control that resists clicking.",
|
|
1116
1228
|
"guidance": [
|
|
1117
|
-
"SCROLLING LIVES HERE
|
|
1229
|
+
"SCROLLING LIVES HERE, and the reliable form is the ELEMENT one: pass the element in args and call arguments[0].scrollIntoView({block:'center'}). window.scrollTo(0, document.body.scrollHeight) reaches the bottom on a desktop browser, but on Chrome for Android it can stop short and leave a footer off screen while still reporting success \u2014 so scroll the thing you actually want rather than the page, and confirm with a screenshot or the page source.",
|
|
1230
|
+
"READING THE PAGE'S MARKUP LIVES HERE TOO: 'return document.documentElement.outerHTML' for the whole document, or 'return arguments[0].outerHTML' with an element in args for one part of it. Prefer the element form \u2014 a real page runs to tens of kilobytes and the whole document is rarely what is wanted. This is also how to discover a selector on a page you have not seen: read the markup around the area you care about rather than guessing a selector, which fails silently when it matches nothing.",
|
|
1118
1231
|
"`return` is required to get a value back; without it the answer is null.",
|
|
1119
1232
|
"An element id can be passed in args as {\"element-6066-11e4-a52e-4f735466cecf\": \"<id>\"} and arrives as a real element in arguments.",
|
|
1120
1233
|
"It runs with the page's own privileges and can change anything, so a script that alters state is as consequential as a click.",
|
|
@@ -1157,7 +1270,8 @@
|
|
|
1157
1270
|
"404": {
|
|
1158
1271
|
"$response": "WebDriverError"
|
|
1159
1272
|
}
|
|
1160
|
-
}
|
|
1273
|
+
},
|
|
1274
|
+
"disabled": true
|
|
1161
1275
|
},
|
|
1162
1276
|
{
|
|
1163
1277
|
"name": "take_screenshot",
|
|
@@ -1168,7 +1282,7 @@
|
|
|
1168
1282
|
"intent": "Take a screenshot of the browser's viewport, as a base64 PNG \u2014 use this to see the page as a user would.",
|
|
1169
1283
|
"guidance": [
|
|
1170
1284
|
"Returned inline as base64 and typically tens of kilobytes, so take one when the picture is needed rather than after every step.",
|
|
1171
|
-
"The VIEWPORT only, not the whole page: anything below the fold needs scrolling into view first with
|
|
1285
|
+
"The VIEWPORT only, not the whole page: anything below the fold needs scrolling into view first with scroll_to_element.",
|
|
1172
1286
|
"get_title and get_element_property answer most checks far more cheaply than reading an image."
|
|
1173
1287
|
],
|
|
1174
1288
|
"path_params": [
|
|
@@ -1563,13 +1677,14 @@
|
|
|
1563
1677
|
}
|
|
1564
1678
|
],
|
|
1565
1679
|
"returns": [
|
|
1680
|
+
"state",
|
|
1566
1681
|
"value"
|
|
1567
1682
|
],
|
|
1568
1683
|
"responses": {
|
|
1569
1684
|
"200": {
|
|
1570
|
-
"description": "
|
|
1685
|
+
"description": "state is \"success\" and value an empty string; the body is the hub's own, not the W3C null.",
|
|
1571
1686
|
"schema": {
|
|
1572
|
-
"$schema": "
|
|
1687
|
+
"$schema": "SessionDeletedResponse"
|
|
1573
1688
|
}
|
|
1574
1689
|
},
|
|
1575
1690
|
"404": {
|
|
@@ -1955,6 +2070,24 @@
|
|
|
1955
2070
|
}
|
|
1956
2071
|
}
|
|
1957
2072
|
}
|
|
2073
|
+
},
|
|
2074
|
+
"SessionDeletedResponse": {
|
|
2075
|
+
"type": "object",
|
|
2076
|
+
"description": "What the hub returns when a session is closed. Not the W3C null: state says whether it closed and value is an empty string.",
|
|
2077
|
+
"properties": {
|
|
2078
|
+
"state": {
|
|
2079
|
+
"type": "string",
|
|
2080
|
+
"description": "\"success\" when the session was closed."
|
|
2081
|
+
},
|
|
2082
|
+
"status": {
|
|
2083
|
+
"type": "integer",
|
|
2084
|
+
"description": "The hub's own legacy status code; 0 on success."
|
|
2085
|
+
},
|
|
2086
|
+
"value": {
|
|
2087
|
+
"type": "string",
|
|
2088
|
+
"description": "Always empty on success."
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
1958
2091
|
}
|
|
1959
2092
|
},
|
|
1960
2093
|
"responses": {
|
|
@@ -2024,7 +2157,9 @@
|
|
|
2024
2157
|
"open_new_window",
|
|
2025
2158
|
"switch_to_frame",
|
|
2026
2159
|
"get_cookies",
|
|
2027
|
-
"delete_session"
|
|
2160
|
+
"delete_session",
|
|
2161
|
+
"scroll_to_element",
|
|
2162
|
+
"scroll_page"
|
|
2028
2163
|
]
|
|
2029
2164
|
},
|
|
2030
2165
|
"browser": {
|