or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

dotnet.mdexpression-factory.mdgo.mdindex.mdjava.mdjavascript-typescript.mdparameter-types.mdpython.mdruby.md

parameter-types.mddocs/

0

# Parameter Types

1

2

Comprehensive parameter type system enabling custom types with regex patterns, transformation functions, and intelligent matching across all language implementations.

3

4

## Capabilities

5

6

### Built-in Parameter Types

7

8

All Cucumber Expressions implementations provide consistent built-in parameter types for common data types.

9

10

**Numeric Types:**

11

12

```typescript { .api }

13

// Integer types

14

{int} // 32-bit signed integer: matches 42, -19

15

{byte} // 8-bit signed integer: matches -128 to 127

16

{short} // 16-bit signed integer: matches -32768 to 32767

17

{long} // 64-bit signed integer: matches large integers

18

{biginteger} // Arbitrary precision integer: matches any size integer

19

20

// Floating point types

21

{float} // 32-bit floating point: matches 3.6, .8, -9.2

22

{double} // 64-bit floating point: matches high precision decimals

23

{bigdecimal} // Arbitrary precision decimal: matches precise decimals

24

```

25

26

**Text Types:**

27

28

```typescript { .api }

29

{word} // Single word without whitespace: matches "banana"

30

{string} // Quoted strings: matches "banana split", 'hello world'

31

{} // Anonymous type: matches anything

32

```

33

34

**Usage Examples:**

35

36

```typescript

37

import { CucumberExpression, ParameterTypeRegistry } from '@cucumber/cucumber-expressions';

38

39

const registry = new ParameterTypeRegistry();

40

41

// Integer matching

42

const intExpr = new CucumberExpression('I have {int} items', registry);

43

console.log(intExpr.match('I have 42 items')?.[0].getValue()); // 42 (number)

44

console.log(intExpr.match('I have -10 items')?.[0].getValue()); // -10 (number)

45

46

// Float matching

47

const floatExpr = new CucumberExpression('Price is {float} dollars', registry);

48

console.log(floatExpr.match('Price is 29.99 dollars')?.[0].getValue()); // 29.99 (number)

49

console.log(floatExpr.match('Price is .50 dollars')?.[0].getValue()); // 0.5 (number)

50

51

// String matching (removes quotes)

52

const stringExpr = new CucumberExpression('I say {string}', registry);

53

console.log(stringExpr.match('I say "hello world"')?.[0].getValue()); // "hello world"

54

console.log(stringExpr.match("I say 'goodbye'")[0].getValue()); // "goodbye"

55

56

// Word matching (no whitespace)

57

const wordExpr = new CucumberExpression('I like {word}', registry);

58

console.log(wordExpr.match('I like bananas')?.[0].getValue()); // "bananas"

59

console.log(wordExpr.match('I like "banana split"')); // null (contains space)

60

61

// Anonymous matching (anything)

62

const anyExpr = new CucumberExpression('I have {} items', registry);

63

console.log(anyExpr.match('I have many items')?.[0].getValue()); // "many"

64

console.log(anyExpr.match('I have 42 red items')?.[0].getValue()); // "42 red"

65

```

66

67

### Custom Parameter Types

68

69

Define custom parameter types with regex patterns and transformation functions for domain-specific data types.

70

71

**JavaScript/TypeScript:**

72

73

```typescript { .api }

74

class ParameterType<T> {

75

constructor(

76

name: string | undefined,

77

regexps: RegExps,

78

type: Constructor<T> | Factory<T> | null,

79

transform?: (...match: string[]) => T | PromiseLike<T>,

80

useForSnippets?: boolean,

81

preferForRegexpMatch?: boolean,

82

builtin?: boolean

83

);

84

}

85

86

// Helper types

87

type RegExps = readonly (string | RegExp)[] | string | RegExp;

88

type Constructor<T> = new (...args: any[]) => T;

89

type Factory<T> = (...args: any[]) => T;

90

```

91

92

**Usage Examples:**

93

94

