or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mddom-testing.mdindex.mdmocking.md

assertions.mddocs/

0

# Assertions

1

2

Powerful assertion library based on @vitest/expect with testing-library DOM matchers and full chai compatibility. The expect function is instrumented for Storybook's addon-interactions debugging.

3

4

## Capabilities

5

6

### Expect Function

7

8

The main assertion function that supports jest-compatible API with additional testing-library matchers.

9

10

```typescript { .api }

11

/**

12

* Create an assertion for the given value

13

* @param actual - The value to assert against

14

* @param message - Optional error message

15

* @returns Assertion object with chainable matchers

16

*/

17

function expect<T>(actual: T, message?: string): Assertion<T>;

18

19

interface Expect extends AsymmetricMatchersContaining {

20

<T>(actual: T, message?: string): Assertion<T>;

21

unreachable(message?: string): Promise<never>;

22

soft<T>(actual: T, message?: string): Assertion<T>;

23

extend(expects: MatchersObject): void;

24

assertions(expected: number): Promise<void>;

25

hasAssertions(): Promise<void>;

26

anything(): any;

27

any(constructor: unknown): any;

28

getState(): MatcherState;

29

setState(state: Partial<MatcherState>): void;

30

not: AsymmetricMatchersContaining;

31

}

32

```

33

34

**Usage Examples:**

35

36

```typescript

37

import { expect, fn } from '@storybook/test';

38

39

// Basic assertions

40

expect(42).toBe(42);

41

expect('hello').toEqual('hello');

42

expect([1, 2, 3]).toContain(2);

43

44

// Mock function assertions

45

const mockFn = fn();

46

mockFn('arg1', 'arg2');

47

expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2');

48

expect(mockFn).toHaveBeenCalledOnce();

49

50

// Async assertions

51

await expect(Promise.resolve('value')).resolves.toBe('value');

52

await expect(Promise.reject('error')).rejects.toBe('error');

53

54

// DOM assertions (with testing-library matchers)

55

const button = document.createElement('button');

56

button.textContent = 'Click me';

57

button.disabled = false;

58

expect(button).toBeInTheDocument();

59

expect(button).toHaveTextContent('Click me');

60

expect(button).toBeEnabled();

61

```

62

63

### Assertion Interface

64

65

The assertion interface provides all jest-compatible matchers plus testing-library DOM matchers.

66

67

```typescript { .api }

68

interface Assertion<T> extends PromisifyObject<JestAssertion<T>>, TestingLibraryMatchers<ReturnType<ExpectStatic['stringContaining']>, Promise<void>> {

69

// Standard jest matchers

70

toBe(expected: T): Promise<void>;

71

toEqual(expected: T): Promise<void>;

72

toStrictEqual(expected: T): Promise<void>;

73

toContain(expected: any): Promise<void>;

74

toContainEqual(expected: any): Promise<void>;

75

toHaveLength(expected: number): Promise<void>;

76

toMatch(expected: string | RegExp): Promise<void>;

77

toMatchObject(expected: Record<string, any>): Promise<void>;

78

toThrow(expected?: string | RegExp | Error): Promise<void>;

79

toThrowError(expected?: string | RegExp | Error): Promise<void>;

80

81

// Mock-specific matchers

82

toHaveBeenCalled(): Promise<void>;

83

toHaveBeenCalledOnce(): Promise<void>;

84

toHaveBeenCalledTimes(expected: number): Promise<void>;

85

toHaveBeenCalledWith(...expected: any[]): Promise<void>;

86

toHaveBeenLastCalledWith(...expected: any[]): Promise<void>;

87

toHaveBeenNthCalledWith(nth: number, ...expected: any[]): Promise<void>;

88

toHaveReturned(): Promise<void>;

89

toHaveReturnedTimes(expected: number): Promise<void>;

90

toHaveReturnedWith(expected: any): Promise<void>;

91

toHaveLastReturnedWith(expected: any): Promise<void>;

92

toHaveNthReturnedWith(nth: number, expected: any): Promise<void>;

93

94

// Testing Library DOM matchers

95

toBeInTheDocument(): Promise<void>;

96

toBeVisible(): Promise<void>;

97

toBeEmptyDOMElement(): Promise<void>;

98

toBeDisabled(): Promise<void>;

99

toBeEnabled(): Promise<void>;

100

toBeInvalid(): Promise<void>;

101

toBeRequired(): Promise<void>;

102

toBeValid(): Promise<void>;

103

toBeChecked(): Promise<void>;

104

toBePartiallyChecked(): Promise<void>;

105

toHaveAccessibleDescription(expected?: string | RegExp): Promise<void>;

106

toHaveAccessibleName(expected?: string | RegExp): Promise<void>;

107

toHaveAttribute(attribute: string, expected?: string | RegExp): Promise<void>;

108

toHaveClass(...expected: string[]): Promise<void>;

109

toHaveFocus(): Promise<void>;

110

toHaveFormValues(expected: Record<string, any>): Promise<void>;

111

toHaveStyle(expected: string | Record<string, any>): Promise<void>;

112

toHaveTextContent(expected?: string | RegExp): Promise<void>;

113

toHaveValue(expected?: string | string[] | number): Promise<void>;

114

toHaveDisplayValue(expected: string | RegExp | string[] | RegExp[]): Promise<void>;

115

116

// Additional matchers

117

toSatisfy<E>(matcher: (value: E) => boolean, message?: string): Promise<void>;

118

119

// Async assertion helpers

120

resolves: Assertion<T>;

121

rejects: Assertion<T>;

122

123

// Negation

124

not: Assertion<T>;

125

}

126

```

