Q9 of 40 · Karate

How does Karate's embedded JavaScript work? Give a real example.

KarateMidkaratejavascriptembedded-jsjava-interoputilities

Short answer

Short answer: Any expression inside karate.call('classpath:script.js') or a * def using a JS expression runs in a Nashorn/GraalVM JavaScript context. Karate variables are accessible inside, and the return value becomes the Karate variable. Use it for logic that's hard in the DSL: date arithmetic, random data generation, string manipulation.

Detail

Karate embeds a JavaScript engine (Nashorn in JDK < 15, GraalJS in newer versions). You can:

1. Inline JS expressions:

* def uuid = function() { return java.util.UUID.randomUUID() + '' }
* def requestId = uuid()

2. Multi-line JS functions:

* def addDays =
  """
  function(date, n) {
    var d = new java.util.Date(date);
    d.setDate(d.getDate() + n);
    return d.toISOString().split('T')[0];
  }
  """
* def tomorrow = addDays(new Date(), 1)

3. Call a .js file — for reusable logic:

* def utils = read('classpath:helpers/utils.js')
* def uniqueEmail = utils.generateEmail('alice')

Java interop: Karate JS can instantiate Java classes directly (new java.util.Date(), java.util.UUID.randomUUID()) — this is powerful but ties your tests to the JVM environment.

Nashorn vs GraalJS: load() and some browser APIs differ between engines. For portability, stick to ECMAScript 5 syntax and Java class calls.

// EXAMPLE

utils.js (helpers/utils.js)

// helpers/utils.js — reusable JS utility functions
function generateEmail(prefix) {
  var uuid = java.util.UUID.randomUUID().toString().substring(0, 8);
  return prefix + '-' + uuid + '@test.example.com';
}

function futureDate(daysAhead) {
  var d = new java.util.Date();
  d.setDate(d.getDate() + daysAhead);
  return d.toISOString().split('T')[0];  // YYYY-MM-DD
}

function randomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

// Return an object so the caller accesses utils.generateEmail()
{ generateEmail: generateEmail, futureDate: futureDate, randomInt: randomInt }

// WHAT INTERVIEWERS LOOK FOR

Knowing where JS runs (embedded engine, not browser), Java interop via new java.util.UUID, and extracting logic to .js files rather than inlining long functions. The Nashorn vs GraalJS compatibility note is a sign of hands-on experience.

// COMMON PITFALL

Writing 30-line JavaScript blocks inline in feature files. Long JS in feature files is unreadable and untestable. Extract to a .js file in helpers/ — it can be unit-tested independently and reused across features.