@dannysir/js-te 0.3.1 → 0.3.3

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/dist/index.mjs CHANGED
@@ -1,27 +1,86 @@
1
- const RESULT_TITLE = {
2
- TESTS: 'Tests: '};
1
+ const COLORS = {
2
+ reset: '\x1b[0m',
3
+ green: '\x1b[32m',
4
+ red: '\x1b[31m',
5
+ bold: '\x1b[1m'
6
+ };
3
7
 
4
- const CHECK = '✓ ';
8
+ const colorize = (text, color) => `${color}${text}${COLORS.reset}`;
5
9
 
6
- const CROSS = '✗ ';
10
+ const green = (text) => colorize(text, COLORS.green + COLORS.bold);
11
+ const red = (text) => colorize(text, COLORS.red + COLORS.bold);
12
+ const bold = (text) => colorize(text, COLORS.bold);
7
13
 
8
- const DIRECTORY_DELIMITER = ' > ';
14
+ const RESULT_MSG = {
15
+ TESTS: 'Tests: ',
16
+ CHECK: '✓ ',
17
+ CROSS: '✗ ',
18
+ DIRECTORY_DELIMITER: ' > ',
19
+ EMPTY: '',
20
+ };
9
21
 
10
- const EMPTY = '';
22
+ const NUM = {
23
+ ZERO: 0};
11
24
 
12
- const DEFAULT_COUNT = 0;
25
+ const formatSuccessMessage = (test) => {
26
+ const pathString = test.path === '' ? RESULT_MSG.EMPTY : test.path + RESULT_MSG.DIRECTORY_DELIMITER;
27
+ return green(RESULT_MSG.CHECK) + pathString + test.description;
28
+ };
13
29
 
14
- const COLORS = {
15
- reset: '\x1b[0m',
16
- green: '\x1b[32m',
17
- red: '\x1b[31m',
18
- bold: '\x1b[1m'
30
+ const formatFailureMessage = (test, error) => {
31
+ const messages = [];
32
+ messages.push(red(RESULT_MSG.CROSS) + test.path + test.description);
33
+ messages.push(red(` Error Message : ${error.message}`));
34
+ return messages.join('\n');
35
+ };
36
+
37
+ const formatErrorMsg = (expect, actual) => {
38
+ return `Expected ${JSON.stringify(expect)} but got ${JSON.stringify(actual)}`;
39
+ };
40
+
41
+ const formatThrowErrorMsg = (expect) => {
42
+ return `Expected function to throw an error containing "${expect}", but it did not throw`;
43
+ };
44
+
45
+ const mockStore = new Map();
46
+
47
+ const clearAllMocks = () => {
48
+ mockStore.clear();
49
+ };
50
+
51
+ const mock = (modulePath, mockExports) => {
52
+ mockStore.set(modulePath, mockExports);
53
+ };
54
+
55
+ const unmock = (modulePath) => {
56
+ mockStore.delete(modulePath);
57
+ };
58
+
59
+ const isMocked = (modulePath) => {
60
+ return mockStore.has(modulePath);
61
+ };
62
+
63
+ const getTestResultMsg = (title, success, fail) => {
64
+ let msg = '\n';
65
+
66
+ msg += title;
67
+ msg += green(success + ' passed') + ', ';
68
+ if (fail) {
69
+ msg += red(fail + ' failed') + ', ';
70
+ }
71
+ msg += bold(success + fail + ' total');
72
+
73
+ return msg;
19
74
  };
20
75
 
21
76
  class TestManager {
22
77
  #tests = [];
23
78
  #testDepth = [];
24
79
  #beforeEachArr = [];
80
+ #placeHolder = {
81
+ 's': (value) => value,
82
+ 'o': (value) => JSON.stringify(value),
83
+ };
25
84
 
26
85
  describe(str, fn) {
27
86
  this.#testDepth.push(str);
@@ -42,7 +101,7 @@ class TestManager {
42
101
  }
43
102
  await fn();
44
103
  },
45
- path: this.#testDepth.join(DIRECTORY_DELIMITER),
104
+ path: this.#testDepth.join(RESULT_MSG.DIRECTORY_DELIMITER),
46
105
  };
