or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdbrowser-automation.mdconfiguration.mdindex.mdreporting.mdtest-framework.md

test-framework.mddocs/

0

# Test Framework Core

1

2

Essential test declaration, organization, and lifecycle management functions for structuring robust test suites with built-in fixtures and configuration options.

3

4

## Capabilities

5

6

### Test Declaration

7

8

Main function for declaring individual test cases with automatic fixture injection.

9

10

```typescript { .api }

11

/**

12

* Declares a test case with built-in fixtures

13

* @param title - Descriptive name for the test

14

* @param testFunction - Async function containing test logic with fixture parameters

15

*/

16

function test(

17

title: string,

18

testFunction: (fixtures: PlaywrightTestArgs & PlaywrightTestOptions) => Promise<void>

19

): void;

20

21

/**

22

* Declares a test case with additional metadata

23

* @param title - Descriptive name for the test

24

* @param details - Test annotations and configuration

25

* @param testFunction - Async function containing test logic

26

*/

27

function test(

28

title: string,

29

details: { tag?: string | string[]; annotation?: { type: string; description?: string }[] },

30

testFunction: (fixtures: PlaywrightTestArgs & PlaywrightTestOptions) => Promise<void>

31

): void;

32

```

33

34

**Usage Examples:**

35

36

```typescript

37

import { test, expect } from "@playwright/test";

38

39

// Basic test

40

test("should load homepage", async ({ page }) => {

41

await page.goto("/");

42

await expect(page.locator("h1")).toBeVisible();

43

});

44

45

// Test with metadata

46

test("should handle user login",

47

{ tag: ["@auth", "@critical"] },

48

async ({ page }) => {

49

await page.goto("/login");

50

// test logic

51

}

52

);

53

```

54

55

### Test Modifiers

56

57

Functions for controlling test execution behavior and marking test states.

58

59

```typescript { .api }

60

/**

61

* Focuses execution on specific tests only

62

* @param title - Test title

63

* @param testFunction - Test implementation

64

*/

65

test.only(title: string, testFunction: (fixtures: PlaywrightTestArgs) => Promise<void>): void;

66

67

/**

68

* Skips test execution conditionally or unconditionally

69

* @param title - Test title

70

* @param testFunction - Test implementation

71

*/

72

test.skip(title: string, testFunction: (fixtures: PlaywrightTestArgs) => Promise<void>): void;

73

74

/**

75

* Marks test as needing fixes (skip with TODO marker)

76

* @param title - Test title

77

* @param testFunction - Test implementation

78

*/

79

test.fixme(title: string, testFunction: (fixtures: PlaywrightTestArgs) => Promise<void>): void;

80

81

/**

82

* Marks test as slow running (triples timeout)

83

* @param title - Test title

84

* @param testFunction - Test implementation

85

*/

86

test.slow(title: string, testFunction: (fixtures: PlaywrightTestArgs) => Promise<void>): void;

87

88

/**

89

* Marks test as expected to fail

90

* @param title - Test title

91

* @param testFunction - Test implementation

92

*/

93

test.fail(title: string, testFunction: (fixtures: PlaywrightTestArgs) => Promise<void>): void;

94

```

95

96

**Usage Examples:**

97

98

```typescript

99

// Focus on specific test during development

100

test.only("debug this specific test", async ({ page }) => {

101

// This is the only test that will run

102

});

103

104

// Skip test conditionally

105

test.skip("skip on mobile", async ({ page, isMobile }) => {

106

test.skip(isMobile, "Feature not supported on mobile");

107

// test logic

108

});

109

110

// Mark as needing attention

111

test.fixme("fix broken authentication", async ({ page }) => {

112

// This test will be skipped until fixed

113

});

114

```

115

116

### Test Organization

117

118

Functions for grouping and organizing tests into logical suites.

119

120

