or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

capabilities.mdframeworks.mdindex.mdnetwork.mdoptions.mdreporters.mdservices.mdworkers.md

reporters.mddocs/

0

# Reporters

1

2

Test result reporting configuration with output formatting, custom reporter support, and flexible logging options for WebdriverIO test execution.

3

4

## Capabilities

5

6

### Reporter Configuration

7

8

Core reporter configuration options for output formatting and logging.

9

10

```typescript { .api }

11

/**

12

* Reporter configuration options

13

*/

14

interface Options {

15

/** Output directory for reporter files */

16

outputDir?: string;

17

/** Complete path of the reporter log file */

18

logFile?: string;

19

/** Define filename format for reporter log files */

20

outputFileFormat?: (options: OutputFileFormatOptions) => string;

21

/** Set complete path for reporter's log output */

22

setLogFile?: (cid: string, name: string) => string;

23

/** Output to stdout instead of file */

24

stdout?: boolean;

25

/** Write to custom stream instead of file */

26

writeStream?: WriteStream | {

27

write: (content: unknown) => boolean;

28

};

29

/** Allow additional options from 3rd party reporters */

30

[key: string]: unknown;

31

}

32

33

/**

34

* Options for output file format function

35

*/

36

interface OutputFileFormatOptions {

37

/** Capability ID */

38

cid: string;

39

/** Test capabilities */

40

capabilities: RequestedStandaloneCapabilities | RequestedMultiremoteCapabilities;

41

}

42

```

43

44

### Reporter Instance Interface

45

46

Reporter instance interface extending Node.js EventEmitter.

47

48

```typescript { .api }

49

/**

50

* Reporter instance interface

51

*/

52

interface ReporterInstance extends EventEmitter {

53

/** Whether reporter has finished processing all events */

54

isSynchronised: boolean;

55

}

56

57

/**

58

* Reporter class constructor

59

*/

60

interface ReporterClass {

61

new(options: Partial<Options>): ReporterInstance;

62

}

63

```

64

65

### Reporter Entry Types

66

67

Different ways to configure reporters in WebdriverIO.

68

69

```typescript { .api }

70

/**

71

* Reporter configuration options

72

*/

73

type ReporterEntry =

74

/** Reporter name as string */

75

| string

76

/** Reporter class */

77

| ReporterClass

78

/** Reporter name with options */

79

| [string, WebdriverIO.ReporterOption]

80

/** Reporter class with options */

81

| [ReporterClass, WebdriverIO.ReporterOption];

82

```

83

84

### File System Integration

85

86

WriteStream interface for custom output destinations.

87

88

```typescript { .api }

89

import type { WriteStream } from 'node:fs';

90

91

/**

92

* Custom write stream interface

93

*/

94

interface CustomWriteStream {

95

/** Write content to stream */

96

write: (content: unknown) => boolean;

97

}

98

```

99

100

**Usage Examples:**

101

102

```typescript

103

import type { Reporters } from "@wdio/types";

104

import { EventEmitter } from "node:events";

105

import { createWriteStream } from "node:fs";

106

107

// Custom reporter implementation

108

class CustomJSONReporter extends EventEmitter implements Reporters.ReporterInstance {

109

private results: any[] = [];

110

private outputFile: string;

111

public isSynchronised: boolean = true;

112

113

constructor(private options: Partial<Reporters.Options>) {

114

super();

115

this.outputFile = options.logFile || 'test-results.json';

116

117

this.on('test:start', this.onTestStart.bind(this));

118

this.on('test:end', this.onTestEnd.bind(this));

119

this.on('runner:end', this.onRunnerEnd.bind(this));

120

}

121

122

onTestStart(test: any) {

123

console.log(`Starting test: ${test.fullTitle}`);

124

}

125

126

onTestEnd(test: any) {

127

this.results.push({

128

title: test.fullTitle,

129

state: test.state,

130

duration: test.duration,

131

error: test.error

132

});

133

}

134

135

onRunnerEnd() {

136

const fs = require('fs');

137

fs.writeFileSync(this.outputFile, JSON.stringify(this.results, null, 2));

138

console.log(`Results written to ${this.outputFile}`);

139

}

140

}

141

142

// Reporter configuration examples

143

const reporterConfigs: Reporters.ReporterEntry[] = [

144

// Built-in reporter by name

145

'spec',

146

147

// Built-in reporter with options

148

['allure', {

149

outputDir: './allure-results',

150

disableWebdriverStepsReporting: true

151

}],

152

153

// Custom reporter class

154

CustomJSONReporter,

155

156

// Custom reporter class with options

157

[CustomJSONReporter, {

158

logFile: './custom-results.json',

159

outputDir: './reports'

160

}],

161

162

// JSON reporter with custom formatting

163

['json', {

164

outputDir: './json-reports',

165

outputFileFormat: (options) => {

166

const { cid, capabilities } = options;

167

const browserName = capabilities.browserName || 'unknown';

168

return `results-${cid}-${browserName}.json`;

169

}

170

}],

171

172

// Spec reporter to stdout

173

['spec', {

174

stdout: true

175

}],

176

177

// Custom write stream

178

['spec', {

179

writeStream: createWriteStream('./test-output.log')

180

}]

181

];

182

183

// Advanced reporter with custom output formatting

184

class AdvancedReporter extends EventEmitter implements Reporters.ReporterInstance {

185

public isSynchronised: boolean = true;

186

private writeStream?: Reporters.Options['writeStream'];

187

188

constructor(private options: Partial<Reporters.Options>) {

189

super();

190

191

// Configure output destination

192

if (options.writeStream) {

193

this.writeStream = options.writeStream;

194

} else if (options.stdout) {

195

this.writeStream = { write: (content) => { console.log(content); return true; } };

196

} else if (options.logFile) {

197

this.writeStream = createWriteStream(options.logFile);

198

}

199

200

this.setupEventHandlers();

201

}

202

203

private setupEventHandlers() {

204

this.on('runner:start', (runner) => {

205

this.write(`Starting tests for ${runner.cid}\n`);

206

});

207

208

this.on('suite:start', (suite) => {

209

this.write(`Suite: ${suite.title}\n`);

210

});

211

212

this.on('test:end', (test) => {

213

const status = test.passed ? 'PASS' : 'FAIL';

214

const duration = test.duration ? `(${test.duration}ms)` : '';

215

this.write(` ${status}: ${test.title} ${duration}\n`);

216

217

if (!test.passed && test.error) {

218

this.write(` Error: ${test.error.message}\n`);

219

}

220

});

221

222

this.on('runner:end', (runner) => {

223

this.write(`Finished tests for ${runner.cid}\n`);

224

});

225

}

226

227

private write(content: string) {

228

if (this.writeStream && 'write' in this.writeStream) {

229

this.writeStream.write(content);

230

}

231

}

232

}

233

234

// Global namespace extension for custom reporter options

235

declare global {

236

namespace WebdriverIO {

237

interface ReporterOption extends Reporters.Options {

238

// Custom reporter-specific options can be added here

239

customOption?: boolean;

240

customFormatter?: (data: any) => string;

241

}

242

}

243

}

244

```