47
106
  this.#tests.push(testObj);
48
107
  }
@@ -70,70 +129,47 @@ class TestManager {
70
129
  this.#beforeEachArr = [];
71
130
  }
72
131
 
132
+ async run() {
133
+ let passed = NUM.ZERO;
134
+ let failed = NUM.ZERO;
135
+
136
+ for (const test of testManager.getTests()) {
137
+ try {
138
+ await test.fn();
139
+ console.log(formatSuccessMessage(test));
140
+ passed++;
141
+ clearAllMocks();
142
+ } catch (error) {
143
+ console.log(formatFailureMessage(test, error));
144
+ failed++;
145
+ }
146
+ }
147
+
148
+ console.log(getTestResultMsg(RESULT_MSG.TESTS, passed, failed));
149
+
150
+ testManager.clearTests();
151
+
152
+ return {passed, failed};
153
+ }
154
+
155
+ #getMatcherForReplace = () => {
156
+ return new RegExp(`%([${Object.keys(this.#placeHolder).join('')}])`, 'g')
157
+ };
158
+
73
159
  #formatDescription(args, description) {
74
160
  let argIndex = 0;
75
- return description.replace(/%([so])/g, (match, type) => {
161
+ return description.replace(this.#getMatcherForReplace(), (match, type) => {
76
162
  if (argIndex >= args.length) return match;
77
163
 
78
- const arg = args[argIndex++];
164
+ const formatter = this.#placeHolder[type];
79
165
 
80
- switch (type) {
81
- case 's':
82
- return arg;
83
- case 'o':
84
- return JSON.stringify(arg);
85
- default:
86
- return match;
87
- }
166
+ return formatter ? formatter(args[argIndex++]) : match;
88
167
  });
89
168
  }
90
169
  }
91
170
 
92
171
  const testManager = new TestManager();
93
172
 
