or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

event-handling.mdframework-integration.mdindex.mdjs-platform.mdjvm-platform.mdnative-platform.mdtest-discovery.md

js-platform.mddocs/

0

# JavaScript Platform Support

1

2

Lightweight JavaScript test runner with master/slave architecture for distributed test execution and inter-process communication through serialized summaries. Optimized for Scala.js compilation and browser/Node.js environments.

3

4

## Capabilities

5

6

### ZTestRunnerJS Base Class

7

8

Abstract base class for JavaScript test runners that provides common functionality for both master and slave execution modes.

9

10

```scala { .api }

11

/**

12

* Base JavaScript test runner with master/slave architecture support

13

* Provides lightweight execution optimized for JavaScript environments

14

*/

15

sealed abstract class ZTestRunnerJS(

16

val args: Array[String],

17

val remoteArgs: Array[String],

18

testClassLoader: ClassLoader,

19

runnerType: String

20

) extends Runner {

21

/** Abstract method for summary handling strategy */

22

def sendSummary: SendSummary

23

24

/** Mutable buffer for collecting test summaries */

25

val summaries: mutable.Buffer[Summary]

26

27

/**

28

* Create test tasks from discovered test definitions

29

* @param defs Array of SBT task definitions

30

* @return Array of executable JavaScript test tasks

31

*/

32

def tasks(defs: Array[TaskDef]): Array[Task]

33

34

/**

35

* Complete test execution and return formatted results

36

* @return Formatted test results or "No tests executed" message

37

*/

38

def done(): String

39

40

/**

41

* Receive serialized summaries from distributed execution

42

* @param summary Serialized summary string from SummaryProtocol

43

* @return Optional response message (always None for JS)

44

*/

45

override def receiveMessage(summary: String): Option[String]

46

47

/**

48

* Serialize task for distributed execution

49

* @param task Task to serialize

50

* @param serializer SBT-provided serialization function

51

* @return Serialized task string

52

*/

53

override def serializeTask(task: Task, serializer: TaskDef => String): String

54

55

/**

56

* Deserialize task from distributed execution

57

* @param task Serialized task string

58

* @param deserializer SBT-provided deserialization function

59

* @return Reconstructed test task

60

*/

61

override def deserializeTask(task: String, deserializer: String => TaskDef): Task

62

}

63

```

64

65

### ZMasterTestRunnerJS

66

67

Master runner for single-process JavaScript execution, typically used when running tests in a single JavaScript context.

68

69

```scala { .api }

70

/**

71

* Master JavaScript test runner for single-process execution

72

* Collects summaries directly without inter-process communication

73

*/

74

final class ZMasterTestRunnerJS(

75

args: Array[String],

76

remoteArgs: Array[String],

77

testClassLoader: ClassLoader

78

) extends ZTestRunnerJS(args, remoteArgs, testClassLoader, "master") {

79

/**

80

* Summary sender that collects results locally

81

* Used when all tests run in the same JavaScript context

82

*/

83

override val sendSummary: SendSummary

84

}

85

```

86

87

### ZSlaveTestRunnerJS

88

89

Slave runner for distributed JavaScript execution, used when tests are executed across multiple JavaScript contexts or processes.

90

91

```scala { .api }

92

/**

93

* Slave JavaScript test runner for distributed execution

94

* Sends summaries to master process via serialization protocol

95

*/

96

final class ZSlaveTestRunnerJS(

97

args: Array[String],

98

remoteArgs: Array[String],

99

testClassLoader: ClassLoader,

100

val sendSummary: SendSummary

101

) extends ZTestRunnerJS(args, remoteArgs, testClassLoader, "slave")

102

```

103

104

### ZTestTask (JavaScript)

105

106

JavaScript-specific test task implementation with asynchronous execution support.

107

108

```scala { .api }

109

/**

110

* JavaScript-specific test task with async execution

111

* Optimized for JavaScript event loop and browser/Node.js environments

112

*/

113

sealed class ZTestTask(

114

taskDef: TaskDef,

115

testClassLoader: ClassLoader,

116

runnerType: String,

117

sendSummary: SendSummary,

118

testArgs: TestArgs,

119

spec: ZIOSpecAbstract

120

) extends BaseTestTask(

121

taskDef, testClassLoader, sendSummary, testArgs, spec,

122

Runtime.default, zio.Console.ConsoleLive

123

) {

124

/**

125

* Execute test with async continuation support

126

* Required for JavaScript's asynchronous execution model

127

* @param eventHandler SBT event handler for reporting

128

* @param loggers Array of SBT loggers

129

* @param continuation Continuation function called when execution completes

130

*/

131

def execute(eventHandler: EventHandler, loggers: Array[Logger], continuation: Array[Task] => Unit): Unit

132

}

133

```