127

128

### Soft Assertions

129

130

Create soft assertions that don't immediately fail the test but collect errors.

131

132

```typescript { .api }

133

/**

134

* Create a soft assertion that collects errors instead of immediately failing

135

* @param actual - The value to assert against

136

* @param message - Optional error message

137

* @returns Assertion object for soft testing

138

*/

139

function soft<T>(actual: T, message?: string): Assertion<T>;

140

```

141

142

**Usage Example:**

143

144

```typescript

145

import { expect } from '@storybook/test';

146

147

// Soft assertions collect errors without stopping execution

148

expect.soft(1).toBe(2); // This won't throw immediately

149

expect.soft(2).toBe(3); // This won't throw immediately

150

expect.soft(3).toBe(3); // This passes

151

152

// All collected soft assertion errors will be reported at the end

153

```

154

155

### Extending Expect

156

157

Add custom matchers to the expect function.

158

159

```typescript { .api }

160

/**

161

* Extend expect with custom matchers

162

* @param expects - Object containing custom matcher functions

163

*/

164

function extend(expects: MatchersObject): void;

165

166

interface MatchersObject {

167

[key: string]: (this: MatcherState, actual: any, ...expected: any[]) => MatcherResult;

168

}

169

170

interface MatcherResult {

171

message: () => string;

172

pass: boolean;

173

}

174

175

interface MatcherState {

176

isNot: boolean;

177

promise: string;

178

assertEquals: (actual: any, expected: any, message?: string) => void;

179

assertType: (value: any, type: string, message?: string) => void;

180

}

181

```

182

183

**Usage Example:**

184

185

```typescript

186

import { expect } from '@storybook/test';

187

188

expect.extend({

189

toBeWithinRange(received, floor, ceiling) {

190

const pass = received >= floor && received <= ceiling;

191

if (pass) {

192

return {

193

message: () => `expected ${received} not to be within range ${floor} - ${ceiling}`,

194

pass: true,

195

};

196

} else {

197

return {

198

message: () => `expected ${received} to be within range ${floor} - ${ceiling}`,

199

pass: false,

200

};

201

}

202

},

203

});

204

205

// Usage

206

expect(100).toBeWithinRange(90, 110);

207

```

208

209

### Asymmetric Matchers

210

211

Create asymmetric matchers for flexible assertions.

212

213

```typescript { .api }

214

/**

215

* Match any value of the given constructor type

216

* @param constructor - Constructor function to match against

217

* @returns Asymmetric matcher

218

*/

219

function any(constructor: unknown): any;

220

221

/**

222

* Match any truthy value

223

* @returns Asymmetric matcher

224

*/

225

function anything(): any;

226

```

227

228

**Usage Examples:**

229

230

```typescript

231

import { expect } from '@storybook/test';

232

233

// Asymmetric matchers for flexible matching

234

expect({ name: 'John', age: 30 }).toEqual({

235

name: expect.any(String),

236

age: expect.any(Number),

237

});

238

239

expect(['apple', 'banana']).toEqual([

240

expect.anything(),

241

expect.anything(),

242

]);

243

```

244

245

### Assertion Count Validation

246

247

Validate the number of assertions executed during a test.

248

249

```typescript { .api }

250

/**

251

* Expect exactly N assertions to be called during the test

252

* @param expected - Expected number of assertions

253

*/

254

function assertions(expected: number): Promise<void>;

255

256

/**

257

* Expect at least one assertion to be called during the test

258

*/

259

function hasAssertions(): Promise<void>;

260

```

261

262

**Usage Examples:**

263

264

```typescript

265

import { expect } from '@storybook/test';

266

267

export const TestStory = {

268

play: async () => {

269

expect.assertions(2); // Expect exactly 2 assertions

270

271

expect(1).toBe(1);

272

expect(2).toBe(2);

273

// Test will fail if not exactly 2 assertions are made

274

},

275

};

276

277

export const AnotherStory = {

278

play: async () => {

279

expect.hasAssertions(); // Expect at least one assertion

280

281

const condition = Math.random() > 0.5;

282

if (condition) {

283

expect(true).toBe(true);

284

}

285

// Test will fail if no assertions are made

286

},

287

};

288

```

289

290

### Unreachable Code

291

292

Mark code paths that should never be reached.

293

294

```typescript { .api }

295

/**

296

* Mark a code path as unreachable - will always fail if executed

297

* @param message - Optional error message

298

* @throws Always throws an error

299

*/

300

function unreachable(message?: string): Promise<never>;

301

```

302

303

**Usage Example:**

304

305

```typescript

306

import { expect } from '@storybook/test';

307

308

export const TestStory = {

309

play: async () => {

310

const value = 'valid';

311

312

switch (value) {

313

case 'valid':

314

expect(true).toBe(true);

315

break;

316

default:

317

expect.unreachable('Should never reach default case');

318

}

319

},

320

};

321

```