or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

alerts.mdconfiguration.mddrivers.mdelements.mdindex.mdinteractions.mdjavascript.mdlocators.mdpage-objects.mdwaits.mdwebdriver.md

javascript.mddocs/

0

# JavaScript Execution

1

2

Interface for executing JavaScript code in the browser context with support for synchronous/asynchronous execution, script pinning, and argument passing.

3

4

## Capabilities

5

6

### JavascriptExecutor Interface

7

8

Interface for executing JavaScript code within the browser context with parameter passing and return value handling.

9

10

```java { .api }

11

/**

12

* JavascriptExecutor interface for executing JavaScript code in browser context

13

* Provides synchronous and asynchronous script execution with argument passing

14

*/

15

interface JavascriptExecutor {

16

/**

17

* Execute JavaScript synchronously in browser context

18

* @param script - JavaScript code to execute

19

* @param args - Arguments to pass to script (accessible as arguments[0], arguments[1], etc.)

20

* @return Result of script execution (may be null, primitive, WebElement, or List)

21

*/

22

Object executeScript(String script, Object... args);

23

24

/**

25

* Execute JavaScript asynchronously in browser context

26

* @param script - JavaScript code to execute (must call callback to complete)

27

* @param args - Arguments to pass to script

28

* @return Result of script execution

29

*/

30

Object executeAsyncScript(String script, Object... args);

31

32

/**

33

* Pin script for reuse with better performance

34

* @param script - JavaScript code to pin

35

* @return ScriptKey for referencing pinned script

36

*/

37

ScriptKey pin(String script);

38

39

/**

40

* Unpin previously pinned script

41

* @param key - ScriptKey of script to unpin

42

*/

43

void unpin(ScriptKey key);

44

45

/**

46

* Get all currently pinned scripts

47

* @return Set of ScriptKey objects for pinned scripts

48

*/

49

Set<ScriptKey> getPinnedScripts();

50

51

/**

52

* Execute pinned script by key

53

* @param key - ScriptKey of pinned script

54

* @param args - Arguments to pass to script

55

* @return Result of script execution

56

*/

57

Object executeScript(ScriptKey key, Object... args);

58

}

59

```

60

61

### ScriptKey Class

62

63

Reference key for pinned JavaScript scripts enabling efficient reuse.

64

65

```java { .api }

66

/**

67

* ScriptKey class representing a pinned JavaScript script

68

* Used for efficient execution of frequently used scripts

69

*/

70

class ScriptKey {

71

/**

72

* Get script identifier

73

* @return Unique identifier for the pinned script

74

*/

75

String getId();

76

77

/**

78

* Get original script content

79

* @return JavaScript code that was pinned

80

*/

81

String getScript();

82

}

83

```

84

85

## Usage Examples

86

87

### Basic JavaScript Execution

88

89

```java

90

import org.openqa.selenium.WebDriver;

91

import org.openqa.selenium.JavascriptExecutor;

92

import org.openqa.selenium.chrome.ChromeDriver;

93

94

WebDriver driver = new ChromeDriver();

95

JavascriptExecutor js = (JavascriptExecutor) driver;

96

97

try {

98

driver.get("https://example.com");

99

100

// Simple script execution

101

String title = (String) js.executeScript("return document.title;");

102

System.out.println("Page title: " + title);

103

104

// Execute script with return value

105

Long scrollHeight = (Long) js.executeScript("return document.body.scrollHeight;");

106

System.out.println("Page height: " + scrollHeight);

107

108

// Execute script that modifies the page

109

js.executeScript("document.body.style.backgroundColor = 'lightblue';");

110

111

// Execute script with no return value

112

js.executeScript("console.log('Hello from WebDriver!');");

113

114

} finally {

115

driver.quit();

116

}

117

```

118

119

### JavaScript with Arguments

120

121