```typescript

95

import { ParameterType, ParameterTypeRegistry, CucumberExpression } from '@cucumber/cucumber-expressions';

96

97

// Simple enum-like parameter type

98

const colorType = new ParameterType(

99

'color',

100

/red|green|blue|yellow|purple/,

101

String,

102

(colorName: string) => colorName.toUpperCase()

103

);

104

105

// Complex parameter type with multiple capture groups

106

const dateType = new ParameterType(

107

'date',

108

/(\d{4})-(\d{2})-(\d{2})/,

109

Date,

110

(year: string, month: string, day: string) => {

111

return new Date(parseInt(year), parseInt(month) - 1, parseInt(day));

112

}

113

);

114

115

// Parameter type with object result

116

const coordinateType = new ParameterType(

117

'coordinate',

118

/\((-?\d+),\s*(-?\d+)\)/,

119

Object,

120

(x: string, y: string) => ({ x: parseInt(x), y: parseInt(y) })

121

);

122

123

// Email parameter type with validation

124

const emailType = new ParameterType(

125

'email',

126

/([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/,

127

String,

128

(email: string) => {

129

if (!email.includes('@')) {

130

throw new Error('Invalid email format');

131

}

132

return email.toLowerCase();

133

}

134

);

135

136

// Register all types

137

const registry = new ParameterTypeRegistry();

138

registry.defineParameterType(colorType);

139

registry.defineParameterType(dateType);

140

registry.defineParameterType(coordinateType);

141

registry.defineParameterType(emailType);

142

143

// Use in expressions

144

const colorExpr = new CucumberExpression('I have a {color} car', registry);

145

console.log(colorExpr.match('I have a red car')?.[0].getValue()); // "RED"

146

147

const dateExpr = new CucumberExpression('Meeting on {date}', registry);

148

const dateResult = dateExpr.match('Meeting on 2023-12-25')?.[0].getValue();

149

console.log(dateResult instanceof Date); // true

150

console.log(dateResult.getFullYear()); // 2023

151

152

const coordExpr = new CucumberExpression('Move to {coordinate}', registry);

153

console.log(coordExpr.match('Move to (10, -5)')?.[0].getValue()); // { x: 10, y: -5 }

154

155

const emailExpr = new CucumberExpression('Send to {email}', registry);

156

console.log(emailExpr.match('Send to User@Example.COM')?.[0].getValue()); // "user@example.com"

157

```

158

159

**Python:**

160

161

```python { .api }

162

class ParameterType:

163

def __init__(

164

self,

165

name: Optional[str],

166

regexp: Union[List[str], str, List[Pattern], Pattern],

167

type: type,

168

transformer: Optional[Callable] = None,

169

use_for_snippets: bool = True,

170

prefer_for_regexp_match: bool = False

171

): ...

172

```

173

174

**Usage Examples:**

175

176

```python

177

from cucumber_expressions import ParameterType, ParameterTypeRegistry, CucumberExpression

178

import re

179

from datetime import datetime

180

from dataclasses import dataclass

181

182

@dataclass

183

class Point:

184

x: int

185

y: int

186

187

# Custom parameter types

188

color_type = ParameterType(

189

name="color",

190

regexp=r"red|green|blue|yellow",

191

type=str,

192

transformer=lambda s: s.upper()

193

)

194

195

point_type = ParameterType(

196

name="point",

197

regexp=r"\((-?\d+),\s*(-?\d+)\)",

198

type=Point,

199

transformer=lambda x, y: Point(int(x), int(y))

200

)

201

202

date_type = ParameterType(

203

name="iso_date",

204

regexp=r"(\d{4})-(\d{2})-(\d{2})",

205

type=datetime,

206

transformer=lambda year, month, day: datetime(int(year), int(month), int(day))

207

)

208

209

# Register and use

210

registry = ParameterTypeRegistry()

211

registry.define_parameter_type(color_type)

212

registry.define_parameter_type(point_type)

213

registry.define_parameter_type(date_type)

214

215

# Use in expressions

216

color_expr = CucumberExpression("I have a {color} shirt", registry)

217

result = color_expr.match("I have a blue shirt")

218

print(result[0].value) # "BLUE"

219

220

point_expr = CucumberExpression("Move to {point}", registry)

221

result = point_expr.match("Move to (5, -3)")

222

print(result[0].value) # Point(x=5, y=-3)

223

```

224

225

**Java:**

226

227

```java { .api }

228

public final class ParameterType<T> implements Comparable<ParameterType<?>> {

229

public ParameterType(

230

String name,

231

List<String> regexps,

232

Class<T> type,

233

CaptureGroupTransformer<T> transformer

234

);

235

236

public ParameterType(

237

String name,

238

String regexp,

239

Class<T> type,

240

Transformer<T> transformer

241

);

242

243

// Many other constructor overloads available

244

}

245

246

@FunctionalInterface

247

public interface CaptureGroupTransformer<T> {

248

T transform(String[] args) throws Throwable;

249

}

250

251

@FunctionalInterface

252

public interface Transformer<T> {

253

T transform(String arg) throws Throwable;

254

}

255

```

256

257

**Usage Examples:**

258

259

