or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async.mdevents.mdindex.mdqueries.mdrendering.md

async.mddocs/

0

# Async Utilities

1

2

Utilities for waiting for asynchronous operations and DOM changes in Vue components.

3

4

## Capabilities

5

6

### WaitFor Function

7

8

Wait for a condition to be true by repeatedly executing a callback function until it succeeds or times out.

9

10

```typescript { .api }

11

/**

12

* Wait for a condition to be true

13

* @param callback - Function to execute repeatedly

14

* @param options - Wait configuration options

15

* @returns Promise resolving to callback return value

16

*/

17

function waitFor<T>(

18

callback: () => T | Promise<T>,

19

options?: {

20

/** Element to observe for mutations */

21

container?: Element;

22

/** Maximum time to wait in milliseconds */

23

timeout?: number;

24

/** Interval between attempts in milliseconds */

25

interval?: number;

26

/** Custom timeout error handler */

27

onTimeout?: (error: Error) => Error;

28

/** MutationObserver configuration */

29

mutationObserverOptions?: MutationObserverInit;

30

}

31

): Promise<T>;

32

```

33

34

**Usage Examples:**

35

36

```typescript

37

import { render, screen, waitFor, fireEvent } from "@testing-library/vue";

38

import AsyncComponent from "./AsyncComponent.vue";

39

40

render(AsyncComponent);

41

42

// Wait for element to appear

43

await waitFor(() => {

44

expect(screen.getByText("Loading complete")).toBeInTheDocument();

45

});

46

47

// Wait for API call to complete

48

const button = screen.getByRole("button", { name: "Load Data" });

49

await fireEvent.click(button);

50

51

await waitFor(() => {

52

expect(screen.getByText("Data loaded successfully")).toBeInTheDocument();

53

}, { timeout: 5000 });

54

55

// Wait for element to have specific attribute

56

await waitFor(() => {

57

const element = screen.getByTestId("status");

58

expect(element).toHaveAttribute("data-status", "complete");

59

});

60

```

61

62

### WaitForElementToBeRemoved Function

63

64

Wait for one or more elements to be removed from the DOM.

65

66

```typescript { .api }

67

/**

68

* Wait for element(s) to be removed from DOM

69

* @param element - Element, elements array, or callback returning elements to wait for removal

70

* @param options - Wait configuration options

71

* @returns Promise that resolves when elements are removed

72

*/

73

function waitForElementToBeRemoved<T>(

74

element: Element | Element[] | (() => Element | Element[] | null),

75

options?: {

76

/** Element to observe for mutations */

77

container?: Element;

78

/** Maximum time to wait in milliseconds */

79

timeout?: number;

80

/** Interval between attempts in milliseconds */

81

interval?: number;

82

/** Custom timeout error handler */

83

onTimeout?: (error: Error) => Error;

84

/** MutationObserver configuration */

85

mutationObserverOptions?: MutationObserverInit;

86

}

87

): Promise<void>;

88

```

89

90

**Usage Examples:**

91

92

```typescript

93

// Wait for loading spinner to disappear

94

const spinner = screen.getByTestId("loading-spinner");

95

await waitForElementToBeRemoved(spinner);

96

97

// Wait for multiple elements to be removed

98

const modals = screen.getAllByRole("dialog");

99

await waitForElementToBeRemoved(modals);

100

101

// Wait using a callback (handles cases where element might not exist initially)

102

await waitForElementToBeRemoved(() =>

103

screen.queryByText("Temporary message")

104

);

105

106

// With custom timeout

107

await waitForElementToBeRemoved(

108

screen.getByText("Processing..."),

109

{ timeout: 10000 }

110

);

111

```

112

113

## Configuration Options

114

115

### Default Configuration

116

117

```typescript { .api }

118

interface WaitForOptions {

119

/** Default container for mutation observation (document.body) */

120

container?: Element;

121

/** Default timeout in milliseconds (1000ms) */

122

timeout?: number;

123

/** Default interval between checks in milliseconds (50ms) */

124

interval?: number;

125

/** Custom error handler for timeouts */

126

onTimeout?: (error: Error) => Error;

127

/** MutationObserver options for DOM change detection */

128

mutationObserverOptions?: MutationObserverInit;

129

}

130

```

131

132

### MutationObserver Options

133

134