```java

122

// Pass arguments to JavaScript

123

WebElement element = driver.findElement(By.id("myElement"));

124

String elementText = (String) js.executeScript(

125

"return arguments[0].textContent;",

126

element

127

);

128

129

// Multiple arguments

130

js.executeScript(

131

"arguments[0].style.backgroundColor = arguments[1]; arguments[0].style.color = arguments[2];",

132

element,

133

"yellow",

134

"red"

135

);

136

137

// Pass different types of arguments

138

js.executeScript(

139

"var element = arguments[0]; var show = arguments[1]; var delay = arguments[2]; " +

140

"if (show) { element.style.display = 'block'; } " +

141

"setTimeout(function() { element.style.opacity = '1'; }, delay);",

142

element,

143

true,

144

1000

145

);

146

147

// Return complex objects

148

Map<String, Object> elementInfo = (Map<String, Object>) js.executeScript(

149

"var elem = arguments[0]; " +

150

"return { " +

151

" tagName: elem.tagName, " +

152

" id: elem.id, " +

153

" className: elem.className, " +

154

" visible: elem.offsetWidth > 0 && elem.offsetHeight > 0 " +

155

"};",

156

element

157

);

158

```

159

160

### DOM Manipulation and Queries

161

162

```java

163

// Scroll to element

164

WebElement targetElement = driver.findElement(By.id("target"));

165

js.executeScript("arguments[0].scrollIntoView(true);", targetElement);

166

167

// Highlight element

168

js.executeScript(

169

"arguments[0].style.border = '3px solid red';" +

170

"arguments[0].style.backgroundColor = 'yellow';",

171

targetElement

172

);

173

174

// Get element position and size

175

Map<String, Object> elementBounds = (Map<String, Object>) js.executeScript(

176

"var rect = arguments[0].getBoundingClientRect(); " +

177

"return { " +

178

" x: rect.left, " +

179

" y: rect.top, " +

180

" width: rect.width, " +

181

" height: rect.height " +

182

"};",

183

targetElement

184

);

185

186

// Check if element is in viewport

187

Boolean isInViewport = (Boolean) js.executeScript(

188

"var rect = arguments[0].getBoundingClientRect(); " +

189

"return rect.top >= 0 && rect.left >= 0 && " +

190

"rect.bottom <= window.innerHeight && rect.right <= window.innerWidth;",

191

targetElement

192

);

193

194

// Find elements by complex criteria

195

List<WebElement> visibleElements = (List<WebElement>) js.executeScript(

196

"var elements = document.querySelectorAll(arguments[0]); " +

197

"var visible = []; " +

198

"for (var i = 0; i < elements.length; i++) { " +

199

" if (elements[i].offsetWidth > 0 && elements[i].offsetHeight > 0) { " +

200

" visible.push(elements[i]); " +

201

" } " +

202

"} " +

203

"return visible;",

204

".product-card"

205

);

206

```

207

208

### Asynchronous JavaScript Execution

209

210

```java

211

// Set script timeout for async operations

212

driver.manage().timeouts().setScriptTimeout(Duration.ofSeconds(30));

213

214

// Simple async script with callback

215

String result = (String) js.executeAsyncScript(

216

"var callback = arguments[arguments.length - 1]; " +

217

"setTimeout(function() { " +

218

" callback('Async operation completed'); " +

219

"}, 2000);"

220

);

221

222

// AJAX request with async script

223

String responseText = (String) js.executeAsyncScript(

224

"var callback = arguments[arguments.length - 1]; " +

225

"var xhr = new XMLHttpRequest(); " +

226

"xhr.open('GET', arguments[0], true); " +

227

"xhr.onreadystatechange = function() { " +

228

" if (xhr.readyState === 4) { " +

229

" callback(xhr.responseText); " +

230

" } " +

231

"}; " +

232

"xhr.send();",

233

"https://api.example.com/data"

234

);

235

236

// Wait for page element to load asynchronously

237

WebElement dynamicElement = (WebElement) js.executeAsyncScript(

238

"var callback = arguments[arguments.length - 1]; " +

239

"var checkElement = function() { " +

240

" var element = document.querySelector(arguments[0]); " +

241

" if (element) { " +

242

" callback(element); " +

243

" } else { " +

244

" setTimeout(checkElement, 100); " +

245

" } " +

246

"}; " +

247

"checkElement();",

248

"#dynamic-content"

249

);

250

```