```java

260

import io.cucumber.cucumberexpressions.*;

261

import java.time.LocalDate;

262

import java.util.Arrays;

263

264

// Custom color enum

265

enum Color {

266

RED, GREEN, BLUE, YELLOW;

267

268

public static Color fromString(String s) {

269

return valueOf(s.toUpperCase());

270

}

271

}

272

273

// Color parameter type

274

ParameterType<Color> colorType = new ParameterType<>(

275

"color",

276

"red|green|blue|yellow",

277

Color.class,

278

Color::fromString

279

);

280

281

// Date parameter type with capture groups

282

ParameterType<LocalDate> dateType = new ParameterType<>(

283

"date",

284

Arrays.asList("(\\d{4})-(\\d{2})-(\\d{2})"),

285

LocalDate.class,

286

(String[] args) -> LocalDate.of(

287

Integer.parseInt(args[0]),

288

Integer.parseInt(args[1]),

289

Integer.parseInt(args[2])

290

)

291

);

292

293

// Point class and parameter type

294

class Point {

295

final int x, y;

296

Point(int x, int y) { this.x = x; this.y = y; }

297

public String toString() { return String.format("(%d,%d)", x, y); }

298

}

299

300

ParameterType<Point> pointType = new ParameterType<>(

301

"point",

302

"\\((\\d+),(\\d+)\\)",

303

Point.class,

304

(String[] args) -> new Point(Integer.parseInt(args[0]), Integer.parseInt(args[1]))

305

);

306

307

// Register and use

308

ParameterTypeRegistry registry = new ParameterTypeRegistry();

309

registry.defineParameterType(colorType);

310

registry.defineParameterType(dateType);

311

registry.defineParameterType(pointType);

312

313

CucumberExpression colorExpr = new CucumberExpression("I have a {color} car", registry);

314

List<Argument<?>> colorArgs = colorExpr.match("I have a red car");

315

System.out.println(colorArgs.get(0).getValue()); // RED

316

317

CucumberExpression dateExpr = new CucumberExpression("Meeting on {date}", registry);

318

List<Argument<?>> dateArgs = dateExpr.match("Meeting on 2023-12-25");

319

System.out.println(dateArgs.get(0).getValue()); // 2023-12-25

320

321

CucumberExpression pointExpr = new CucumberExpression("Move to {point}", registry);

322

List<Argument<?>> pointArgs = pointExpr.match("Move to (10,5)");

323

System.out.println(pointArgs.get(0).getValue()); // (10,5)

324

```

325

326

### Parameter Type Configuration

327

328

Control parameter type behavior with configuration options.

329

330

```typescript { .api }

331

// Configuration options for parameter types

332

interface ParameterTypeOptions {

333

/**

334

* Whether to use this parameter type for snippet generation

335

* Default: true

336

*/

337

useForSnippets?: boolean;

338

339

/**

340

* Whether to prefer this parameter type for regexp matches

341

* Default: false

342

*/

343

preferForRegexpMatch?: boolean;

344

345

/**

346

* Whether this is a built-in parameter type

347

* Default: false

348

*/

349

builtin?: boolean;

350

}

351

```

352

353

**Usage Examples:**

354

355

```typescript

356

// Parameter type that won't be used for snippets

357

const internalType = new ParameterType(

358

'internal_id',

359

/INTERNAL_\d+/,

360

String,

361

(s: string) => s,

362

false, // useForSnippets = false

363

false // preferForRegexpMatch = false

364

);

365

366

// Parameter type preferred for regexp matching

367

const preferredType = new ParameterType(

368

'preferred_number',

369

/\d+/,

370

Number,

371

(s: string) => parseInt(s),

372

true, // useForSnippets = true

373

true // preferForRegexpMatch = true

374

);

375

```

376

377

### Parameter Type Registry Management

378

379

Comprehensive registry management with lookup and validation capabilities.

380

381

```typescript { .api }

382

class ParameterTypeRegistry implements DefinesParameterType {

383

/**

384

* Look up parameter type by name

385

*/

386

lookupByTypeName(typeName: string): ParameterType<unknown> | undefined;

387

388

/**

389

* Look up parameter type by regexp pattern

390

*/

391

lookupByRegexp(

392

parameterTypeRegexp: string,

393

expressionRegexp: RegExp,

394

text: string

395

): ParameterType<unknown> | undefined;

396

397

/**

398

* Define new parameter type

399

*/

400

defineParameterType(parameterType: ParameterType<unknown>): void;

401

402

/**

403

* Get all registered parameter types

404

*/

405

readonly parameterTypes: IterableIterator<ParameterType<unknown>>;

406

}

407

```

408

409

**Usage Examples:**

410

411

