puty 0.1.1 → 0.1.2
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 +35 -6
- package/package.json +1 -1
- package/src/puty.js +21 -15
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@ Puty is ideal for testing pure functions - functions that always return the same
|
|
|
11
11
|
- [Quick Start](#quick-start)
|
|
12
12
|
- [Usage](#usage)
|
|
13
13
|
- [Testing Functions](#testing-functions)
|
|
14
|
+
- [Async Functions and Methods](#async-functions-and-methods)
|
|
14
15
|
- [Testing Classes](#testing-classes)
|
|
15
16
|
- [Testing Factory Functions](#testing-factory-functions)
|
|
16
17
|
- [Error Testing](#error-testing)
|
|
@@ -25,6 +26,7 @@ Puty is ideal for testing pure functions - functions that always return the same
|
|
|
25
26
|
- 📦 Modular test organization with `!include` directive
|
|
26
27
|
- 🎯 Clear separation of test data and test logic
|
|
27
28
|
- 🧪 Mock support for testing functions with dependencies
|
|
29
|
+
- ⏳ Async support for functions, class methods, and factory method executions
|
|
28
30
|
- ⚡ Powered by Vitest for fast test execution
|
|
29
31
|
|
|
30
32
|
## Installation
|
|
@@ -199,6 +201,32 @@ describe('math', () => {
|
|
|
199
201
|
|
|
200
202
|
See the [YAML Structure](#yaml-structure) section for detailed documentation of all available fields.
|
|
201
203
|
|
|
204
|
+
### Async Functions and Methods
|
|
205
|
+
|
|
206
|
+
Puty supports async functions and async method executions using the same YAML fields:
|
|
207
|
+
|
|
208
|
+
- `out` asserts the resolved return value
|
|
209
|
+
- `throws` asserts either a thrown error or a rejected promise
|
|
210
|
+
|
|
211
|
+
Example:
|
|
212
|
+
|
|
213
|
+
```yaml
|
|
214
|
+
file: './async.js'
|
|
215
|
+
group: async
|
|
216
|
+
---
|
|
217
|
+
suite: fetchUser
|
|
218
|
+
exportName: fetchUser
|
|
219
|
+
---
|
|
220
|
+
case: resolves user
|
|
221
|
+
in: [1]
|
|
222
|
+
out:
|
|
223
|
+
id: 1
|
|
224
|
+
---
|
|
225
|
+
case: rejects for missing user
|
|
226
|
+
in: [999]
|
|
227
|
+
throws: 'not found'
|
|
228
|
+
```
|
|
229
|
+
|
|
202
230
|
### Testing Classes
|
|
203
231
|
|
|
204
232
|
Puty also supports testing classes with method calls and state assertions:
|
|
@@ -334,7 +362,9 @@ The `__undefined__` keyword works in:
|
|
|
334
362
|
|
|
335
363
|
### Error Testing
|
|
336
364
|
|
|
337
|
-
You can test that functions or methods
|
|
365
|
+
You can test that functions or methods fail with expected errors:
|
|
366
|
+
- Sync functions/methods: thrown errors are supported
|
|
367
|
+
- Async functions/methods: rejected promises are supported
|
|
338
368
|
|
|
339
369
|
```yaml
|
|
340
370
|
case: divide by zero
|
|
@@ -510,8 +540,8 @@ For function tests:
|
|
|
510
540
|
```yaml
|
|
511
541
|
case: 'test description' # Required: Test case name
|
|
512
542
|
in: [arg1, arg2] # Required: Input arguments (use $mock:name for mocks)
|
|
513
|
-
out: expectedValue # Optional: Expected output (
|
|
514
|
-
throws: 'Error message' # Optional: Expected error message
|
|
543
|
+
out: expectedValue # Optional: Expected output (resolved value for async functions)
|
|
544
|
+
throws: 'Error message' # Optional: Expected error message (sync throw or async rejection)
|
|
515
545
|
mocks: # Optional: Case-specific mocks
|
|
516
546
|
mockName:
|
|
517
547
|
calls: # Array of expected calls
|
|
@@ -526,8 +556,8 @@ case: 'test description'
|
|
|
526
556
|
executions:
|
|
527
557
|
- method: 'methodName' # Supports nested: 'user.api.getData'
|
|
528
558
|
in: [arg1]
|
|
529
|
-
out: expectedValue # Optional
|
|
530
|
-
throws: 'Error msg' # Optional
|
|
559
|
+
out: expectedValue # Optional (resolved value for async methods)
|
|
560
|
+
throws: 'Error msg' # Optional (sync throw or async rejection)
|
|
531
561
|
asserts:
|
|
532
562
|
- property: 'prop' # Supports nested: 'user.profile.name'
|
|
533
563
|
op: 'eq' # Currently only 'eq' is supported
|
|
@@ -563,4 +593,3 @@ executions:
|
|
|
563
593
|
in: ['/users/123']
|
|
564
594
|
out: 'GET /users/123'
|
|
565
595
|
```
|
|
566
|
-
|
package/package.json
CHANGED
package/src/puty.js
CHANGED
|
@@ -245,18 +245,20 @@ const setupFunctionTests = (suite) => {
|
|
|
245
245
|
mockFunctions,
|
|
246
246
|
executions,
|
|
247
247
|
} = testCase;
|
|
248
|
-
test(name, () => {
|
|
248
|
+
test(name, async () => {
|
|
249
249
|
if (!functionUnderTest) {
|
|
250
250
|
throw new Error(`Function not found for test case: ${name}`);
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
try {
|
|
254
254
|
if (throws) {
|
|
255
|
-
//
|
|
256
|
-
expect(
|
|
255
|
+
// Supports both sync throws and async rejections
|
|
256
|
+
await expect(
|
|
257
|
+
Promise.resolve().then(() => functionUnderTest(...(inArg || []))),
|
|
258
|
+
).rejects.toThrow(throws);
|
|
257
259
|
} else {
|
|
258
260
|
// Call the function
|
|
259
|
-
const result = functionUnderTest(...(inArg || []));
|
|
261
|
+
const result = await functionUnderTest(...(inArg || []));
|
|
260
262
|
|
|
261
263
|
// Assert return value if 'out' field is present in the test case
|
|
262
264
|
if ("out" in testCase) {
|
|
@@ -276,11 +278,13 @@ const setupFunctionTests = (suite) => {
|
|
|
276
278
|
} = execution;
|
|
277
279
|
|
|
278
280
|
if (execThrows) {
|
|
279
|
-
expect(
|
|
280
|
-
|
|
281
|
-
|
|
281
|
+
await expect(
|
|
282
|
+
Promise.resolve().then(() =>
|
|
283
|
+
callNestedMethod(result, method, execInArg || []),
|
|
284
|
+
),
|
|
285
|
+
).rejects.toThrow(execThrows);
|
|
282
286
|
} else {
|
|
283
|
-
const methodResult = callNestedMethod(
|
|
287
|
+
const methodResult = await callNestedMethod(
|
|
284
288
|
result,
|
|
285
289
|
method,
|
|
286
290
|
execInArg || [],
|
|
@@ -304,7 +308,7 @@ const setupFunctionTests = (suite) => {
|
|
|
304
308
|
expect(actualValue).toEqual(processedValue);
|
|
305
309
|
}
|
|
306
310
|
} else if (assertion.method) {
|
|
307
|
-
const assertResult = callNestedMethod(
|
|
311
|
+
const assertResult = await callNestedMethod(
|
|
308
312
|
result,
|
|
309
313
|
assertion.method,
|
|
310
314
|
assertion.in || [],
|
|
@@ -347,7 +351,7 @@ const setupClassTests = (suite) => {
|
|
|
347
351
|
const { cases, ClassUnderTest, constructorArgs } = suite;
|
|
348
352
|
for (const testCase of cases) {
|
|
349
353
|
const { name, executions, mockFunctions } = testCase;
|
|
350
|
-
test(name, () => {
|
|
354
|
+
test(name, async () => {
|
|
351
355
|
if (!ClassUnderTest) {
|
|
352
356
|
throw new Error(`Class not found for test suite: ${suite.name}`);
|
|
353
357
|
}
|
|
@@ -366,11 +370,13 @@ const setupClassTests = (suite) => {
|
|
|
366
370
|
|
|
367
371
|
// Execute the method and check its return value - supports nested methods
|
|
368
372
|
if (throws) {
|
|
369
|
-
expect(
|
|
370
|
-
|
|
371
|
-
|
|
373
|
+
await expect(
|
|
374
|
+
Promise.resolve().then(() =>
|
|
375
|
+
callNestedMethod(instance, method, inArg || []),
|
|
376
|
+
),
|
|
377
|
+
).rejects.toThrow(throws);
|
|
372
378
|
} else {
|
|
373
|
-
const result = callNestedMethod(instance, method, inArg || []);
|
|
379
|
+
const result = await callNestedMethod(instance, method, inArg || []);
|
|
374
380
|
if (expectedOut !== undefined) {
|
|
375
381
|
const processedExpectedOut = processUndefined(expectedOut);
|
|
376
382
|
expect(result).toEqual(processedExpectedOut);
|
|
@@ -393,7 +399,7 @@ const setupClassTests = (suite) => {
|
|
|
393
399
|
// Add more operators as needed
|
|
394
400
|
} else if (assertion.method) {
|
|
395
401
|
// Method assertion - supports nested methods like "user.api.getData"
|
|
396
|
-
const result = callNestedMethod(
|
|
402
|
+
const result = await callNestedMethod(
|
|
397
403
|
instance,
|
|
398
404
|
assertion.method,
|
|
399
405
|
assertion.in || [],
|