```typescript { .api }

121

/**

122

* Groups related tests into a describe block

123

* @param title - Suite description

124

* @param callback - Function containing test declarations

125

*/

126

test.describe(title: string, callback: () => void): void;

127

128

/**

129

* Focus execution on entire test suite

130

* @param title - Suite description

131

* @param callback - Function containing test declarations

132

*/

133

test.describe.only(title: string, callback: () => void): void;

134

135

/**

136

* Skip entire test suite

137

* @param title - Suite description

138

* @param callback - Function containing test declarations

139

*/

140

test.describe.skip(title: string, callback: () => void): void;

141

142

/**

143

* Mark entire suite as needing fixes

144

* @param title - Suite description

145

* @param callback - Function containing test declarations

146

*/

147

test.describe.fixme(title: string, callback: () => void): void;

148

149

/**

150

* Run tests in suite serially (one after another)

151

* @param title - Suite description

152

* @param callback - Function containing test declarations

153

*/

154

test.describe.serial(title: string, callback: () => void): void;

155

156

/**

157

* Run tests in suite in parallel (default behavior)

158

* @param title - Suite description

159

* @param callback - Function containing test declarations

160

*/

161

test.describe.parallel(title: string, callback: () => void): void;

162

163

/**

164

* Configure suite-specific execution options

165

* @param options - Suite configuration options

166

*/

167

test.describe.configure(options: {

168

mode?: 'default' | 'parallel' | 'serial';

169

retries?: number;

170

timeout?: number;

171

}): void;

172

```

173

174

**Usage Examples:**

175

176

```typescript

177

test.describe("User Authentication", () => {

178

test.beforeEach(async ({ page }) => {

179

await page.goto("/login");

180

});

181

182

test("successful login", async ({ page }) => {

183

// test logic

184

});

185

186

test("failed login", async ({ page }) => {

187

// test logic

188

});

189

});

190

191

// Configure serial execution for dependent tests

192

test.describe.serial("Database Migration", () => {

193

test.describe.configure({ mode: 'serial' });

194

195

test("run migration", async ({ page }) => {

196

// must run first

197

});

198

199

test("verify migration", async ({ page }) => {

200

// depends on previous test

201

});

202

});

203

```

204

205

### Lifecycle Hooks

206

207

Functions for setup and teardown operations before and after tests.

208

209

```typescript { .api }

210

/**

211

* Runs before each test in the current suite

212

* @param hookFunction - Setup function with test fixtures

213

*/

214

test.beforeEach(hookFunction: (fixtures: PlaywrightTestArgs) => Promise<void>): void;

215

216

/**

217

* Runs after each test in the current suite

218

* @param hookFunction - Teardown function with test fixtures

219

*/

220

test.afterEach(hookFunction: (fixtures: PlaywrightTestArgs) => Promise<void>): void;

221

222

/**

223

* Runs once before all tests in the worker

224

* @param hookFunction - Setup function with worker fixtures

225

*/

226

test.beforeAll(hookFunction: (fixtures: PlaywrightWorkerArgs) => Promise<void>): void;

227

228

/**

229

* Runs once after all tests in the worker

230

* @param hookFunction - Teardown function with worker fixtures

231

*/

232

test.afterAll(hookFunction: (fixtures: PlaywrightWorkerArgs) => Promise<void>): void;

233

```

234

235

**Usage Examples:**

236

237

```typescript

238

test.describe("Shopping Cart", () => {

239

test.beforeEach(async ({ page }) => {

240

await page.goto("/shop");

241

await page.click("[data-testid='add-to-cart']");

242

});

243

244

test.afterEach(async ({ page }) => {

245

await page.click("[data-testid='clear-cart']");

246

});

247

248

test("view cart items", async ({ page }) => {

249

await page.click("[data-testid='view-cart']");

250

// test logic

251

});

252

});

253

254

test.beforeAll(async ({ browser }) => {

255

// Setup shared resources across all tests

256

console.log(`Testing with ${browser.browserType().name()}`);

257

});

258

```

259

260

### Test Enhancement

261

262

Advanced functions for extending test capabilities and accessing test metadata.

263

264

```typescript { .api }

265

/**

266

* Extends test with custom fixtures

267

* @param fixtures - Custom fixture definitions

268

* @returns Extended test function with additional fixtures

269

*/

270

test.extend<T, W>(fixtures: Fixtures<T, W>): TestType<PlaywrightTestArgs & T, PlaywrightWorkerArgs & W>;

271

272

/**

273

* Sets default options for tests in current suite

274

* @param options - Default test configuration options

275

*/

276

test.use(options: PlaywrightTestOptions): void;

277

278

/**

279

* Creates hierarchical test steps for better reporting

280

* @param title - Step description

281

* @param body - Step implementation

282

* @returns Promise resolving to step result

283

*/

284

test.step<T>(title: string, body: () => Promise<T>): Promise<T>;

285

286

/**

287

* Access current test information and metadata

288

* @returns Test information object

289

*/

290

test.info(): TestInfo;

291

```

292

293

**Usage Examples:**

294

295