```typescript

412

const registry = new ParameterTypeRegistry();

413

414

// Check if parameter type exists

415

const intType = registry.lookupByTypeName('int');

416

console.log(intType?.name); // "int"

417

418

// Get all parameter types

419

for (const paramType of registry.parameterTypes) {

420

console.log(`${paramType.name}: ${paramType.regexpStrings}`);

421

}

422

423

// Define custom type and verify

424

const customType = new ParameterType('custom', /custom_\w+/, String);

425

registry.defineParameterType(customType);

426

427

const retrieved = registry.lookupByTypeName('custom');

428

console.log(retrieved === customType); // true

429

```

430

431

### Multi-Language Parameter Type Patterns

432

433

Common patterns for defining parameter types across different programming languages.

434

435

**Enum-based Types:**

436

437

```typescript

438

// TypeScript enum type

439

enum Status { ACTIVE = 'active', INACTIVE = 'inactive', PENDING = 'pending' }

440

441

const statusType = new ParameterType(

442

'status',

443

/active|inactive|pending/,

444

Status,

445

(s: string) => Status[s.toUpperCase() as keyof typeof Status]

446

);

447

```

448

449

```python

450

# Python enum type

451

from enum import Enum

452

453

class Status(Enum):

454

ACTIVE = "active"

455

INACTIVE = "inactive"

456

PENDING = "pending"

457

458

status_type = ParameterType(

459

name="status",

460

regexp=r"active|inactive|pending",

461

type=Status,

462

transformer=lambda s: Status(s.lower())

463

)

464

```

465

466

```java

467

// Java enum type

468

public enum Status {

469

ACTIVE, INACTIVE, PENDING;

470

471

public static Status fromString(String s) {

472

return valueOf(s.toUpperCase());

473

}

474

}

475

476

ParameterType<Status> statusType = new ParameterType<>(

477

"status",

478

"active|inactive|pending",

479

Status.class,

480

Status::fromString

481

);

482

```

483

484

**Complex Object Types:**

485

486

```typescript

487

// TypeScript complex object

488

interface User {

489

name: string;

490

age: number;

491

email: string;

492

}

493

494

const userType = new ParameterType(

495

'user',

496

/(\w+):(\d+):([^:]+)/,

497

Object,

498

(name: string, age: string, email: string): User => ({

499

name,

500

age: parseInt(age),

501

email

502

})

503

);

504

```

505

506

**Validation and Error Handling:**

507

508

```typescript

509

const validatedEmailType = new ParameterType(

510

'validated_email',

511

/([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/,

512

String,

513

(email: string) => {

514

if (!email.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)) {

515

throw new Error(`Invalid email format: ${email}`);

516

}

517

return email.toLowerCase();

518

}

519

);

520

```

521

522

## Advanced Parameter Type Features

523

524

### Async Transformers

525

526

Support for asynchronous transformation functions in JavaScript/TypeScript.

527

528

```typescript { .api }

529

// Async transformer example

530

const asyncUserType = new ParameterType(

531

'async_user',

532

/user_(\d+)/,

533

Object,

534

async (userId: string) => {

535

// Simulate async database lookup

536

const response = await fetch(`/api/users/${userId}`);

537

return await response.json();

538

}

539

);

540

541

// Usage with async/await

542

const expr = new CucumberExpression('Load {async_user}', registry);

543

const args = expr.match('Load user_123');

544

if (args) {

545

const user = await args[0].getValue();

546

console.log(user); // User object from API

547

}

548

```

549

550

### Multiple Regex Patterns

551

552

Support for multiple regex patterns per parameter type.

553

554

```typescript { .api }

555

// Multiple pattern support

556

const flexibleDateType = new ParameterType(

557

'flexible_date',

558

[

559

/(\d{4})-(\d{2})-(\d{2})/, // ISO format: 2023-12-25

560

/(\d{2})\/(\d{2})\/(\d{4})/, // US format: 12/25/2023

561

/(\d{2})-(\d{2})-(\d{4})/ // EU format: 25-12-2023

562

],

563

Date,

564

(...parts: string[]) => {

565

// Handle different date formats

566

if (parts[0].length === 4) {

567

// ISO format: YYYY-MM-DD

568

return new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2]));

569

} else if (parts[2].length === 4) {

570

// US or EU format based on position

571

return new Date(parseInt(parts[2]), parseInt(parts[0]) - 1, parseInt(parts[1]));

572

}

573

throw new Error('Invalid date format');

574

}

575

);

576

```

577

578

Built-in parameter types provide comprehensive coverage for common data types, while custom parameter types enable domain-specific extensions with full transformation and validation capabilities across all supported programming languages.