@nu-art/testalot 0.401.1
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/consts.d.ts +47 -0
- package/consts.js +81 -0
- package/index.d.ts +2 -0
- package/index.js +7 -0
- package/package.json +44 -0
- package/test-template.test.d.ts +1 -0
- package/test-template.test.js +41 -0
- package/types.d.ts +76 -0
- package/types.js +6 -0
package/consts.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { TestCase_Error, TestModel } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Default test processor for async test cases.
|
|
4
|
+
*
|
|
5
|
+
* Validates that either `expectedResult` or `error` is provided, then:
|
|
6
|
+
* - If error is expected: Asserts the promise rejects with the expected error
|
|
7
|
+
* - If result is expected: Awaits the promise and validates the result
|
|
8
|
+
* - If expectedResult is a function: Calls it with the actual result
|
|
9
|
+
* - Otherwise: Deep equals comparison
|
|
10
|
+
*
|
|
11
|
+
* @template Result - Actual result type
|
|
12
|
+
* @template ExpectedResult - Expected result type
|
|
13
|
+
*/
|
|
14
|
+
export type DefaultTestProcessor<Result = any, ExpectedResult = Result> = (promisedResult: Promise<Result>, expectedResult?: ((() => Promise<any>) | ExpectedResult), error?: TestCase_Error) => Promise<any>;
|
|
15
|
+
/**
|
|
16
|
+
* Default implementation of test processor.
|
|
17
|
+
*
|
|
18
|
+
* Handles both success and error cases, with flexible result validation.
|
|
19
|
+
*/
|
|
20
|
+
export declare const defaultTestProcessor: DefaultTestProcessor;
|
|
21
|
+
/**
|
|
22
|
+
* Creates a test scenario runner function.
|
|
23
|
+
*
|
|
24
|
+
* Returns a function that can be used as a Mocha test. If no test case is provided,
|
|
25
|
+
* creates a default test case that accepts any result.
|
|
26
|
+
*
|
|
27
|
+
* @template Result - Actual result type
|
|
28
|
+
* @template ExpectedResult - Expected result type
|
|
29
|
+
* @param test - Async function to test
|
|
30
|
+
* @param _testCase - Optional test case (creates default if not provided)
|
|
31
|
+
* @param processor - Test processor function (default: defaultTestProcessor)
|
|
32
|
+
* @returns Function that can be used as a Mocha test
|
|
33
|
+
*/
|
|
34
|
+
export declare const runScenario: <Result, ExpectedResult = Result>(test: () => Promise<Result>, _testCase?: TestModel<void, ExpectedResult>, processor?: DefaultTestProcessor<any, any>) => () => Promise<any>;
|
|
35
|
+
/**
|
|
36
|
+
* Runs a single test case with input.
|
|
37
|
+
*
|
|
38
|
+
* Resolves the test case, extracts expected result or error, and runs the test.
|
|
39
|
+
*
|
|
40
|
+
* @template Input - Input type
|
|
41
|
+
* @template Result - Actual result type
|
|
42
|
+
* @template ExpectedResult - Expected result type
|
|
43
|
+
* @param test - Async function that takes input and returns result
|
|
44
|
+
* @param _testCase - Test case with input and expectations
|
|
45
|
+
* @param processor - Test processor function (default: defaultTestProcessor)
|
|
46
|
+
*/
|
|
47
|
+
export declare const runSingleTestCase: <Input, Result, ExpectedResult = Result>(test: (input: Input) => Promise<Result>, _testCase: TestModel<Input, ExpectedResult>, processor?: DefaultTestProcessor<any, any>) => Promise<any>;
|
package/consts.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @nu-art/testalot - Testing utilities and test framework helpers
|
|
3
|
+
* Copyright (C) 2024 Adam van der Kruk aka TacB0sS
|
|
4
|
+
* Licensed under the Apache License, Version 2.0
|
|
5
|
+
*/
|
|
6
|
+
import chai, { expect } from 'chai';
|
|
7
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
8
|
+
chai.use(chaiAsPromised);
|
|
9
|
+
/**
|
|
10
|
+
* Resolves content that can be either a value or a function.
|
|
11
|
+
*/
|
|
12
|
+
function resolveContent(content, ...param) {
|
|
13
|
+
return typeof content === 'function' ? content(...param) : content;
|
|
14
|
+
}
|
|
15
|
+
const Void = undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Default implementation of test processor.
|
|
18
|
+
*
|
|
19
|
+
* Handles both success and error cases, with flexible result validation.
|
|
20
|
+
*/
|
|
21
|
+
export const defaultTestProcessor = async (promisedResult, expectedResult, error) => {
|
|
22
|
+
if (expectedResult == null && error == null)
|
|
23
|
+
throw new Error('MUST provide expectedResult or error');
|
|
24
|
+
if (typeof error === 'object')
|
|
25
|
+
return expect(promisedResult).to.be.rejectedWith(error.expected);
|
|
26
|
+
let result;
|
|
27
|
+
try {
|
|
28
|
+
result = await promisedResult;
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
if (typeof error === 'function')
|
|
32
|
+
return await error(e);
|
|
33
|
+
throw e;
|
|
34
|
+
}
|
|
35
|
+
if (typeof expectedResult === 'function')
|
|
36
|
+
return await expectedResult(result);
|
|
37
|
+
expect(result).to.deep.equal(expectedResult);
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Creates a test scenario runner function.
|
|
41
|
+
*
|
|
42
|
+
* Returns a function that can be used as a Mocha test. If no test case is provided,
|
|
43
|
+
* creates a default test case that accepts any result.
|
|
44
|
+
*
|
|
45
|
+
* @template Result - Actual result type
|
|
46
|
+
* @template ExpectedResult - Expected result type
|
|
47
|
+
* @param test - Async function to test
|
|
48
|
+
* @param _testCase - Optional test case (creates default if not provided)
|
|
49
|
+
* @param processor - Test processor function (default: defaultTestProcessor)
|
|
50
|
+
* @returns Function that can be used as a Mocha test
|
|
51
|
+
*/
|
|
52
|
+
export const runScenario = (test, _testCase, processor = defaultTestProcessor) => {
|
|
53
|
+
let testCase;
|
|
54
|
+
if (_testCase)
|
|
55
|
+
testCase = resolveContent(_testCase);
|
|
56
|
+
else
|
|
57
|
+
testCase = {
|
|
58
|
+
input: Void,
|
|
59
|
+
result: async (r) => {
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
return async () => runSingleTestCase(test, testCase, processor);
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Runs a single test case with input.
|
|
66
|
+
*
|
|
67
|
+
* Resolves the test case, extracts expected result or error, and runs the test.
|
|
68
|
+
*
|
|
69
|
+
* @template Input - Input type
|
|
70
|
+
* @template Result - Actual result type
|
|
71
|
+
* @template ExpectedResult - Expected result type
|
|
72
|
+
* @param test - Async function that takes input and returns result
|
|
73
|
+
* @param _testCase - Test case with input and expectations
|
|
74
|
+
* @param processor - Test processor function (default: defaultTestProcessor)
|
|
75
|
+
*/
|
|
76
|
+
export const runSingleTestCase = async (test, _testCase, processor = defaultTestProcessor) => {
|
|
77
|
+
const testCase = resolveContent(_testCase);
|
|
78
|
+
const expectedResult = 'result' in testCase ? testCase.result : undefined;
|
|
79
|
+
const error = 'error' in testCase ? testCase.error : undefined;
|
|
80
|
+
return processor(test(testCase.input), expectedResult, error);
|
|
81
|
+
};
|
package/index.d.ts
ADDED
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nu-art/testalot",
|
|
3
|
+
"version": "0.401.1",
|
|
4
|
+
"description": "Testing utilities and test framework helpers for TypeScript projects",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"typescript",
|
|
8
|
+
"testing",
|
|
9
|
+
"test-framework",
|
|
10
|
+
"mocha",
|
|
11
|
+
"test-utilities",
|
|
12
|
+
"nu-art",
|
|
13
|
+
"thunderstorm"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://github.com/nu-art-js/thunderstorm",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/nu-art-js/thunderstorm/issues?q=is%3Aissue+label%3Atestalot"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+ssh://git@github.com:nu-art-js/thunderstorm.git",
|
|
22
|
+
"directory": "_thunderstorm/testalot"
|
|
23
|
+
},
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"directory": "dist"
|
|
26
|
+
},
|
|
27
|
+
"license": "Apache-2.0",
|
|
28
|
+
"author": "TacB0sS",
|
|
29
|
+
"scripts": {},
|
|
30
|
+
"dependencies": {},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"chai": "^4.0.0",
|
|
33
|
+
"chai-as-promised": "^7.0.0"
|
|
34
|
+
},
|
|
35
|
+
"unitConfig": {
|
|
36
|
+
"type": "typescript-lib"
|
|
37
|
+
},
|
|
38
|
+
"exports": {
|
|
39
|
+
".": {
|
|
40
|
+
"types": "./index.d.ts",
|
|
41
|
+
"import": "./index.js"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { runSingleTestCase } from './consts.js';
|
|
2
|
+
const justAGlobalConst = 'just a global const';
|
|
3
|
+
// the test cases, notice these can be a resolvable content, in order to keep bind consts between the input and the output,
|
|
4
|
+
const test = async (input) => {
|
|
5
|
+
// the actual test logic that all test cases will pass through and all will yield the Result
|
|
6
|
+
// this logic is silly but demonstrate the concept
|
|
7
|
+
if (input.inputB === 2)
|
|
8
|
+
throw new Error('a part of the error message would be The expected error message - but it\'s not the only part of the message');
|
|
9
|
+
return iAmJustAHelperFunction();
|
|
10
|
+
};
|
|
11
|
+
// helper function - dedicated for this test suite
|
|
12
|
+
function iAmJustAHelperFunction() {
|
|
13
|
+
return justAGlobalConst;
|
|
14
|
+
}
|
|
15
|
+
const runTestCase = (testCase, processor) => () => runSingleTestCase(test, testCase, processor);
|
|
16
|
+
// the mocha test launch
|
|
17
|
+
describe('template', () => {
|
|
18
|
+
it('My very fancy test', () => {
|
|
19
|
+
const justAConst = 'case 1';
|
|
20
|
+
return runTestCase({
|
|
21
|
+
input: {
|
|
22
|
+
inputA: `input for test ${justAConst}`,
|
|
23
|
+
inputB: 1,
|
|
24
|
+
inputC: ''
|
|
25
|
+
},
|
|
26
|
+
result: justAGlobalConst
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
it('My super fancy test case 2 - expected to fail', () => {
|
|
30
|
+
return runTestCase({
|
|
31
|
+
input: {
|
|
32
|
+
inputA: 'input for test case 2',
|
|
33
|
+
inputB: 2,
|
|
34
|
+
inputC: ''
|
|
35
|
+
},
|
|
36
|
+
error: {
|
|
37
|
+
expected: 'The expected error message'
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
});
|
package/types.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content that can be either a value or a function that returns a value.
|
|
3
|
+
*/
|
|
4
|
+
export type ResolvableContent<T, K extends any[] = any[]> = T | ((...param: K) => T);
|
|
5
|
+
/**
|
|
6
|
+
* Test case input/output type.
|
|
7
|
+
*
|
|
8
|
+
* @template Input - Input type for the test
|
|
9
|
+
* @template Result - Expected result type
|
|
10
|
+
*/
|
|
11
|
+
export type Types<Input, Result> = {
|
|
12
|
+
expected?: Result;
|
|
13
|
+
input: Input;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Error expectation for test cases.
|
|
17
|
+
*
|
|
18
|
+
* Can be:
|
|
19
|
+
* - Object with expected error message/pattern and optional constructor
|
|
20
|
+
* - Function that validates the error
|
|
21
|
+
*/
|
|
22
|
+
export type TestCase_Error = {
|
|
23
|
+
expected: string | RegExp;
|
|
24
|
+
message?: string;
|
|
25
|
+
constructor?: Error | Function;
|
|
26
|
+
} | ((error: Error) => Promise<any>);
|
|
27
|
+
/**
|
|
28
|
+
* Test case model with input and expected result or error.
|
|
29
|
+
*
|
|
30
|
+
* Supports:
|
|
31
|
+
* - Resolvable content (value or function)
|
|
32
|
+
* - Optional description (can reference the test case itself)
|
|
33
|
+
* - Expected result (value or validation function)
|
|
34
|
+
* - Expected error (object or validation function)
|
|
35
|
+
*
|
|
36
|
+
* @template Input - Input type
|
|
37
|
+
* @template ExpectedResult - Expected result type
|
|
38
|
+
*/
|
|
39
|
+
export type TestModel<Input, ExpectedResult> = ResolvableContent<{
|
|
40
|
+
description?: ResolvableContent<string, [TestModel<Input, ExpectedResult>]>;
|
|
41
|
+
input: Input;
|
|
42
|
+
} & ({
|
|
43
|
+
result: ExpectedResult | ((result: ExpectedResult) => Promise<any>);
|
|
44
|
+
} | {
|
|
45
|
+
error: TestCase_Error;
|
|
46
|
+
})>;
|
|
47
|
+
/**
|
|
48
|
+
* Function that processes a test case.
|
|
49
|
+
*
|
|
50
|
+
* @template Input - Input type
|
|
51
|
+
* @template ExpectedResult - Expected result type
|
|
52
|
+
*/
|
|
53
|
+
export type TestProcessor<Input, ExpectedResult> = (input: TestModel<Input, ExpectedResult>) => void | Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Test suite configuration.
|
|
56
|
+
*
|
|
57
|
+
* Defines a collection of test cases with setup/teardown hooks.
|
|
58
|
+
*
|
|
59
|
+
* @template Input - Input type for test cases
|
|
60
|
+
* @template ExpectedResult - Expected result type
|
|
61
|
+
* @deprecated
|
|
62
|
+
*/
|
|
63
|
+
export type TestSuite<Input, ExpectedResult> = {
|
|
64
|
+
/** Optional setup function (runs before all tests) */
|
|
65
|
+
before?: () => (void | Promise<void>);
|
|
66
|
+
/** Function that processes each test case */
|
|
67
|
+
processor: TestProcessor<Input, ExpectedResult>;
|
|
68
|
+
/** Optional teardown function (runs after all tests) */
|
|
69
|
+
after?: () => (void | Promise<void>);
|
|
70
|
+
/** Array of test cases */
|
|
71
|
+
testcases: TestModel<Input, ExpectedResult>[];
|
|
72
|
+
/** Suite label/name */
|
|
73
|
+
label: string;
|
|
74
|
+
/** Optional timeout in milliseconds (default: 5000) */
|
|
75
|
+
timeout?: number;
|
|
76
|
+
};
|