134

135

### ZTestTask Companion Object (JavaScript)

136

137

Factory methods for creating JavaScript test tasks.

138

139

```scala { .api }

140

object ZTestTask {

141

/**

142

* Create a JavaScript test task instance

143

* @param taskDef SBT task definition

144

* @param testClassLoader ClassLoader for loading test classes

145

* @param runnerType Runner type identifier ("master" or "slave")

146

* @param sendSummary Summary collection effect

147

* @param args Parsed test arguments

148

* @return Configured JavaScript ZTestTask instance

149

*/

150

def apply(

151

taskDef: TaskDef,

152

testClassLoader: ClassLoader,

153

runnerType: String,

154

sendSummary: SendSummary,

155

args: TestArgs

156

): ZTestTask

157

}

158

```

159

160

### SummaryProtocol

161

162

Serialization protocol for inter-process communication in distributed JavaScript execution.

163

164

```scala { .api }

165

/**

166

* Serialization protocol for test summaries in JavaScript environments

167

* Enables communication between master and slave processes

168

*/

169

object SummaryProtocol {

170

/**

171

* Serialize test summary to string for transmission

172

* @param summary Test execution summary to serialize

173

* @return Tab-separated string representation

174

*/

175

def serialize(summary: Summary): String

176

177

/**

178

* Deserialize string back to test summary

179

* @param s Serialized summary string

180

* @return Optional Summary if deserialization succeeds

181

*/

182

def deserialize(s: String): Option[Summary]

183

184

/**

185

* Escape tab characters in tokens for serialization

186

* @param token String token to escape

187

* @return Escaped string safe for tab-separated format

188

*/

189

def escape(token: String): String

190

191

/**

192

* Unescape tab characters from serialized tokens

193

* @param token Escaped string token

194

* @return Unescaped original string

195

*/

196

def unescape(token: String): String

197

}

198

```

199

200

### Asynchronous Execution

201

202

JavaScript test tasks use asynchronous execution with continuations:

203

204

```scala { .api }

205

def execute(eventHandler: EventHandler, loggers: Array[Logger], continuation: Array[Task] => Unit): Unit = {

206

// Fork execution on default runtime

207

val fiber = Runtime.default.unsafe.fork {

208

val logic = ZIO.consoleWith { console =>

209

(for {

210

summary <- spec.runSpecAsApp(FilteredSpec(spec.spec, args), args, console)

211

_ <- sendSummary.provide(ZLayer.succeed(summary))

212

_ <- ZIO.when(summary.status == Summary.Failure) {

213

ZIO.attempt(eventHandler.handle(ZTestEvent(/* failure event */)))

214

}

215

} yield ()).provideLayer(sharedFilledTestLayer +!+ (Scope.default >>> spec.bootstrap))

216

}

217

logic

218

}

219

220

// Add observer for completion handling

221

fiber.unsafe.addObserver { exit =>

222

exit match {

223

case Exit.Failure(cause) => Console.err.println(s"$runnerType failed. $cause")

224

case _ =>

225

}

226

continuation(Array())

227

}

228

}

229

```

230

231

### Master/Slave Architecture

232

233

**Master Process Flow:**

234

1. Receives test definitions from SBT

235

2. Creates test tasks for local execution

236

3. Collects summaries directly in local buffer

237

4. Aggregates results and reports to SBT

238

239

**Slave Process Flow:**

240

1. Receives serialized tasks from master

241

2. Executes tests in isolated JavaScript context

242

3. Serializes summaries using `SummaryProtocol`

243

4. Sends results back to master via `send` function

244

245

### Platform Optimizations

246

247

JavaScript platform provides several optimizations:

248

249

- **Lightweight Runtime**: Uses default ZIO runtime without heavy JVM features

250

- **Async Execution**: Leverages JavaScript event loop for non-blocking execution

251

- **Serialization Protocol**: Efficient string-based communication for distributed execution

252

- **Browser Compatibility**: Works in both Node.js and browser environments

253

- **Small Bundle Size**: Minimal overhead for Scala.js compilation

254

255

### Usage Example

256

257

```scala

258

// Framework automatically creates appropriate runner type

259

val framework = new ZTestFramework()

260

261

// For single-process execution

262

val masterRunner = framework.runner(args, remoteArgs, classLoader)

263

264

// For distributed execution

265

val slaveRunner = framework.slaveRunner(args, remoteArgs, classLoader, summaryCallback)

266

267

// SBT handles task serialization/deserialization automatically

268

val serializedTask = masterRunner.serializeTask(task, serializer)

269

val deserializedTask = slaveRunner.deserializeTask(serializedTask, deserializer)

270

```