94
- const mockStore = new Map();
95
-
96
- function clearAllMocks() {
97
- mockStore.clear();
98
- }
99
-
100
- function mock(modulePath, mockExports) {
101
- mockStore.set(modulePath, mockExports);
102
- }
103
-
104
- function unmock(modulePath) {
105
- mockStore.delete(modulePath);
106
- }
107
-
108
- function isMocked(modulePath) {
109
- return mockStore.has(modulePath);
110
- }
111
-
112
- const colorize = (text, color) => `${color}${text}${COLORS.reset}`;
113
-
114
- const green = (text) => colorize(text, COLORS.green + COLORS.bold);
115
- const red = (text) => colorize(text, COLORS.red + COLORS.bold);
116
- const bold = (text) => colorize(text, COLORS.bold);
117
-
118
- const formatSuccessMessage = (test) => {
119
- const pathString = test.path === '' ? EMPTY : test.path + DIRECTORY_DELIMITER;
120
- return green(CHECK) + pathString + test.description;
121
- };
122
-
123
- const formatFailureMessage = (test, error) => {
124
- const messages = [];
125
- messages.push(red(CROSS) + test.path + test.description);
126
- messages.push(red(` Error Message : ${error.message}`));
127
- return messages.join('\n');
128
- };
129
-
130
- const getErrorMsg = (expect, actual) => {
131
- return `Expected ${JSON.stringify(expect)} but got ${JSON.stringify(actual)}`;
132
- };
133
- const getThrowErrorMsg = (expect) => {
134
- return `Expected function to throw an error containing "${expect}", but it did not throw`;
135
- };
136
-
137
173
  const runArgFnc = (actual) => {
138
174
  if (typeof actual === 'function') {
139
175
  return actual();
@@ -144,14 +180,14 @@ const runArgFnc = (actual) => {
144
180
  const toBe = (actual, expected) => {
145
181
  const value = runArgFnc(actual);
146
182
  if (value !== expected) {
147
- throw new Error(getErrorMsg(expected, value));
183
+ throw new Error(formatErrorMsg(expected, value));
148
184
  }
149
185
  };
150
186
 
151
187
  const toEqual = (actual, expected) => {
152
188
  const value = runArgFnc(actual);
153
189
  if (JSON.stringify(value) !== JSON.stringify(expected)) {
154
- throw new Error(getErrorMsg(expected, value));
190
+ throw new Error(formatErrorMsg(expected, value));
155
191
  }
156
192
  };
157
193
 
@@ -160,24 +196,24 @@ const toThrow = (actual, expected) => {
160
196
  runArgFnc(actual);
161
197
  } catch (e) {
162
198
  if (!e.message.includes(expected)) {
163
- throw new Error(getErrorMsg(expected, e.message));
199
+ throw new Error(formatErrorMsg(expected, e.message));
164
200
  }
165
201
  return;
166
202
  }
167
- throw new Error(getThrowErrorMsg(expected));
203
+ throw new Error(formatThrowErrorMsg(expected));
168
204
  };
169
205
 
170
206
  const toBeTruthy = (actual) => {
171
207
  const value = runArgFnc(actual);
172
208
  if (!value) {
173
- throw new Error(getErrorMsg(true, value));
209
+ throw new Error(formatErrorMsg(true, value));
174
210
  }
175
211
  };
176
212
 
177
213
  const toBeFalsy = (actual) => {
178
214
  const value = runArgFnc(actual);
179
215
  if (value) {
180
- throw new Error(getErrorMsg(false, value));
216
+ throw new Error(formatErrorMsg(false, value));
181
217
  }
182
218
  };
183
219
 
@@ -201,48 +237,75 @@ const expect = (actual) => {
201
237
  }
202
238
  };
203
239
 
204
- const getTestResultMsg = (title, success, fail) => {
205
- let msg = '\n';
206
-
207
- msg += title;
208
- msg += green(success + ' passed') + ', ';
209
- if (fail) {
210
- msg += red(fail + ' failed') + ', ';
211
- }
212
- msg += bold(success + fail + ' total');
213
-
214
- return msg;
215
- };
216
-
217
- const run = async () => {
218
- let passed = DEFAULT_COUNT;
219
- let failed = DEFAULT_COUNT;
220
-
221
- for (const test of testManager.getTests()) {
222
- try {
223
- await test.fn();
224
- console.log(formatSuccessMessage(test));
225
- passed++;
226
- clearAllMocks();
227
- } catch (error) {
228
- console.log(formatFailureMessage(test, error));
229
- failed++;
230
- }
231
- }
232
-
233
- console.log(getTestResultMsg(RESULT_TITLE.TESTS, passed, failed));
234
-
235
- testManager.clearTests();
236
-
237
- return {passed, failed};
238
- };
239
-
240
+ /**
241
+ * 테스트 케이스를 정의합니다.
242
+ * @param {string} description - 테스트 설명
243
+ * @param {Function} fn - 테스트 함수
244
+ *
245
+ * @example
246
+ * test('더하기 테스트', () => {
247
+ * expect(1 + 2).toBe(3);
248
+ * });
249
+ */
240
250
  const test = (description, fn) => testManager.test(description, fn);
251
+
252
+ /**
253
+ * 배열 형태의 테스트 케이스를 반복 실행합니다.
254
+ * @param {Array<Array>} cases - 테스트 케이스 배열
255
+ * @returns {Function} 테스트 실행 함수
256
+ *
257
+ * @example
258
+ * test.each([
259
+ * [1, 2, 3],
260
+ * [2, 3, 5],
261
+ * ])('add(%s, %s) = %s', (a, b, expected) => {
262
+ * expect(a + b).toBe(expected);
263
+ * });
264
+ */
241
265
  test.each = (cases) => testManager.testEach(cases);
242
266
 
267
+ /**
268
+ * 테스트 그룹을 정의합니다. 중첩 가능합니다.
269
+ * @param {string} suiteName - 그룹 이름
270
+ * @param {Function} fn - 그룹 내부 테스트들을 정의하는 함수
271
+ *
272
+ * @example
273
+ * describe('계산기', () => {
274
+ * test('더하기', () => {
275
+ * expect(1 + 1).toBe(2);
276
+ * });
277
+ * });
278
+ */
243
279
  const describe = (suiteName, fn) => testManager.describe(suiteName, fn);
244
280
 
281
+ /**
282
+ * 각 테스트 실행 전에 실행될 함수를 등록합니다.
283
+ * @param {Function} fn - 전처리 함수
284
+ *
285
+ * @example
286
+ * describe('카운터 테스트', () => {
287
+ * let counter;
288
+ *
289
+ * beforeEach(() => {
290
+ * counter = 0;
291
+ * });
292
+ *
293
+ * test('초기값은 0', () => {
294
+ * expect(counter).toBe(0);
295
+ * });
296
+ * });
297
+ */
245
298
  const beforeEach = (fn) => testManager.beforeEach(fn);
246
299
 
300
+ /**
301
+ * 등록된 모든 테스트를 실행합니다.
302
+ * @returns {Promise<{passed: number, failed: number}>} 테스트 결과
303
+ *
304
+ * @example
305
+ * const { passed, failed } = await run();
306
+ * console.log(`${passed} passed, ${failed} failed`);
307
+ */
308
+ const run = () => testManager.run();
309
+
247
310
  export { beforeEach, clearAllMocks, describe, expect, isMocked, mock, mockStore, run, test, unmock };
248
311
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","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.mjs","sources":["../src/constants/view.js","../src/utils/consoleColor.js","../src/constants/index.js","../src/utils/formatString.js","../src/mock/store.js","../src/cli/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 formatErrorMsg = (expect, actual) => {\n return `Expected ${JSON.stringify(expect)} but got ${JSON.stringify(actual)}`;\n};\n\nexport const formatThrowErrorMsg = (expect) => {\n return `Expected function to throw an error containing \"${expect}\", but it did not throw`;\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 \"../../utils/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} from \"./utils/formatString.js\";\nimport {clearAllMocks} from \"./mock/store.js\";\nimport {NUM, RESULT_MSG} from \"./constants/index.js\";\nimport {getTestResultMsg} from \"./cli/utils/messages.js\";\n\nclass TestManager {\n #tests = [];\n #testDepth = [];\n #beforeEachArr = [];\n #placeHolder = {\n 's': (value) => value,\n 'o': (value) => JSON.stringify(value),\n };\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 #getMatcherForReplace = () => {\n return new RegExp(`%([${Object.keys(this.#placeHolder).join('')}])`, 'g')\n };\n\n #formatDescription(args, description) {\n let argIndex = 0;\n return description.replace(this.#getMatcherForReplace(), (match, type) => {\n if (argIndex >= args.length) return match;\n\n const formatter = this.#placeHolder[type];\n\n return formatter ? formatter(args[argIndex++]) : match;\n });\n }\n}\n\nexport const testManager = new TestManager();","import {formatErrorMsg, formatThrowErrorMsg} 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(formatErrorMsg(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(formatErrorMsg(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(formatErrorMsg(expected, e.message));\n }\n return;\n }\n throw new Error(formatThrowErrorMsg(expected));\n};\n\nexport const toBeTruthy = (actual) => {\n const value = runArgFnc(actual);\n if (!value) {\n throw new Error(formatErrorMsg(true, value));\n }\n};\n\nexport const toBeFalsy = (actual) => {\n const value = runArgFnc(actual);\n if (value) {\n throw new Error(formatErrorMsg(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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"}
package/index.js ADDED
@@ -0,0 +1,90 @@
1
+ import {testManager} from "./src/testManager.js";
2
+ import {clearAllMocks, isMocked, mock, unmock, mockStore} from './src/mock/store.js';
3
+ import {expect} from "./src/expect.js";
4
+
5
+ /**
6
+ * 테스트 케이스를 정의합니다.
7
+ * @param {string} description - 테스트 설명
8
+ * @param {Function} fn - 테스트 함수
9
+ *
10
+ * @example
11
+ * test('더하기 테스트', () => {
12
+ * expect(1 + 2).toBe(3);
13
+ * });
14
+ */
15
+ export const test = (description, fn) => testManager.test(description, fn);
16
+
17
+ /**
18
+ * 배열 형태의 테스트 케이스를 반복 실행합니다.
19
+ * @param {Array<Array>} cases - 테스트 케이스 배열
20
+ * @returns {Function} 테스트 실행 함수
21
+ *
22
+ * @example
23
+ * test.each([
24
+ * [1, 2, 3],
25
+ * [2, 3, 5],
26
+ * ])('add(%s, %s) = %s', (a, b, expected) => {
27
+ * expect(a + b).toBe(expected);
28
+ * });
29
+ */
30
+ test.each = (cases) => testManager.testEach(cases);
31
+
32
+ /**
33
+ * 테스트 그룹을 정의합니다. 중첩 가능합니다.
34
+ * @param {string} suiteName - 그룹 이름
35
+ * @param {Function} fn - 그룹 내부 테스트들을 정의하는 함수
36
+ *
37
+ * @example
38
+ * describe('계산기', () => {
39
+ * test('더하기', () => {
40
+ * expect(1 + 1).toBe(2);
41
+ * });
42
+ * });
43
+ */
44
+ export const describe = (suiteName, fn) => testManager.describe(suiteName, fn);
45
+
46
+ /**
47
+ * 각 테스트 실행 전에 실행될 함수를 등록합니다.
48
+ * @param {Function} fn - 전처리 함수
49
+ *
50
+ * @example
51
+ * describe('카운터 테스트', () => {
52
+ * let counter;
53
+ *
54
+ * beforeEach(() => {
55
+ * counter = 0;
56
+ * });
57
+ *
58
+ * test('초기값은 0', () => {
59
+ * expect(counter).toBe(0);
60
+ * });
61
+ * });
62
+ */
63
+ export const beforeEach = (fn) => testManager.beforeEach(fn);
64
+
65
+ /**
66
+ * 등록된 모든 테스트를 실행합니다.
67
+ * @returns {Promise<{passed: number, failed: number}>} 테스트 결과
68
+ *
69
+ * @example
70
+ * const { passed, failed } = await run();
71
+ * console.log(`${passed} passed, ${failed} failed`);
72
+ */
73
+ export const run = () => testManager.run();
74
+
75
+ /**
76
+ * 값을 검증하는 matcher 함수들을 반환합니다.
77
+ * @function
78
+ * @param {*} actual - 검증할 값
79
+ * @returns {Object} matcher 함수들
80
+ *
81
+ * @example
82
+ * expect(1 + 1).toBe(2);
83
+ * expect([1, 2, 3]).toEqual([1, 2, 3]);
84
+ * expect(() => { throw new Error('error') }).toThrow('error');
85
+ * expect(true).toBeTruthy();
86
+ * expect(false).toBeFalsy();
87
+ */
88
+ export {expect};
89
+
90
+ export {mock, clearAllMocks, unmock, isMocked, mockStore};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dannysir/js-te",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "JavaScript test library",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -24,11 +24,8 @@
24
24
  "files": [
25
25
  "bin/",
26
26
  "dist/",
27
- "utils/",
28
27
  "src/",
29
- "babelTransformImport.js",
30
- "babelCollectMocks.js",
31
- "constants.js"
28
+ "index.js"
32
29
  ],
33
30
  "keywords": [
34
31
  "javascript",
@@ -1,5 +1,6 @@
1
1
  import path from 'path';
2
- import { BABEL } from "./constants.js";
2
+
3
+ import {BABEL} from "../constants/babel.js";
3
4
 
4
5
  export const createMockCollectorPlugin = (mockedPaths) => {
5
6
  return ({types: t}) => {