251

252

### Script Pinning for Performance

253

254

```java

255

// Pin frequently used scripts

256

ScriptKey scrollScript = js.pin(

257

"window.scrollTo(0, arguments[0]);"

258

);

259

260

ScriptKey highlightScript = js.pin(

261

"arguments[0].style.border = '2px solid ' + arguments[1];" +

262

"arguments[0].style.backgroundColor = arguments[2];"

263

);

264

265

ScriptKey getElementInfoScript = js.pin(

266

"var elem = arguments[0]; " +

267

"return { " +

268

" text: elem.textContent, " +

269

" visible: elem.offsetWidth > 0 && elem.offsetHeight > 0, " +

270

" classes: elem.className.split(' '), " +

271

" attributes: Array.from(elem.attributes).map(attr => ({name: attr.name, value: attr.value})) " +

272

"};"

273

);

274

275

// Use pinned scripts multiple times

276

js.executeScript(scrollScript, 500);

277

js.executeScript(scrollScript, 1000);

278

279

WebElement button1 = driver.findElement(By.id("btn1"));

280

WebElement button2 = driver.findElement(By.id("btn2"));

281

282

js.executeScript(highlightScript, button1, "red", "yellow");

283

js.executeScript(highlightScript, button2, "blue", "lightgreen");

284

285

Map<String, Object> info1 = (Map<String, Object>) js.executeScript(getElementInfoScript, button1);

286

Map<String, Object> info2 = (Map<String, Object>) js.executeScript(getElementInfoScript, button2);

287

288

// Clean up pinned scripts when done

289

js.unpin(scrollScript);

290

js.unpin(highlightScript);

291

js.unpin(getElementInfoScript);

292

293

// Or get all pinned scripts and unpin them

294

Set<ScriptKey> pinnedScripts = js.getPinnedScripts();

295

pinnedScripts.forEach(js::unpin);

296

```

297

298

### Page Analysis and Testing

299

300

```java

301

// Performance metrics

302

Map<String, Object> performanceData = (Map<String, Object>) js.executeScript(

303

"var perf = window.performance; " +

304

"var timing = perf.timing; " +

305

"return { " +

306

" loadTime: timing.loadEventEnd - timing.navigationStart, " +

307

" domContentLoaded: timing.domContentLoadedEventEnd - timing.navigationStart, " +

308

" firstPaint: perf.getEntriesByType('paint')[0]?.startTime || null, " +

309

" memoryUsage: perf.memory ? perf.memory.usedJSHeapSize : null " +

310

"};"

311

);

312

313

// Accessibility checks

314

List<Map<String, Object>> accessibilityIssues = (List<Map<String, Object>>) js.executeScript(

315

"var issues = []; " +

316

"var images = document.querySelectorAll('img'); " +

317

"images.forEach(function(img, index) { " +

318

" if (!img.alt) { " +

319

" issues.push({type: 'missing-alt', element: 'img', index: index}); " +

320

" } " +

321

"}); " +

322

"var links = document.querySelectorAll('a'); " +

323

"links.forEach(function(link, index) { " +

324

" if (!link.textContent.trim() && !link.getAttribute('aria-label')) { " +

325

" issues.push({type: 'empty-link', element: 'a', index: index}); " +

326

" } " +

327

"}); " +

328

"return issues;"

329

);

330

331

// Form validation status

332

Boolean isFormValid = (Boolean) js.executeScript(

333

"var form = arguments[0]; " +

334

"return form.checkValidity();",

335

driver.findElement(By.id("myForm"))

336

);

337

338

// Get all form errors

339

List<String> formErrors = (List<String>) js.executeScript(

340

"var form = arguments[0]; " +

341

"var errors = []; " +

342

"var inputs = form.querySelectorAll('input, select, textarea'); " +

343

"inputs.forEach(function(input) { " +

344

" if (!input.checkValidity()) { " +

345

" errors.push(input.name + ': ' + input.validationMessage); " +

346

" } " +

347

"}); " +

348

"return errors;",

349

driver.findElement(By.id("myForm"))

350

);

351

```

