@dannysir/js-te 0.3.0 → 0.3.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 +13 -7
- package/bin/cli.js +14 -62
- package/dist/index.cjs +166 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +166 -102
- package/dist/index.mjs.map +1 -1
- package/index.js +90 -0
- package/package.json +4 -6
- package/src/babelPlugins/babelCollectMocks.js +35 -0
- package/src/babelPlugins/babelTransformImport.js +184 -0
- package/src/babelPlugins/utils/getModuleInfo.js +21 -0
- package/src/babelPlugins/utils/pathHelper.js +56 -0
- package/src/babelPlugins/utils/wrapperCreator.js +121 -0
- package/src/cli/runTests.js +22 -0
- package/src/cli/setupEnvironment.js +32 -0
- package/src/cli/setupFiles.js +15 -0
- package/src/constants/babel.js +12 -0
- package/src/constants/index.js +29 -0
- package/src/constants/view.js +9 -0
- package/src/matchers.js +1 -2
- package/src/mock/collectMocks.js +2 -3
- package/src/mock/store.js +4 -4
- package/src/testManager.js +31 -12
- package/{utils → src/utils}/consoleColor.js +2 -2
- package/{bin → src}/utils/findFiles.js +16 -5
- package/{utils → src/utils}/formatString.js +15 -5
- package/src/utils/messages.js +26 -0
- package/{bin → src}/utils/transformFiles.js +9 -4
- package/babelTransformImport.js +0 -317
- package/constants.js +0 -46
- package/src/testRunner.js +0 -28
- package/utils/makeMessage.js +0 -14
package/README.md
CHANGED
|
@@ -3,20 +3,26 @@
|
|
|
3
3
|
Jest에서 영감을 받아 만든 가벼운 JavaScript 테스트 프레임워크입니다.
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
## [📎 최근 업데이트 0.3.
|
|
6
|
+
## [📎 최근 업데이트 0.3.2v](https://github.com/dannysir/js-te-package/blob/main/CHANGELOG.md) & 주요 업데이트 내용
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
### `mock` 이후 import를 해야하는 문제 해결
|
|
8
|
+
### `mock` 이후 import를 해야하는 문제 해결 (0.3.0v)
|
|
10
9
|
- 문제 : 기존의 경우 모킹 기능 이용시 반드시 동적 import문을 mock 다음에 작성해야 했음
|
|
11
10
|
- 해결
|
|
12
11
|
- 기존 `mockStore`를 직접 비교하여 import하는 방식에서 wrapper 패턴을 이용하도록 적용
|
|
13
12
|
- 모듈을 새로운 함수로 만들어 함수를 실행할 때마다 `mockStore`와 비교하여 값을 리턴하도록 수정
|
|
14
|
-
### 모듈 변환 최적화
|
|
13
|
+
### 모듈 변환 최적화 (0.3.0v)
|
|
15
14
|
- 문제 : 앞선 변경으로 인해 모든 파일의 모듈들이 사용될 때마다 `mockStore`와 비교하는 로직이 실행됨
|
|
16
15
|
- 해결
|
|
17
|
-
- `cli`로직에 mock을 미리 검사하여 mock 경로를 미리 저장하는 로직을 추가
|
|
16
|
+
- `cli.js`로직에 mock을 미리 검사하여 mock 경로를 미리 저장하는 로직을 추가
|
|
18
17
|
- 미리 확인한 mock 경로를 이용해 import문이 만약 저장된 경로일 때만 babel 변환
|
|
19
|
-
|
|
18
|
+
### 리펙토링 (0.3.2v)
|
|
19
|
+
- 불필요하게 거대한 로직 분리
|
|
20
|
+
- `cli.js` 내부 로직 분리 & `cli.js` 내부에서는 전체 흐름만 관리하도록 수정
|
|
21
|
+
- 바벨 플러그인 코드내 중복되는 코드 제거
|
|
22
|
+
- 디렉토리 구조 변경
|
|
23
|
+
- 기존 디렉토리 내부에 있던 유틸 디렉토리를 통합된 유틸로 관리
|
|
24
|
+
- bin 내부에 존재하는 로직을 `cli.js`를 제외하고 전부 src 디렉토리로 옮김
|
|
25
|
+
- 분리된 디렉토리를 src 내부에서 관리하도록 수정 (ex: `babelTransformImport.js`)
|
|
20
26
|
---
|
|
21
27
|
## 설치
|
|
22
28
|
|
|
@@ -195,7 +201,7 @@ export const subtract = (a, b) => a - b;
|
|
|
195
201
|
export const multiply = (a, b) => a * b;
|
|
196
202
|
|
|
197
203
|
// math.test.js
|
|
198
|
-
const { add, multiply } = import('./math.js'); // 0.3.0 버전부터는 최상단에 선언 가능
|
|
204
|
+
const { add, subtract, multiply } = import('./math.js'); // 0.3.0 버전부터는 최상단에 선언 가능
|
|
199
205
|
|
|
200
206
|
test('부분 모킹 예제', async () => {
|
|
201
207
|
mock('/Users/san/untitled/index.js', {
|
package/bin/cli.js
CHANGED
|
@@ -1,73 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {RESULT_TITLE} from "../constants.js";
|
|
10
|
-
import {collectMockedPaths} from "../src/mock/collectMocks.js";
|
|
11
|
-
|
|
12
|
-
const getUserModuleType = () => {
|
|
13
|
-
try {
|
|
14
|
-
const pkgPath = path.join(process.cwd(), 'package.json');
|
|
15
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
16
|
-
return pkg.type === 'module' ? 'esm' : 'cjs';
|
|
17
|
-
} catch {
|
|
18
|
-
return 'cjs';
|
|
19
|
-
}
|
|
20
|
-
};
|
|
3
|
+
import {NUM, RESULT_MSG} from "../src/constants/index.js";
|
|
4
|
+
import {restoreFiles} from "../src/utils/transformFiles.js";
|
|
5
|
+
import {getErrorMsgInLogic, getFileCountString, getTestResultMsg} from "../src/utils/messages.js";
|
|
6
|
+
import {setupEnvironment} from "../src/cli/setupEnvironment.js";
|
|
7
|
+
import {setupFiles} from "../src/cli/setupFiles.js";
|
|
8
|
+
import {runTests} from "../src/cli/runTests.js";
|
|
21
9
|
|
|
22
10
|
const main = async () => {
|
|
23
11
|
try {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const moduleType = getUserModuleType();
|
|
28
|
-
|
|
29
|
-
let jsTe;
|
|
30
|
-
if (moduleType === 'esm') {
|
|
31
|
-
jsTe = await import('@dannysir/js-te');
|
|
32
|
-
} else {
|
|
33
|
-
const { createRequire } = await import('module');
|
|
34
|
-
const require = createRequire(import.meta.url);
|
|
35
|
-
jsTe = require('@dannysir/js-te');
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
Object.keys(jsTe).forEach(key => {
|
|
39
|
-
global[key] = jsTe[key];
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const testFiles = findTestFiles(process.cwd());
|
|
43
|
-
console.log(`\nFound ${green(testFiles.length)} test file(s)`);
|
|
44
|
-
|
|
45
|
-
const mockedPaths = collectMockedPaths(testFiles);
|
|
46
|
-
|
|
47
|
-
const sourceFiles = findAllSourceFiles(process.cwd());
|
|
48
|
-
for (const file of sourceFiles) {
|
|
49
|
-
transformFiles(file, mockedPaths);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
for (const file of testFiles) {
|
|
53
|
-
console.log(`\n${yellow(file)}\n`);
|
|
54
|
-
transformFiles(file, mockedPaths);
|
|
55
|
-
|
|
56
|
-
await import(path.resolve(file));
|
|
57
|
-
|
|
58
|
-
const {passed, failed} = await jsTe.run();
|
|
59
|
-
totalPassed += passed;
|
|
60
|
-
totalFailed += failed;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
console.log(getTestResultMsg(RESULT_TITLE.TOTAL, totalPassed, totalFailed));
|
|
12
|
+
const jsTe = await setupEnvironment();
|
|
13
|
+
const {mockedPaths, testFiles} = setupFiles();
|
|
64
14
|
|
|
65
|
-
|
|
15
|
+
console.log(getFileCountString(testFiles.length));
|
|
16
|
+
const {totalPassed, totalFailed} = await runTests(jsTe, mockedPaths, testFiles);
|
|
17
|
+
console.log(getTestResultMsg(RESULT_MSG.TOTAL, totalPassed, totalFailed));
|
|
66
18
|
|
|
19
|
+
return totalFailed > NUM.ZERO ? NUM.ONE : NUM.ZERO;
|
|
67
20
|
} catch (error) {
|
|
68
|
-
console.log(
|
|
69
|
-
|
|
70
|
-
return 1;
|
|
21
|
+
console.log(getErrorMsgInLogic(error.message));
|
|
22
|
+
return NUM.ONE;
|
|
71
23
|
} finally {
|
|
72
24
|
restoreFiles();
|
|
73
25
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -1,23 +1,87 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
3
|
+
const COLORS = {
|
|
4
|
+
reset: '\x1b[0m',
|
|
5
|
+
green: '\x1b[32m',
|
|
6
|
+
red: '\x1b[31m',
|
|
7
|
+
bold: '\x1b[1m'
|
|
8
|
+
};
|
|
5
9
|
|
|
6
|
-
const
|
|
10
|
+
const colorize = (text, color) => `${color}${text}${COLORS.reset}`;
|
|
7
11
|
|
|
8
|
-
const
|
|
12
|
+
const green = (text) => colorize(text, COLORS.green + COLORS.bold);
|
|
13
|
+
const red = (text) => colorize(text, COLORS.red + COLORS.bold);
|
|
14
|
+
const bold = (text) => colorize(text, COLORS.bold);
|
|
9
15
|
|
|
10
|
-
const
|
|
16
|
+
const RESULT_MSG = {
|
|
17
|
+
TESTS: 'Tests: ',
|
|
18
|
+
CHECK: '✓ ',
|
|
19
|
+
CROSS: '✗ ',
|
|
20
|
+
DIRECTORY_DELIMITER: ' > ',
|
|
21
|
+
EMPTY: '',
|
|
22
|
+
};
|
|
11
23
|
|
|
12
|
-
const
|
|
24
|
+
const NUM = {
|
|
25
|
+
ZERO: 0};
|
|
13
26
|
|
|
14
|
-
const
|
|
27
|
+
const formatSuccessMessage = (test) => {
|
|
28
|
+
const pathString = test.path === '' ? RESULT_MSG.EMPTY : test.path + RESULT_MSG.DIRECTORY_DELIMITER;
|
|
29
|
+
return green(RESULT_MSG.CHECK) + pathString + test.description;
|
|
30
|
+
};
|
|
15
31
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
red:
|
|
20
|
-
|
|
32
|
+
const formatFailureMessage = (test, error) => {
|
|
33
|
+
const messages = [];
|
|
34
|
+
messages.push(red(RESULT_MSG.CROSS) + test.path + test.description);
|
|
35
|
+
messages.push(red(` Error Message : ${error.message}`));
|
|
36
|
+
return messages.join('\n');
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const getErrorMsg = (expect, actual) => {
|
|
40
|
+
return `Expected ${JSON.stringify(expect)} but got ${JSON.stringify(actual)}`;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const getThrowErrorMsg = (expect) => {
|
|
44
|
+
return `Expected function to throw an error containing "${expect}", but it did not throw`;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const placeHolder = {
|
|
48
|
+
's': (value) => value,
|
|
49
|
+
'o': (value) => JSON.stringify(value),
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const getMatcherForReplace = () => {
|
|
53
|
+
return new RegExp(`%([${Object.keys(placeHolder).join('')}])`, 'g')
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const mockStore = new Map();
|
|
57
|
+
|
|
58
|
+
const clearAllMocks = () => {
|
|
59
|
+
mockStore.clear();
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const mock = (modulePath, mockExports) => {
|
|
63
|
+
mockStore.set(modulePath, mockExports);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const unmock = (modulePath) => {
|
|
67
|
+
mockStore.delete(modulePath);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const isMocked = (modulePath) => {
|
|
71
|
+
return mockStore.has(modulePath);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const getTestResultMsg = (title, success, fail) => {
|
|
75
|
+
let msg = '\n';
|
|
76
|
+
|
|
77
|
+
msg += title;
|
|
78
|
+
msg += green(success + ' passed') + ', ';
|
|
79
|
+
if (fail) {
|
|
80
|
+
msg += red(fail + ' failed') + ', ';
|
|
81
|
+
}
|
|
82
|
+
msg += bold(success + fail + ' total');
|
|
83
|
+
|
|
84
|
+
return msg;
|
|
21
85
|
};
|
|
22
86
|
|
|
23
87
|
class TestManager {
|
|
@@ -44,7 +108,7 @@ class TestManager {
|
|
|
44
108
|
}
|
|
45
109
|
await fn();
|
|
46
110
|
},
|
|
47
|
-
path: this.#testDepth.join(DIRECTORY_DELIMITER),
|
|
111
|
+
path: this.#testDepth.join(RESULT_MSG.DIRECTORY_DELIMITER),
|
|
48
112
|
};
|
|
49
113
|
this.#tests.push(testObj);
|
|
50
114
|
}
|
|
@@ -72,70 +136,43 @@ class TestManager {
|
|
|
72
136
|
this.#beforeEachArr = [];
|
|
73
137
|
}
|
|
74
138
|
|
|
139
|
+
async run() {
|
|
140
|
+
let passed = NUM.ZERO;
|
|
141
|
+
let failed = NUM.ZERO;
|
|
142
|
+
|
|
143
|
+
for (const test of testManager.getTests()) {
|
|
144
|
+
try {
|
|
145
|
+
await test.fn();
|
|
146
|
+
console.log(formatSuccessMessage(test));
|
|
147
|
+
passed++;
|
|
148
|
+
clearAllMocks();
|
|
149
|
+
} catch (error) {
|
|
150
|
+
console.log(formatFailureMessage(test, error));
|
|
151
|
+
failed++;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
console.log(getTestResultMsg(RESULT_MSG.TESTS, passed, failed));
|
|
156
|
+
|
|
157
|
+
testManager.clearTests();
|
|
158
|
+
|
|
159
|
+
return {passed, failed};
|
|
160
|
+
}
|
|
161
|
+
|
|
75
162
|
#formatDescription(args, description) {
|
|
76
163
|
let argIndex = 0;
|
|
77
|
-
return description.replace(
|
|
164
|
+
return description.replace(getMatcherForReplace(), (match, type) => {
|
|
78
165
|
if (argIndex >= args.length) return match;
|
|
79
166
|
|
|
80
|
-
const
|
|
167
|
+
const formatter = placeHolder[type];
|
|
81
168
|
|
|
82
|
-
|
|
83
|
-
case 's':
|
|
84
|
-
return arg;
|
|
85
|
-
case 'o':
|
|
86
|
-
return JSON.stringify(arg);
|
|
87
|
-
default:
|
|
88
|
-
return match;
|
|
89
|
-
}
|
|
169
|
+
return formatter ? formatter(args[argIndex++]) : match;
|
|
90
170
|
});
|
|
91
171
|
}
|
|
92
172
|
}
|
|
93
173
|
|
|
94
174
|
const testManager = new TestManager();
|
|
95
175
|
|
|
96
|
-
const mockStore = new Map();
|
|
97
|
-
|
|
98
|
-
function clearAllMocks() {
|
|
99
|
-
mockStore.clear();
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function mock(modulePath, mockExports) {
|
|
103
|
-
mockStore.set(modulePath, mockExports);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function unmock(modulePath) {
|
|
107
|
-
mockStore.delete(modulePath);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function isMocked(modulePath) {
|
|
111
|
-
return mockStore.has(modulePath);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const colorize = (text, color) => `${color}${text}${COLORS.reset}`;
|
|
115
|
-
|
|
116
|
-
const green = (text) => colorize(text, COLORS.green + COLORS.bold);
|
|
117
|
-
const red = (text) => colorize(text, COLORS.red + COLORS.bold);
|
|
118
|
-
const bold = (text) => colorize(text, COLORS.bold);
|
|
119
|
-
|
|
120
|
-
const formatSuccessMessage = (test) => {
|
|
121
|
-
const pathString = test.path === '' ? EMPTY : test.path + DIRECTORY_DELIMITER;
|
|
122
|
-
return green(CHECK) + pathString + test.description;
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
const formatFailureMessage = (test, error) => {
|
|
126
|
-
const messages = [];
|
|
127
|
-
messages.push(red(CROSS) + test.path + test.description);
|
|
128
|
-
messages.push(red(` Error Message : ${error.message}`));
|
|
129
|
-
return messages.join('\n');
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
const getErrorMsg = (expect, actual) => {
|
|
133
|
-
return `Expected ${JSON.stringify(expect)} but got ${JSON.stringify(actual)}`;
|
|
134
|
-
};
|
|
135
|
-
const getThrowErrorMsg = (expect) => {
|
|
136
|
-
return `Expected function to throw an error containing "${expect}", but it did not throw`;
|
|
137
|
-
};
|
|
138
|
-
|
|
139
176
|
const runArgFnc = (actual) => {
|
|
140
177
|
if (typeof actual === 'function') {
|
|
141
178
|
return actual();
|
|
@@ -203,49 +240,76 @@ const expect = (actual) => {
|
|
|
203
240
|
}
|
|
204
241
|
};
|
|
205
242
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
return msg;
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
const run = async () => {
|
|
220
|
-
let passed = DEFAULT_COUNT;
|
|
221
|
-
let failed = DEFAULT_COUNT;
|
|
222
|
-
|
|
223
|
-
for (const test of testManager.getTests()) {
|
|
224
|
-
try {
|
|
225
|
-
await test.fn();
|
|
226
|
-
console.log(formatSuccessMessage(test));
|
|
227
|
-
passed++;
|
|
228
|
-
clearAllMocks();
|
|
229
|
-
} catch (error) {
|
|
230
|
-
console.log(formatFailureMessage(test, error));
|
|
231
|
-
failed++;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
console.log(getTestResultMsg(RESULT_TITLE.TESTS, passed, failed));
|
|
236
|
-
|
|
237
|
-
testManager.clearTests();
|
|
238
|
-
|
|
239
|
-
return {passed, failed};
|
|
240
|
-
};
|
|
241
|
-
|
|
243
|
+
/**
|
|
244
|
+
* 테스트 케이스를 정의합니다.
|
|
245
|
+
* @param {string} description - 테스트 설명
|
|
246
|
+
* @param {Function} fn - 테스트 함수
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* test('더하기 테스트', () => {
|
|
250
|
+
* expect(1 + 2).toBe(3);
|
|
251
|
+
* });
|
|
252
|
+
*/
|
|
242
253
|
const test = (description, fn) => testManager.test(description, fn);
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* 배열 형태의 테스트 케이스를 반복 실행합니다.
|
|
257
|
+
* @param {Array<Array>} cases - 테스트 케이스 배열
|
|
258
|
+
* @returns {Function} 테스트 실행 함수
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* test.each([
|
|
262
|
+
* [1, 2, 3],
|
|
263
|
+
* [2, 3, 5],
|
|
264
|
+
* ])('add(%s, %s) = %s', (a, b, expected) => {
|
|
265
|
+
* expect(a + b).toBe(expected);
|
|
266
|
+
* });
|
|
267
|
+
*/
|
|
243
268
|
test.each = (cases) => testManager.testEach(cases);
|
|
244
269
|
|
|
270
|
+
/**
|
|
271
|
+
* 테스트 그룹을 정의합니다. 중첩 가능합니다.
|
|
272
|
+
* @param {string} suiteName - 그룹 이름
|
|
273
|
+
* @param {Function} fn - 그룹 내부 테스트들을 정의하는 함수
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* describe('계산기', () => {
|
|
277
|
+
* test('더하기', () => {
|
|
278
|
+
* expect(1 + 1).toBe(2);
|
|
279
|
+
* });
|
|
280
|
+
* });
|
|
281
|
+
*/
|
|
245
282
|
const describe = (suiteName, fn) => testManager.describe(suiteName, fn);
|
|
246
283
|
|
|
284
|
+
/**
|
|
285
|
+
* 각 테스트 실행 전에 실행될 함수를 등록합니다.
|
|
286
|
+
* @param {Function} fn - 전처리 함수
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* describe('카운터 테스트', () => {
|
|
290
|
+
* let counter;
|
|
291
|
+
*
|
|
292
|
+
* beforeEach(() => {
|
|
293
|
+
* counter = 0;
|
|
294
|
+
* });
|
|
295
|
+
*
|
|
296
|
+
* test('초기값은 0', () => {
|
|
297
|
+
* expect(counter).toBe(0);
|
|
298
|
+
* });
|
|
299
|
+
* });
|
|
300
|
+
*/
|
|
247
301
|
const beforeEach = (fn) => testManager.beforeEach(fn);
|
|
248
302
|
|
|
303
|
+
/**
|
|
304
|
+
* 등록된 모든 테스트를 실행합니다.
|
|
305
|
+
* @returns {Promise<{passed: number, failed: number}>} 테스트 결과
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* const { passed, failed } = await run();
|
|
309
|
+
* console.log(`${passed} passed, ${failed} failed`);
|
|
310
|
+
*/
|
|
311
|
+
const run = () => testManager.run();
|
|
312
|
+
|
|
249
313
|
exports.beforeEach = beforeEach;
|
|
250
314
|
exports.clearAllMocks = clearAllMocks;
|
|
251
315
|
exports.describe = describe;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../constants.js","../src/testManager.js","../src/mock/store.js","../utils/consoleColor.js","../utils/formatString.js","../src/matchers.js","../src/expect.js","../utils/makeMessage.js","../src/testRunner.js","../index.js"],"sourcesContent":["export const RESULT_TITLE = {\n TESTS: 'Tests: ',\n TOTAL : 'Total Result: '\n};\n\nexport const CHECK = '✓ ';\n\nexport const CROSS = '✗ ';\n\nexport const DIRECTORY_DELIMITER = ' > ';\n\nexport const EMPTY = '';\n\nexport const DEFAULT_COUNT = 0;\n\nexport const COLORS = {\n reset: '\\x1b[0m',\n green: '\\x1b[32m',\n red: '\\x1b[31m',\n yellow: '\\x1b[33m',\n cyan: '\\x1b[36m',\n gray: '\\x1b[90m',\n bold: '\\x1b[1m'\n};\n\nexport const MOCK = {\n STORE_NAME: 'mockStore',\n STORE_PATH : '@dannysir/js-te/src/mock/store.js'\n};\n\nexport const BABEL = {\n MODULE: 'module',\n CONST: 'const',\n HAS: 'has',\n GET: 'get',\n PERIOD: '.',\n};\n\nexport const PATH = {\n NODE_MODULES: 'node_modules',\n TEST_DIRECTORY: 'test',\n TEST_FILE: '.test.js',\n JAVASCRIPT_FILE: '.js',\n BIN: 'bin',\n DIST: 'dist',\n};\n","import {DIRECTORY_DELIMITER} from \"../constants.js\";\n\nclass TestManager {\n #tests = [];\n #testDepth = [];\n #beforeEachArr = [];\n\n describe(str, fn) {\n this.#testDepth.push(str);\n const prevLength = this.#beforeEachArr.length;\n fn();\n this.#beforeEachArr.length = prevLength;\n this.#testDepth.pop();\n }\n\n test(description, fn) {\n const beforeEachHooks = [...this.#beforeEachArr];\n\n const testObj = {\n description,\n fn: async () => {\n for (const hook of beforeEachHooks) {\n await hook();\n }\n await fn();\n },\n path: this.#testDepth.join(DIRECTORY_DELIMITER),\n }\n this.#tests.push(testObj);\n }\n\n testEach(cases) {\n return (description, fn) => {\n cases.forEach(testCase => {\n const args = Array.isArray(testCase) ? testCase : [testCase];\n this.test(this.#formatDescription(args, description), () => fn(...args));\n });\n };\n }\n\n beforeEach(fn) {\n this.#beforeEachArr.push(fn);\n }\n\n getTests() {\n return [...this.#tests];\n }\n\n clearTests() {\n this.#tests = [];\n this.#testDepth = [];\n this.#beforeEachArr = [];\n }\n\n #formatDescription(args, description) {\n let argIndex = 0;\n return description.replace(/%([so])/g, (match, type) => {\n if (argIndex >= args.length) return match;\n\n const arg = args[argIndex++];\n\n switch (type) {\n case 's':\n return arg;\n case 'o':\n return JSON.stringify(arg);\n default:\n return match;\n }\n });\n }\n}\n\nexport const testManager = new TestManager();","export const mockStore = new Map();\n\nexport function clearAllMocks() {\n mockStore.clear();\n}\n\nexport function mock(modulePath, mockExports) {\n mockStore.set(modulePath, mockExports);\n}\n\nexport function unmock(modulePath) {\n mockStore.delete(modulePath);\n}\n\nexport function isMocked(modulePath) {\n return mockStore.has(modulePath);\n}\n","import {COLORS} from \"../constants.js\";\n\nexport const colorize = (text, color) => `${color}${text}${COLORS.reset}`;\n\nexport const green = (text) => colorize(text, COLORS.green + COLORS.bold);\nexport const red = (text) => colorize(text, COLORS.red + COLORS.bold);\nexport const bold = (text) => colorize(text, COLORS.bold);\nexport const yellow = (text) => colorize(text, COLORS.yellow + COLORS.bold);","import {CHECK, CROSS, DIRECTORY_DELIMITER, EMPTY} from \"../constants.js\";\nimport {green, red} from \"./consoleColor.js\";\n\nexport const formatSuccessMessage = (test) => {\n const pathString = test.path === '' ? EMPTY : test.path + DIRECTORY_DELIMITER;\n return green(CHECK) + pathString + test.description;\n};\n\nexport const formatFailureMessage = (test, error) => {\n const messages = [];\n messages.push(red(CROSS) + test.path + test.description);\n messages.push(red(` Error Message : ${error.message}`));\n return messages.join('\\n');\n};\n\nexport const getErrorMsg = (expect, actual) => {\n return `Expected ${JSON.stringify(expect)} but got ${JSON.stringify(actual)}`;\n};\nexport const getThrowErrorMsg = (expect) => {\n return `Expected function to throw an error containing \"${expect}\", but it did not throw`;\n};","\nimport {getErrorMsg, getThrowErrorMsg} from \"../utils/formatString.js\";\n\nconst runArgFnc = (actual) => {\n if (typeof actual === 'function') {\n return actual();\n }\n return actual;\n};\n\nexport const toBe = (actual, expected) => {\n const value = runArgFnc(actual);\n if (value !== expected) {\n throw new Error(getErrorMsg(expected, value));\n }\n};\n\nexport const toEqual = (actual, expected) => {\n const value = runArgFnc(actual);\n if (JSON.stringify(value) !== JSON.stringify(expected)) {\n throw new Error(getErrorMsg(expected, value));\n }\n};\n\nexport const toThrow = (actual, expected) => {\n try {\n runArgFnc(actual);\n } catch (e) {\n if (!e.message.includes(expected)) {\n throw new Error(getErrorMsg(expected, e.message));\n }\n return;\n }\n throw new Error(getThrowErrorMsg(expected));\n};\n\nexport const toBeTruthy = (actual) => {\n const value = runArgFnc(actual);\n if (!value) {\n throw new Error(getErrorMsg(true, value));\n }\n};\n\nexport const toBeFalsy = (actual) => {\n const value = runArgFnc(actual);\n if (value) {\n throw new Error(getErrorMsg(false, value));\n }\n};\n","import {toBe, toBeFalsy, toBeTruthy, toEqual, toThrow} from \"./matchers.js\";\n\nexport const expect = (actual) => {\n return {\n toBe(expected) {\n toBe(actual, expected);\n },\n toEqual(expected) {\n toEqual(actual, expected);\n },\n toThrow(expected) {\n toThrow(actual, expected);\n },\n toBeTruthy() {\n toBeTruthy(actual);\n },\n toBeFalsy() {\n toBeFalsy(actual);\n }\n }\n};\n","import {bold, green, red} from \"./consoleColor.js\";\n\nexport const getTestResultMsg = (title, success, fail) => {\n let msg = '\\n';\n\n msg += title;\n msg += green(success + ' passed') + ', ';\n if (fail) {\n msg += red(fail + ' failed') + ', ';\n }\n msg += bold(success + fail + ' total');\n\n return msg;\n};","import {DEFAULT_COUNT, RESULT_TITLE} from \"../constants.js\";\nimport {testManager} from \"./testManager.js\";\nimport {formatFailureMessage, formatSuccessMessage} from \"../utils/formatString.js\";\nimport {getTestResultMsg} from \"../utils/makeMessage.js\";\nimport {clearAllMocks} from \"./mock/store.js\";\n\nexport const run = async () => {\n let passed = DEFAULT_COUNT;\n let failed = DEFAULT_COUNT;\n\n for (const test of testManager.getTests()) {\n try {\n await test.fn();\n console.log(formatSuccessMessage(test));\n passed++;\n clearAllMocks();\n } catch (error) {\n console.log(formatFailureMessage(test, error));\n failed++;\n }\n }\n\n console.log(getTestResultMsg(RESULT_TITLE.TESTS, passed, failed));\n\n testManager.clearTests();\n\n return {passed, failed};\n};\n","import {testManager} from \"./src/testManager.js\";\nimport {clearAllMocks, isMocked, mock, unmock, mockStore} from './src/mock/store.js';\nimport {expect} from \"./src/expect.js\";\nimport {run} from \"./src/testRunner\";\n\nexport const test = (description, fn) => testManager.test(description, fn);\ntest.each = (cases) => testManager.testEach(cases);\n\nexport const describe = (suiteName, fn) => testManager.describe(suiteName, fn);\n\nexport const beforeEach = (fn) => testManager.beforeEach(fn);\n\nexport {expect, run};\n\nexport {mock, clearAllMocks, unmock, isMocked, mockStore};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/constants/view.js","../src/utils/consoleColor.js","../src/constants/index.js","../src/utils/formatString.js","../src/mock/store.js","../src/utils/messages.js","../src/testManager.js","../src/matchers.js","../src/expect.js","../index.js"],"sourcesContent":["export const COLORS = {\n reset: '\\x1b[0m',\n green: '\\x1b[32m',\n red: '\\x1b[31m',\n yellow: '\\x1b[33m',\n cyan: '\\x1b[36m',\n gray: '\\x1b[90m',\n bold: '\\x1b[1m'\n};\n","import {COLORS} from \"../constants/view.js\";\n\nexport const colorize = (text, color) => `${color}${text}${COLORS.reset}`;\n\nexport const green = (text) => colorize(text, COLORS.green + COLORS.bold);\nexport const red = (text) => colorize(text, COLORS.red + COLORS.bold);\nexport const bold = (text) => colorize(text, COLORS.bold);\nexport const yellow = (text) => colorize(text, COLORS.yellow + COLORS.bold);\n","export const PATH = {\n NODE_MODULES: 'node_modules',\n TEST_DIRECTORY: 'test',\n TEST_FILE: '.test.js',\n JAVASCRIPT_FILE: '.js',\n BIN: 'bin',\n DIST: 'dist',\n DANNYSIR_JS_TE: '@dannysir/js-te',\n};\n\nexport const RESULT_MSG = {\n TESTS: 'Tests: ',\n TOTAL: 'Total Result: ',\n CHECK: '✓ ',\n CROSS: '✗ ',\n DIRECTORY_DELIMITER: ' > ',\n EMPTY: '',\n};\n\nexport const NUM = {\n ZERO: 0,\n ONE: 1,\n};\n\nexport const MODULE_TYPE = {\n MODULE: 'module',\n ESM: 'esm',\n CJS: 'cjs',\n};\n","import {green, red} from \"./consoleColor.js\";\nimport {RESULT_MSG} from \"../constants/index.js\";\n\nexport const formatSuccessMessage = (test) => {\n const pathString = test.path === '' ? RESULT_MSG.EMPTY : test.path + RESULT_MSG.DIRECTORY_DELIMITER;\n return green(RESULT_MSG.CHECK) + pathString + test.description;\n};\n\nexport const formatFailureMessage = (test, error) => {\n const messages = [];\n messages.push(red(RESULT_MSG.CROSS) + test.path + test.description);\n messages.push(red(` Error Message : ${error.message}`));\n return messages.join('\\n');\n};\n\nexport const getErrorMsg = (expect, actual) => {\n return `Expected ${JSON.stringify(expect)} but got ${JSON.stringify(actual)}`;\n};\n\nexport const getThrowErrorMsg = (expect) => {\n return `Expected function to throw an error containing \"${expect}\", but it did not throw`;\n};\n\nexport const placeHolder = {\n 's': (value) => value,\n 'o': (value) => JSON.stringify(value),\n};\n\nexport const getMatcherForReplace = () => {\n return new RegExp(`%([${Object.keys(placeHolder).join('')}])`, 'g')\n};\n","export const mockStore = new Map();\n\nexport const clearAllMocks = () => {\n mockStore.clear();\n}\n\nexport const mock = (modulePath, mockExports) => {\n mockStore.set(modulePath, mockExports);\n}\n\nexport const unmock = (modulePath) => {\n mockStore.delete(modulePath);\n}\n\nexport const isMocked = (modulePath) => {\n return mockStore.has(modulePath);\n}\n","import {bold, green, red, yellow} from \"./consoleColor.js\";\n\nexport const getTestResultMsg = (title, success, fail) => {\n let msg = '\\n';\n\n msg += title;\n msg += green(success + ' passed') + ', ';\n if (fail) {\n msg += red(fail + ' failed') + ', ';\n }\n msg += bold(success + fail + ' total');\n\n return msg;\n};\n\nexport const getFileCountString = (n) => {\n return `\\nFound ${green(n)} test file(s)`;\n};\n\nexport const getFilePath = (path) => {\n return `\\n${yellow(path)}\\n`;\n};\n\nexport const getErrorMsgInLogic = (error) => {\n return red(`\\n✗ Test execution failed\\n Error: ${error}\\n`)\n};\n","import {formatFailureMessage, formatSuccessMessage, getMatcherForReplace, placeHolder} from \"./utils/formatString.js\";\nimport {clearAllMocks} from \"./mock/store.js\";\nimport {NUM, RESULT_MSG} from \"./constants/index.js\";\nimport {getTestResultMsg} from \"./utils/messages.js\";\n\nclass TestManager {\n #tests = [];\n #testDepth = [];\n #beforeEachArr = [];\n\n describe(str, fn) {\n this.#testDepth.push(str);\n const prevLength = this.#beforeEachArr.length;\n fn();\n this.#beforeEachArr.length = prevLength;\n this.#testDepth.pop();\n }\n\n test(description, fn) {\n const beforeEachHooks = [...this.#beforeEachArr];\n\n const testObj = {\n description,\n fn: async () => {\n for (const hook of beforeEachHooks) {\n await hook();\n }\n await fn();\n },\n path: this.#testDepth.join(RESULT_MSG.DIRECTORY_DELIMITER),\n }\n this.#tests.push(testObj);\n }\n\n testEach(cases) {\n return (description, fn) => {\n cases.forEach(testCase => {\n const args = Array.isArray(testCase) ? testCase : [testCase];\n this.test(this.#formatDescription(args, description), () => fn(...args));\n });\n };\n }\n\n beforeEach(fn) {\n this.#beforeEachArr.push(fn);\n }\n\n getTests() {\n return [...this.#tests];\n }\n\n clearTests() {\n this.#tests = [];\n this.#testDepth = [];\n this.#beforeEachArr = [];\n }\n\n async run() {\n let passed = NUM.ZERO;\n let failed = NUM.ZERO;\n\n for (const test of testManager.getTests()) {\n try {\n await test.fn();\n console.log(formatSuccessMessage(test));\n passed++;\n clearAllMocks();\n } catch (error) {\n console.log(formatFailureMessage(test, error));\n failed++;\n }\n }\n\n console.log(getTestResultMsg(RESULT_MSG.TESTS, passed, failed));\n\n testManager.clearTests();\n\n return {passed, failed};\n }\n\n #formatDescription(args, description) {\n let argIndex = 0;\n return description.replace(getMatcherForReplace(), (match, type) => {\n if (argIndex >= args.length) return match;\n\n const formatter = placeHolder[type];\n\n return formatter ? formatter(args[argIndex++]) : match;\n });\n }\n}\n\nexport const testManager = new TestManager();","import {getErrorMsg, getThrowErrorMsg} from \"./utils/formatString.js\";\n\nconst runArgFnc = (actual) => {\n if (typeof actual === 'function') {\n return actual();\n }\n return actual;\n};\n\nexport const toBe = (actual, expected) => {\n const value = runArgFnc(actual);\n if (value !== expected) {\n throw new Error(getErrorMsg(expected, value));\n }\n};\n\nexport const toEqual = (actual, expected) => {\n const value = runArgFnc(actual);\n if (JSON.stringify(value) !== JSON.stringify(expected)) {\n throw new Error(getErrorMsg(expected, value));\n }\n};\n\nexport const toThrow = (actual, expected) => {\n try {\n runArgFnc(actual);\n } catch (e) {\n if (!e.message.includes(expected)) {\n throw new Error(getErrorMsg(expected, e.message));\n }\n return;\n }\n throw new Error(getThrowErrorMsg(expected));\n};\n\nexport const toBeTruthy = (actual) => {\n const value = runArgFnc(actual);\n if (!value) {\n throw new Error(getErrorMsg(true, value));\n }\n};\n\nexport const toBeFalsy = (actual) => {\n const value = runArgFnc(actual);\n if (value) {\n throw new Error(getErrorMsg(false, value));\n }\n};\n","import {toBe, toBeFalsy, toBeTruthy, toEqual, toThrow} from \"./matchers.js\";\n\nexport const expect = (actual) => {\n return {\n toBe(expected) {\n toBe(actual, expected);\n },\n toEqual(expected) {\n toEqual(actual, expected);\n },\n toThrow(expected) {\n toThrow(actual, expected);\n },\n toBeTruthy() {\n toBeTruthy(actual);\n },\n toBeFalsy() {\n toBeFalsy(actual);\n }\n }\n};\n","import {testManager} from \"./src/testManager.js\";\nimport {clearAllMocks, isMocked, mock, unmock, mockStore} from './src/mock/store.js';\nimport {expect} from \"./src/expect.js\";\n\n/**\n * 테스트 케이스를 정의합니다.\n * @param {string} description - 테스트 설명\n * @param {Function} fn - 테스트 함수\n *\n * @example\n * test('더하기 테스트', () => {\n * expect(1 + 2).toBe(3);\n * });\n */\nexport const test = (description, fn) => testManager.test(description, fn);\n\n/**\n * 배열 형태의 테스트 케이스를 반복 실행합니다.\n * @param {Array<Array>} cases - 테스트 케이스 배열\n * @returns {Function} 테스트 실행 함수\n *\n * @example\n * test.each([\n * [1, 2, 3],\n * [2, 3, 5],\n * ])('add(%s, %s) = %s', (a, b, expected) => {\n * expect(a + b).toBe(expected);\n * });\n */\ntest.each = (cases) => testManager.testEach(cases);\n\n/**\n * 테스트 그룹을 정의합니다. 중첩 가능합니다.\n * @param {string} suiteName - 그룹 이름\n * @param {Function} fn - 그룹 내부 테스트들을 정의하는 함수\n *\n * @example\n * describe('계산기', () => {\n * test('더하기', () => {\n * expect(1 + 1).toBe(2);\n * });\n * });\n */\nexport const describe = (suiteName, fn) => testManager.describe(suiteName, fn);\n\n/**\n * 각 테스트 실행 전에 실행될 함수를 등록합니다.\n * @param {Function} fn - 전처리 함수\n *\n * @example\n * describe('카운터 테스트', () => {\n * let counter;\n *\n * beforeEach(() => {\n * counter = 0;\n * });\n *\n * test('초기값은 0', () => {\n * expect(counter).toBe(0);\n * });\n * });\n */\nexport const beforeEach = (fn) => testManager.beforeEach(fn);\n\n/**\n * 등록된 모든 테스트를 실행합니다.\n * @returns {Promise<{passed: number, failed: number}>} 테스트 결과\n *\n * @example\n * const { passed, failed } = await run();\n * console.log(`${passed} passed, ${failed} failed`);\n */\nexport const run = () => testManager.run();\n\n/**\n * 값을 검증하는 matcher 함수들을 반환합니다.\n * @function\n * @param {*} actual - 검증할 값\n * @returns {Object} matcher 함수들\n *\n * @example\n * expect(1 + 1).toBe(2);\n * expect([1, 2, 3]).toEqual([1, 2, 3]);\n * expect(() => { throw new Error('error') }).toThrow('error');\n * expect(true).toBeTruthy();\n * expect(false).toBeFalsy();\n */\nexport {expect};\n\nexport {mock, clearAllMocks, unmock, isMocked, mockStore};\n"],"names":[],"mappings":"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"}
|