twd-js 1.0.1 โ†’ 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,31 +12,7 @@
12
12
 
13
13
  TWD (Testing Web Development) is a library designed to seamlessly integrate testing into your web development workflow. It streamlines the process of writing, running, and managing tests directly in your application, with a modern UI and powerful mocking capabilities.
14
14
 
15
- Currently, TWD supports React, with plans to add more frameworks soon.
16
-
17
- **For complete and updated documentation, tutorials, and examples, visit: [https://brikev.github.io/twd/](https://brikev.github.io/twd/)**
18
-
19
- ## Table of Contents
20
-
21
- - [Features](#features)
22
- - [Installation](#installation)
23
- - [Quick Start](#quick-start)
24
- - [Writing Tests](#writing-tests)
25
- - [Test Structure](#test-structure)
26
- - [Element Selection](#element-selection)
27
- - [Assertions](#assertions)
28
- - [User Interactions](#user-interactions)
29
- - [API Mocking](#api-mocking)
30
- - [Setup](#setup)
31
- - [Mock Requests](#mock-requests)
32
- - [Wait for Requests](#wait-for-requests)
33
- - [API Reference](#api-reference)
34
- - [Test Functions](#test-functions)
35
- - [TWD Commands](#twd-commands)
36
- - [Assertions](#assertions-1)
37
- - [Examples](#examples)
38
- - [Contributing](#contributing)
39
- - [License](#license)
15
+ **๐Ÿ“– [Full Documentation](https://brikev.github.io/twd/) | ๐Ÿš€ [Getting Started](https://brikev.github.io/twd/getting-started) | ๐Ÿ“š [API Reference](https://brikev.github.io/twd/api/)**
40
16
 
41
17
  ## Features
42
18
 
@@ -45,440 +21,131 @@ Currently, TWD supports React, with plans to add more frameworks soon.
45
21
  - ๐Ÿ”ฅ **Mock Service Worker** integration for API/request mocking
46
22
  - ๐Ÿ“ **Simple, readable test syntax** (inspired by popular test frameworks)
47
23
  - ๐Ÿงฉ **Automatic test discovery** with Vite support
24
+ - ๐ŸŽฏ **Testing Library support** - Use `screenDom` for semantic, accessible queries
48
25
  - ๐Ÿ› ๏ธ **Works with React** (support for more frameworks coming)
49
26
 
50
27
  ## Installation
51
28
 
52
- You can install TWD via npm:
53
-
54
29
  ```bash
55
- # with npm
56
30
  npm install twd-js
57
-
58
- # with yarn
31
+ # or
59
32
  yarn add twd-js
60
-
61
- # with pnpm
33
+ # or
62
34
  pnpm add twd-js
63
35
  ```
64
36
 
65
37
  ## Quick Start
66
38
 
67
- 1. **Add the TWD Sidebar to your React app:**
68
-
69
- ```tsx
70
- import { StrictMode } from "react";
71
- import { createRoot } from "react-dom/client";
72
- import App from "./App";
73
- import "./index.css";
74
-
75
- // Only load the test sidebar and tests in development mode
76
- if (import.meta.env.DEV) {
77
- // Use Vite's glob import to find all test files
78
- const testModules = import.meta.glob("./**/*.twd.test.ts");
79
- const { initTests, twd, TWDSidebar } = await import('twd-js');
80
- // You need to pass the test modules, the sidebar component, and createRoot function
81
- initTests(testModules, <TWDSidebar open={true} position="left" />, createRoot);
82
- // if you want to use mock requests, you can initialize it here
83
- twd.initRequestMocking()
84
- .then(() => {
85
- console.log("Request mocking initialized");
86
- })
87
- .catch((err) => {
88
- console.error("Error initializing request mocking:", err);
89
- });
90
- }
91
-
92
- createRoot(document.getElementById("root")!).render(
93
- <StrictMode>
94
- <App />
95
- </StrictMode>
96
- );
97
- ```
98
-
99
- **TWDSidebar Props**
100
-
101
- | Prop | Type | Default | Description |
102
- |-----------|---------------------|---------|---------------------------------------------|
103
- | open | boolean | true | Whether the sidebar is open by default |
104
- | position | "left" \| "right" | "left" | Sidebar position (left or right side)
105
-
106
- 2. **Write your tests:**
107
-
108
- Create files ending with `.twd.test.ts` (or any extension you prefer):
109
-
110
- ```ts
111
- // src/app.twd.test.ts
112
- import { twd, userEvent } from "twd-js";
113
- import { describe, it } from "twd-js/runner";
114
-
115
- describe("Hello World Page", () => {
116
- it("should display the welcome title and counter button", async () => {
117
- await twd.visit("/");
118
-
119
- const title = await twd.get("[data-testid='welcome-title']");
120
- title.should("be.visible").should("have.text", "Welcome to TWD");
121
-
122
- const counterButton = await twd.get("[data-testid='counter-button']");
123
- counterButton.should("be.visible").should("have.text", "Count is 0");
124
-
125
- await userEvent.click(counterButton.el);
126
- counterButton.should("have.text", "Count is 1");
127
- });
128
- });
129
- ```
130
-
131
- <p align="center">
132
- <img src="./images/twd_side_bar_success.png" alt="TWD Sidebar in action" width="800">
133
- </p>
134
-
135
- 3. **Auto-load your tests:**
136
-
137
-
138
- - With Vite and the new TWD loader:
139
-
140
- ```ts
141
- // src/main.tsx (or your main entry file)
142
- import { StrictMode } from 'react';
143
- import { createRoot } from 'react-dom/client';
144
- import './index.css';
145
- import router from './routes.ts';
146
- import { RouterProvider } from 'react-router';
147
-
148
- // Only load the test sidebar and tests in development mode
149
- if (import.meta.env.DEV) {
150
- // Use Vite's glob import to find all test files
151
- const testModules = import.meta.glob("./**/*.twd.test.ts");
152
- const { initTests, twd, TWDSidebar } = await import('twd-js');
153
- // You need to pass the test modules, the sidebar component, and createRoot function
154
- initTests(testModules, <TWDSidebar open={true} position="left" />, createRoot);
155
- // Optionally initialize request mocking
156
- twd.initRequestMocking()
157
- .then(() => {
158
- console.log("Request mocking initialized");
159
- })
160
- .catch((err) => {
161
- console.error("Error initializing request mocking:", err);
162
- });
163
- }
164
- // ...rest of your app bootstrap
165
- createRoot(document.getElementById('root')!).render(
166
- <StrictMode>
167
- <RouterProvider router={router} />
168
- </StrictMode>,
169
- );
170
- ```
171
-
172
- - Or manually (not recommended):
173
-
174
- ```ts
175
- // src/main.tsx
176
- if (import.meta.env.DEV) {
177
- const testModules = {
178
- './app.twd.test.ts': () => import('./app.twd.test'),
179
- './another-test-file.twd.test.ts': () => import('./another-test-file.twd.test'),
180
- };
181
- const { initTests, TWDSidebar } = await import('twd-js');
182
- initTests(testModules, <TWDSidebar open={true} position="left" />, createRoot);
183
- }
184
- ```
185
-
186
- 4. **Run your app and open the TWD sidebar** to see and run your tests in the browser.
187
-
188
- ## Writing Tests
189
-
190
- ### Test Structure
191
-
192
- TWD uses a familiar testing structure with `describe`, `it`, `beforeEach`, and other common testing functions:
39
+ 1. **Add TWD to your React app:**
193
40
 
194
- ```ts
195
- import { twd, userEvent } from "twd-js";
196
- import { describe, it, beforeEach } from "twd-js/runner";
41
+ ```tsx
42
+ // src/main.tsx
43
+ import { StrictMode } from "react";
44
+ import { createRoot } from "react-dom/client";
45
+ import App from "./App";
197
46
 
198
- describe("User authentication", () => {
199
- beforeEach(() => {
200
- // Reset state before each test
201
- });
202
- it("should login successfully", async () => {
203
- await twd.visit("/login");
204
- // Your test logic here
205
- });
206
-
207
- it.skip("skipped test", () => {
208
- // This test will be skipped
209
- });
210
-
211
- it.only("only this test runs", () => {
212
- // Only this test will run when .only is present
213
- });
214
- });
215
- ```
47
+ if (import.meta.env.DEV) {
48
+ const testModules = import.meta.glob("./**/*.twd.test.ts");
49
+ const { initTests, twd, TWDSidebar } = await import('twd-js');
50
+ initTests(testModules, <TWDSidebar open={true} position="left" />, createRoot);
51
+ twd.initRequestMocking().catch(console.error);
52
+ }
216
53
 
217
- ### Element Selection
54
+ createRoot(document.getElementById("root")!).render(
55
+ <StrictMode><App /></StrictMode>
56
+ );
57
+ ```
218
58
 
219
- TWD provides two main methods for selecting elements:
59
+ 2. **Write your first test:**
220
60
 
221
61
  ```ts
222
- // Select a single element
223
- const button = await twd.get("button");
224
- const input = await twd.get("input#email");
62
+ // src/app.twd.test.ts
63
+ import { twd, userEvent, screenDom } from "twd-js";
64
+ import { describe, it } from "twd-js/runner";
225
65
 
226
- // Select multiple elements
227
- const items = await twd.getAll(".item");
228
- items[0].should("be.visible");
66
+ describe("Hello World Page", () => {
67
+ it("should display the welcome title and counter button", async () => {
68
+ await twd.visit("/");
69
+
70
+ // Option 1: Use TWD's native selectors
71
+ const title = await twd.get("h1");
72
+ title.should("be.visible").should("have.text", "Welcome to TWD");
73
+
74
+ const counterButton = await twd.get("button");
75
+ counterButton.should("be.visible").should("have.text", "Count is 0");
76
+
77
+ const user = userEvent.setup();
78
+ await user.click(counterButton.el);
79
+ counterButton.should("have.text", "Count is 1");
80
+
81
+ // Option 2: Use Testing Library queries (semantic, accessible)
82
+ // const title = screenDom.getByRole("heading", { name: /welcome to twd/i });
83
+ // twd.should(title, "be.visible");
84
+ // twd.should(title, "have.text", "Welcome to TWD");
85
+ //
86
+ // const counterButton = screenDom.getByRole("button", { name: /count is/i });
87
+ // twd.should(counterButton, "be.visible");
88
+ // await user.click(counterButton);
89
+ // twd.should(counterButton, "have.text", "Count is 1");
90
+ });
91
+ });
229
92
  ```
230
93
 
231
- ### Assertions
94
+ 3. **Run your app** - The TWD sidebar will appear automatically in development mode!
232
95
 
233
- TWD includes a comprehensive set of assertions for testing element states:
96
+ <p align="center">
97
+ <img src="./images/twd_side_bar_success.png" alt="TWD Sidebar in action" width="800">
98
+ </p>
234
99
 
235
- ```ts
236
- // Text content
237
- element.should("have.text", "exact text");
238
- element.should("contain.text", "partial text");
239
- element.should("be.empty");
240
-
241
- // Attributes and values
242
- element.should("have.attr", "placeholder", "Type here");
243
- element.should("have.value", "input value");
244
- element.should("have.class", "active");
245
-
246
- // Element state
247
- element.should("be.disabled");
248
- element.should("be.enabled");
249
- element.should("be.checked");
250
- element.should("be.selected");
251
- element.should("be.focused");
252
- element.should("be.visible");
253
-
254
- // Negated assertions
255
- element.should("not.be.disabled");
256
- element.should("not.have.text", "wrong text");
257
-
258
- // URL assertions
259
- twd.url().should("eq", "http://localhost:3000/contact");
260
- twd.url().should("contain.url", "/contact");
261
- ```
100
+ ## Key Concepts
262
101
 
263
- ### User Interactions
102
+ ### Element Selection
264
103
 
265
- TWD integrates with `@testing-library/user-event` for realistic user interactions:
104
+ TWD supports two approaches:
266
105
 
106
+ **Native Selectors:**
267
107
  ```ts
268
- import { userEvent } from "twd-js";
269
-
270
- const user = userEvent.setup();
271
108
  const button = await twd.get("button");
272
- const input = await twd.get("input");
273
-
274
- // Click interactions
275
- await user.click(button.el);
276
- await user.dblClick(button.el);
277
-
278
- // Typing
279
- await user.type(input.el, "Hello World");
280
-
281
- // Form interactions
282
- await user.selectOptions(selectElement.el, "option-value");
109
+ button.should("be.visible");
283
110
  ```
284
111
 
285
- ## API Mocking
286
-
287
- ### Setup
288
-
289
- TWD provides a CLI to easily set up a mock service worker for API/request mocking in your app. You do **not** need to manually register the service worker in your appโ€”TWD handles this automatically when you use `twd.initRequestMocking()` in your tests.
290
-
291
- Run the following command in your project root:
292
-
293
- ```bash
294
- npx twd-js init <public-dir> [--save]
295
- ```
296
-
297
- - Replace `<public-dir>` with the path to your app's public/static directory (e.g., `public/` or `dist/`).
298
- - Use `--save` to print a registration snippet for your app.
299
-
300
- This will copy `mock-sw.js` to your public directory.
301
-
302
- **Removing the Service Worker in Production Builds**
303
-
304
- The service worker file (`mock-sw.js`) is only needed during development for API mocking. To remove it from production builds, use the `removeMockServiceWorker` Vite plugin:
305
-
112
+ **Testing Library Queries:**
306
113
  ```ts
307
- // vite.config.ts
308
- import { defineConfig } from 'vite';
309
- import { removeMockServiceWorker } from 'twd-js';
310
-
311
- export default defineConfig({
312
- plugins: [
313
- // ... other plugins
314
- removeMockServiceWorker()
315
- ]
316
- });
114
+ const button = screenDom.getByRole("button", { name: /submit/i });
115
+ twd.should(button, "be.visible");
317
116
  ```
318
117
 
319
- This plugin will automatically remove `mock-sw.js` from your build output during production builds.
320
-
321
- ### Mock Requests
322
-
323
- Use `twd.mockRequest()` to define API mocks in your tests:
118
+ ### User Interactions
324
119
 
325
120
  ```ts
326
- import { twd } from "twd-js";
327
-
328
- // Initialize mocking when loading tests
329
- // await twd.initRequestMocking();
330
-
331
- it("fetches user data", async () => {
332
- // Mock the API request
333
- twd.mockRequest("getUser", {
334
- method: "GET",
335
- url: "https://api.example.com/user/123",
336
- response: {
337
- id: 123,
338
- name: "John Doe",
339
- email: "john@example.com"
340
- },
341
- status: 200,
342
- headers: { "Content-Type": "application/json" }
343
- });
344
-
345
- // Trigger the request in your app
346
- const button = await twd.get("button[data-testid='load-user']");
347
- await userEvent.click(button.el);
348
-
349
- // Wait for the mock to be called
350
- const rule = await twd.waitForRequest("getUser");
351
- console.log("Request body:", rule.request);
352
-
353
- // Clean up mocks after test
354
- twd.clearRequestMockRules();
355
- });
121
+ const user = userEvent.setup();
122
+ await user.click(button);
123
+ await user.type(input, "Hello World");
356
124
  ```
357
125
 
358
- ### Wait for Requests
359
-
360
- TWD provides utilities to wait for mocked requests:
126
+ ### API Mocking
361
127
 
362
128
  ```ts
363
- // Wait for a single request
364
- const rule = await twd.waitForRequest("getUserData");
365
-
366
- // Wait for multiple requests
367
- const rules = await twd.waitForRequests(["getUser", "getPosts"]);
129
+ twd.mockRequest("getUser", {
130
+ method: "GET",
131
+ url: "/api/user",
132
+ response: { id: 1, name: "John" }
133
+ });
368
134
 
369
- // Access request data
370
- console.log("Request body:", rule.request);
371
- console.log("Response:", rule.response);
135
+ const rule = await twd.waitForRequest("getUser");
372
136
  ```
373
137
 
374
- ## API Reference
375
-
376
- ### Test Functions
377
-
378
- | Function | Description | Example |
379
- |----------|-------------|---------|
380
- | `describe(name, fn)` | Groups related tests | `describe("User login", () => {...})` |
381
- | `it(name, fn)` | Defines a test case | `it("should login", async () => {...})` |
382
- | `it.only(name, fn)` | Runs only this test | `it.only("focused test", () => {...})` |
383
- | `it.skip(name, fn)` | Skips this test | `it.skip("broken test", () => {...})` |
384
- | `beforeEach(fn)` | Runs before each test | `beforeEach(() => {...})` |
138
+ ## Learn More
385
139
 
386
- ### TWD Commands
387
-
388
- | Command | Description | Example |
389
- |---------|-------------|---------|
390
- | `twd.get(selector)` | Select single element | `await twd.get("button")` |
391
- | `twd.getAll(selector)` | Select multiple elements | `await twd.getAll(".item")` |
392
- | `twd.visit(url)` | Navigate to URL | `twd.visit("/contact")` |
393
- | `twd.wait(ms)` | Wait for specified time | `await twd.wait(500)` |
394
- | `twd.url()` | Get URL API for assertions | `twd.url().should("contain.url", "/home")` |
395
-
396
- ### Assertions
397
-
398
- #### Element Content
399
- - `have.text` - Exact text match
400
- - `contain.text` - Partial text match
401
- - `be.empty` - Element has no text content
402
-
403
- #### Element Attributes
404
- - `have.attr` - Has specific attribute value
405
- - `have.value` - Input/textarea value
406
- - `have.class` - Has CSS class
407
-
408
- #### Element State
409
- - `be.disabled` / `be.enabled` - Form element state
410
- - `be.checked` - Checkbox/radio state
411
- - `be.selected` - Option element state
412
- - `be.focused` - Element has focus
413
- - `be.visible` - Element is visible
414
-
415
- #### URL Assertions
416
- - `eq` - Exact URL match
417
- - `contain.url` - URL contains substring
418
-
419
- All assertions can be negated with `not.` prefix (e.g., `not.be.disabled`).
140
+ - ๐Ÿ“– **[Full Documentation](https://brikev.github.io/twd/)** - Complete guides and tutorials
141
+ - ๐ŸŽฏ **[Writing Tests](https://brikev.github.io/twd/writing-tests)** - Learn how to write effective tests
142
+ - ๐Ÿ”ฅ **[API Mocking](https://brikev.github.io/twd/api-mocking)** - Mock API requests in your tests
143
+ - ๐Ÿ“š **[API Reference](https://brikev.github.io/twd/api/)** - Complete API documentation
144
+ - ๐Ÿงช **[Testing Library Support](https://brikev.github.io/twd/api/react-testing-library)** - Use semantic queries
420
145
 
421
146
  ## Examples
422
147
 
423
- ### Basic Form Testing
424
-
425
- ```ts
426
- import { twd, userEvent } from "twd-js";
427
- import { describe, it } from "twd-js/runner";
428
-
429
- describe("Contact form", () => {
430
- it("submits form data", async () => {
431
- await twd.visit("/contact");
432
-
433
- const user = userEvent.setup();
434
- const emailInput = await twd.get("input#email");
435
- const messageInput = await twd.get("textarea#message");
436
- const submitBtn = await twd.get("button[type='submit']");
437
-
438
- await user.type(emailInput.el, "test@example.com");
439
- await user.type(messageInput.el, "Hello world");
440
-
441
- emailInput.should("have.value", "test@example.com");
442
- messageInput.should("have.value", "Hello world");
443
-
444
- await user.click(submitBtn.el);
445
- });
446
- });
447
- ```
448
-
449
- ### API Mocking with Authentication
450
-
451
- ```ts
452
- import { twd, userEvent } from "twd-js";
453
- import { describe, it } from "twd-js/runner";
454
-
455
- describe("Protected routes", () => {
456
- it("redirects to login when unauthorized", async () => {
457
- await twd.visit("/dashboard");
458
- await twd.wait(100);
459
- twd.url().should("contain.url", "/login");
460
- });
461
-
462
- it("loads dashboard with valid session", async () => {
463
- // Mock authentication check
464
- await twd.mockRequest("authCheck", {
465
- method: "GET",
466
- url: "/api/auth/me",
467
- response: { id: 1, name: "John Doe" }
468
- });
469
-
470
- await twd.visit("/dashboard");
471
- await twd.waitForRequest("authCheck");
472
-
473
- const welcome = await twd.get("h1");
474
- welcome.should("contain.text", "Welcome, John");
475
-
476
- twd.clearRequestMockRules();
477
- });
478
- });
479
- ```
480
-
481
- For more comprehensive examples, see the [examples](https://github.com/BRIKEV/twd/tree/main/examples) directory in the repository.
148
+ Check out the [examples directory](https://github.com/BRIKEV/twd/tree/main/examples) for complete working examples.
482
149
 
483
150
  ## Contributing
484
151
 
@@ -1 +1 @@
1
- export declare const TWD_VERSION = "1.0.1";
1
+ export declare const TWD_VERSION = "1.1.0";