```typescript { .api }

135

interface MutationObserverInit {

136

/** Observe attribute changes */

137

attributes?: boolean;

138

/** List of attribute names to observe */

139

attributeFilter?: string[];

140

/** Include old attribute values in mutations */

141

attributeOldValue?: boolean;

142

/** Observe character data changes */

143

characterData?: boolean;

144

/** Include old character data in mutations */

145

characterDataOldValue?: boolean;

146

/** Observe child list changes */

147

childList?: boolean;

148

/** Observe all descendant mutations */

149

subtree?: boolean;

150

}

151

```

152

153

## Common Async Patterns

154

155

### API Loading States

156

157

```typescript

158

import { render, screen, waitFor, fireEvent } from "@testing-library/vue";

159

160

// Test loading → success flow

161

const loadButton = screen.getByRole("button", { name: "Load Data" });

162

await fireEvent.click(loadButton);

163

164

// Wait for loading to start

165

await waitFor(() => {

166

expect(screen.getByText("Loading...")).toBeInTheDocument();

167

});

168

169

// Wait for loading to finish

170

await waitForElementToBeRemoved(screen.getByText("Loading..."));

171

172

// Verify success state

173

expect(screen.getByText("Data loaded")).toBeInTheDocument();

174

```

175

176

### Form Validation

177

178

```typescript

179

// Test async form validation

180

const emailInput = screen.getByLabelText("Email");

181

const submitButton = screen.getByRole("button", { name: "Submit" });

182

183

await fireEvent.update(emailInput, "invalid-email");

184

await fireEvent.click(submitButton);

185

186

// Wait for validation error

187

await waitFor(() => {

188

expect(screen.getByText("Please enter a valid email")).toBeInTheDocument();

189

});

190

```

191

192

### Component State Changes

193

194

```typescript

195

// Test reactive state updates

196

const toggleButton = screen.getByRole("button", { name: "Toggle Theme" });

197

await fireEvent.click(toggleButton);

198

199

// Wait for theme to change

200

await waitFor(() => {

201

const root = document.documentElement;

202

expect(root).toHaveAttribute("data-theme", "dark");

203

});

204

```

205

206

### Navigation and Route Changes

207

208

```typescript

209

// Test Vue Router navigation

210

const navLink = screen.getByRole("link", { name: "About" });

211

await fireEvent.click(navLink);

212

213

// Wait for new page content

214

await waitFor(() => {

215

expect(screen.getByText("About Page")).toBeInTheDocument();

216

});

217

```

218

219

## Error Handling

220

221

### Timeout Errors

222

223

When `waitFor` times out, it throws a detailed error with the last error from the callback:

224

225

```typescript

226

try {

227

await waitFor(() => {

228

expect(screen.getByText("Never appears")).toBeInTheDocument();

229

}, { timeout: 1000 });

230

} catch (error) {

231

// Error includes timeout info and last expectation failure

232

console.log(error.message);

233

}

234

```

235

236

### Custom Error Handling

237

238

```typescript

239

await waitFor(() => {

240

expect(screen.getByText("Content")).toBeInTheDocument();

241

}, {

242

timeout: 5000,

243

onTimeout: (error) => {

244

return new Error(`Custom timeout message: ${error.message}`);

245

}

246

});

247

```

248

249

## Global Configuration

250

251

Configure default timeouts and intervals using DOM Testing Library's configure function:

252

253

```typescript { .api }

254

/**

255

* Configure global library behavior

256

* @param options - Configuration options

257

*/

258

function configure(options: {

259

/** Default timeout for async utilities in milliseconds */

260

asyncUtilTimeout?: number;

261

/** Attribute name used for getByTestId queries */

262

testIdAttribute?: string;

263

/** Whether to include hidden elements by default */

264

defaultHidden?: boolean;

265

/** CSS selector for elements to ignore */

266

defaultIgnore?: string;

267

/** Show original stack traces in errors */

268

showOriginalStackTrace?: boolean;

269

/** Enable query suggestions in error messages */

270

throwSuggestions?: boolean;

271

}): void;

272

273

/**

274

* Get current configuration

275

* @returns Current configuration object

276

*/

277

function getConfig(): {

278

asyncUtilTimeout: number;

279

testIdAttribute: string;

280

defaultHidden: boolean;

281

defaultIgnore: string;

282

showOriginalStackTrace: boolean;

283

throwSuggestions: boolean;

284

};

285

```

286

287

**Usage Examples:**

288

289

```typescript

290

import { configure } from "@testing-library/vue";

291

292

// Configure timeout for all async utilities

293

configure({

294

asyncUtilTimeout: 2000,

295

});

296

297

// Configure test ID attribute

298

configure({

299

testIdAttribute: 'data-cy',

300

});

301

302

// Enable query suggestions for better error messages

303

configure({

304

throwSuggestions: true,

305

});

306

```