```typescript

296

// Extend test with custom fixtures

297

const testWithDB = test.extend<{ db: Database }>({

298

db: async ({}, use) => {

299

const db = await connectToDatabase();

300

await use(db);

301

await db.close();

302

},

303

});

304

305

testWithDB("user can save data", async ({ page, db }) => {

306

// Use both page and db fixtures

307

});

308

309

// Configure default options

310

test.use({

311

viewport: { width: 1280, height: 720 },

312

ignoreHTTPSErrors: true

313

});

314

315

// Create test steps

316

test("multi-step checkout", async ({ page }) => {

317

await test.step("add items to cart", async () => {

318

await page.click("[data-testid='add-to-cart']");

319

});

320

321

await test.step("proceed to checkout", async () => {

322

await page.click("[data-testid='checkout']");

323

});

324

325

await test.step("complete payment", async () => {

326

await page.fill("#card-number", "4242424242424242");

327

await page.click("#submit-payment");

328

});

329

});

330

331

// Access test information

332

test("get test metadata", async ({ page }) => {

333

const info = test.info();

334

console.log(`Running test: ${info.title} in ${info.file}`);

335

});

336

```

337

338

## Core Types

339

340

### Test Function Type

341

342

```typescript { .api }

343

interface TestType<TestArgs, WorkerArgs> {

344

(title: string, testFunction: (args: TestArgs) => Promise<void>): void;

345

(title: string, details: TestDetails, testFunction: (args: TestArgs) => Promise<void>): void;

346

347

only: (title: string, testFunction: (args: TestArgs) => Promise<void>) => void;

348

skip: (title: string, testFunction: (args: TestArgs) => Promise<void>) => void;

349

fixme: (title: string, testFunction: (args: TestArgs) => Promise<void>) => void;

350

slow: (title: string, testFunction: (args: TestArgs) => Promise<void>) => void;

351

fail: (title: string, testFunction: (args: TestArgs) => Promise<void>) => void;

352

353

describe: DescribeFunction;

354

beforeEach: (hookFunction: (args: TestArgs) => Promise<void>) => void;

355

afterEach: (hookFunction: (args: TestArgs) => Promise<void>) => void;

356

beforeAll: (hookFunction: (args: WorkerArgs) => Promise<void>) => void;

357

afterAll: (hookFunction: (args: WorkerArgs) => Promise<void>) => void;

358

359

extend<T, W>(fixtures: Fixtures<T, W>): TestType<TestArgs & T, WorkerArgs & W>;

360

use: (options: TestOptions) => void;

361

step<T>(title: string, body: () => Promise<T>): Promise<T>;

362

info(): TestInfo;

363

}

364

```

365

366

### Test Details and Metadata

367

368

```typescript { .api }

369

interface TestDetails {

370

tag?: string | string[];

371

annotation?: TestAnnotation[];

372

}

373

374

interface TestAnnotation {

375

type: string;

376

description?: string;

377

}

378

379

interface TestInfo {

380

title: string;

381

file: string;

382

line: number;

383

column: number;

384

status?: TestStatus;

385

duration: number;

386

errors: TestError[];

387

attachments: Attachment[];

388

annotations: TestAnnotation[];

389

expectedStatus: TestStatus;

390

timeout: number;

391

project: TestProject;

392

}

393

394

type TestStatus = 'passed' | 'failed' | 'timedOut' | 'skipped' | 'interrupted';

395

```

396

397

### Fixture System

398

399

```typescript { .api }

400

type Fixtures<T, W> = {

401

[K in keyof T]: FixtureFunction<T[K], T, W>;

402

} & {

403

[K in keyof W]: WorkerFixtureFunction<W[K], T, W>;

404

};

405

406

type FixtureFunction<R, T, W> = (

407

args: T & W,

408

use: (r: R) => Promise<void>

409

) => Promise<void>;

410

411

type WorkerFixtureFunction<R, T, W> = (

412

args: W,

413

use: (r: R) => Promise<void>,

414

workerInfo: WorkerInfo

415

) => Promise<void>;

416

417

/**

418

* Enhanced fixture type definitions for precise fixture typing

419

*/

420

type TestFixture<R, Args extends {}> = (

421

args: Args,

422

use: (r: R) => Promise<void>,

423

testInfo: TestInfo

424

) => any;

425

426

type WorkerFixture<R, Args extends {}> = (

427

args: Args,

428

use: (r: R) => Promise<void>,

429

workerInfo: WorkerInfo

430

) => any;

431

432

type TestBody<Args> = (args: Args, testInfo: TestInfo) => Promise<void> | void;

433

type ConditionBody<Args> = (args: Args) => boolean | Promise<boolean>;

434

```