352

353

### Advanced JavaScript Patterns

354

355

```java

356

// Custom event triggering

357

js.executeScript(

358

"var event = new CustomEvent(arguments[1], {detail: arguments[2]}); " +

359

"arguments[0].dispatchEvent(event);",

360

targetElement,

361

"customEvent",

362

Map.of("data", "test")

363

);

364

365

// Cookie manipulation

366

js.executeScript("document.cookie = arguments[0] + '=' + arguments[1] + '; path=/';", "testCookie", "testValue");

367

String cookieValue = (String) js.executeScript(

368

"return document.cookie.split('; ').find(row => row.startsWith(arguments[0] + '=')).split('=')[1];",

369

"testCookie"

370

);

371

372

// Local storage operations

373

js.executeScript("localStorage.setItem(arguments[0], arguments[1]);", "key", "value");

374

String storedValue = (String) js.executeScript("return localStorage.getItem(arguments[0]);", "key");

375

376

// Session storage operations

377

js.executeScript("sessionStorage.setItem(arguments[0], JSON.stringify(arguments[1]));", "userData", Map.of("name", "John", "age", 30));

378

Map<String, Object> userData = (Map<String, Object>) js.executeScript(

379

"return JSON.parse(sessionStorage.getItem(arguments[0]));",

380

"userData"

381

);

382

383

// Dynamic CSS injection

384

js.executeScript(

385

"var style = document.createElement('style'); " +

386

"style.textContent = arguments[0]; " +

387

"document.head.appendChild(style);",

388

".highlight { background-color: yellow; border: 2px solid red; }"

389

);

390

```

391

392

### Error Handling in JavaScript Execution

393

394

```java

395

// Safe script execution with error handling

396

public Object safeExecuteScript(JavascriptExecutor js, String script, Object... args) {

397

try {

398

return js.executeScript(

399

"try { " +

400

" return (function() { " + script + " })(); " +

401

"} catch (e) { " +

402

" return {error: e.message, stack: e.stack}; " +

403

"}",

404

args

405

);

406

} catch (Exception e) {

407

System.err.println("Script execution failed: " + e.getMessage());

408

return null;

409

}

410

}

411

412

// Check if result is an error

413

public boolean isScriptError(Object result) {

414

if (result instanceof Map) {

415

Map<String, Object> resultMap = (Map<String, Object>) result;

416

return resultMap.containsKey("error");

417

}

418

return false;

419

}

420

421

// Usage

422

Object result = safeExecuteScript(js, "return document.querySelector('#nonexistent').textContent;");

423

if (isScriptError(result)) {

424

Map<String, Object> error = (Map<String, Object>) result;

425

System.err.println("JavaScript error: " + error.get("error"));

426

} else {

427

System.out.println("Result: " + result);

428

}

429

430

// Timeout handling for async scripts

431

public Object executeAsyncScriptWithTimeout(JavascriptExecutor js, String script, Duration timeout, Object... args) {

432

// Set script timeout

433

driver.manage().timeouts().setScriptTimeout(timeout);

434

435

try {

436

return js.executeAsyncScript(script, args);

437

} catch (ScriptTimeoutException e) {

438

System.err.println("Async script timed out after " + timeout.getSeconds() + " seconds");

439

return null;

440

} finally {

441

// Reset to default timeout

442

driver.manage().timeouts().setScriptTimeout(Duration.ofSeconds(30));

443

}

444

}

445

```