@nudojs/cli 0.2.1 → 0.3.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.
Files changed (64) hide show
  1. package/dist/{chunk-3HCPXPEW.js → chunk-YDM4HHQ4.js} +1783 -1421
  2. package/dist/evaluator-api.d.ts +12 -1
  3. package/dist/evaluator-api.js +52 -2
  4. package/dist/index.d.ts +1 -2
  5. package/dist/index.js +366 -3572
  6. package/package.json +23 -11
  7. package/CHANGELOG.md +0 -41
  8. package/examples/real-world.js +0 -66
  9. package/examples/validate-real-world.ts +0 -160
  10. package/src/__tests__/builtin-advanced.test.ts +0 -292
  11. package/src/__tests__/builtin-api.test.ts +0 -308
  12. package/src/__tests__/builtin-functions.test.ts +0 -313
  13. package/src/__tests__/builtin-map.test.ts +0 -129
  14. package/src/__tests__/builtin-promise.test.ts +0 -150
  15. package/src/__tests__/builtin-regexp.test.ts +0 -133
  16. package/src/__tests__/builtin-set.test.ts +0 -163
  17. package/src/__tests__/builtin-url.test.ts +0 -256
  18. package/src/__tests__/builtin-web.test.ts +0 -340
  19. package/src/__tests__/combination-scenarios.test.ts +0 -384
  20. package/src/__tests__/edge-cases.test.ts +0 -749
  21. package/src/__tests__/evaluator-loops.test.ts +0 -283
  22. package/src/__tests__/evaluator-nullish-coalescing.test.ts +0 -86
  23. package/src/__tests__/evaluator-optional-chaining.test.ts +0 -37
  24. package/src/__tests__/evaluator-phase2.test.ts +0 -564
  25. package/src/__tests__/evaluator-phase3.test.ts +0 -864
  26. package/src/__tests__/evaluator-refined.test.ts +0 -121
  27. package/src/__tests__/evaluator-string-methods.test.ts +0 -151
  28. package/src/__tests__/evaluator.test.ts +0 -943
  29. package/src/__tests__/mock-arrow-function.test.ts +0 -169
  30. package/src/__tests__/mock-comparison.test.ts +0 -221
  31. package/src/__tests__/mock-comprehensive.test.ts +0 -250
  32. package/src/__tests__/mock-final-integration.test.ts +0 -263
  33. package/src/__tests__/mock-helpers.test.ts +0 -174
  34. package/src/__tests__/mock-realworld.test.ts +0 -191
  35. package/src/__tests__/mock-rest-debug.test.ts +0 -110
  36. package/src/__tests__/mock-rest-edge.test.ts +0 -176
  37. package/src/__tests__/mock-sinon-runtime.test.ts +0 -168
  38. package/src/__tests__/narrowing-discriminated.test.ts +0 -35
  39. package/src/__tests__/narrowing-in-operator.test.ts +0 -56
  40. package/src/__tests__/narrowing-switch.test.ts +0 -56
  41. package/src/__tests__/narrowing-truthiness.test.ts +0 -52
  42. package/src/__tests__/narrowing.test.ts +0 -82
  43. package/src/__tests__/nudo-mock-syntax.test.ts +0 -245
  44. package/src/__tests__/realworld-patterns.test.ts +0 -430
  45. package/src/__tests__/syntax-sugar.test.ts +0 -345
  46. package/src/builtins/builtin-intl.ts +0 -17
  47. package/src/builtins/builtin-map.ts +0 -174
  48. package/src/builtins/builtin-promise.ts +0 -116
  49. package/src/builtins/builtin-reflect.ts +0 -30
  50. package/src/builtins/builtin-regexp.ts +0 -34
  51. package/src/builtins/builtin-set.ts +0 -131
  52. package/src/builtins/builtin-symbol.ts +0 -16
  53. package/src/builtins/builtin-url.ts +0 -58
  54. package/src/builtins/builtin-weak.ts +0 -22
  55. package/src/builtins/builtin-web.ts +0 -111
  56. package/src/builtins/index.ts +0 -61
  57. package/src/config.ts +0 -32
  58. package/src/env-loader.ts +0 -174
  59. package/src/evaluator-api.ts +0 -36
  60. package/src/evaluator.ts +0 -5623
  61. package/src/index.ts +0 -931
  62. package/src/narrowing.ts +0 -537
  63. package/src/resolve-npm.ts +0 -63
  64. package/tsconfig.json +0 -9
@@ -1,263 +0,0 @@
1
- import { describe, it, expect, beforeAll } from "vitest";
2
- import { parse, extractDirectives, type CaseDirective, parseTypeValueExpr } from "@nudojs/parser";
3
- import { typeValueToString, createEnvironment, T } from "@nudojs/core";
4
- import { evaluateFunctionFull } from "../evaluator.js";
5
-
6
- function runTest(source: string): { name: string; caseName: string; result: string }[] {
7
- const ast = parse(source);
8
- const directives = extractDirectives(ast);
9
- const env = createEnvironment();
10
- const results: { name: string; caseName: string; result: string }[] = [];
11
-
12
- for (const fn of directives) {
13
- for (const d of fn.directives) {
14
- if (d.kind === "mock") {
15
- if (d.arrowFn) {
16
- const fnType = T.fn(d.arrowFn.params, d.arrowFn.body, env);
17
- (fnType as any)._paramPatterns = d.arrowFn.paramPatterns;
18
- env.bind(d.name, fnType);
19
- } else if (d.sinonExpr) {
20
- const body = { type: "BlockStatement", body: [] };
21
- const mockFn = T.fn(["...args"], body, env);
22
- if (d.sinonExpr.returnValue) {
23
- (mockFn as any)._directReturn = d.sinonExpr.returnValue;
24
- } else if (d.sinonExpr.resolvedValue) {
25
- (mockFn as any)._directReturn = T.promise(d.sinonExpr.resolvedValue);
26
- } else {
27
- (mockFn as any)._directReturn = T.unknown;
28
- }
29
- env.bind(d.name, mockFn);
30
- } else if (d.expression) {
31
- env.bind(d.name, parseTypeValueExpr(d.expression));
32
- }
33
- }
34
- }
35
-
36
- const caseDirectives = fn.directives.filter((d): d is CaseDirective => d.kind === "case");
37
- for (const dir of caseDirectives) {
38
- const result = evaluateFunctionFull(fn.node, dir.args, env);
39
- results.push({
40
- name: fn.name,
41
- caseName: dir.name,
42
- result: typeValueToString(result.value),
43
- });
44
- }
45
- }
46
- return results;
47
- }
48
-
49
- describe("Final Integration Test - All Mock Features", () => {
50
- const source = `
51
- // 1. 基础箭头函数 Mock - filter
52
- // @nudo:mock predicate = (x) => x > 3
53
- // @nudo:case "filter" ([1, 2, 3, 4, 5])
54
- function filterGreater(arr) {
55
- const result = [];
56
- for (const item of arr) {
57
- if (predicate(item)) result.push(item);
58
- }
59
- return result;
60
- }
61
-
62
- // 2. 基础箭头函数 Mock - map
63
- // @nudo:mock transform = (x) => x * 2
64
- // @nudo:case "map" ([1, 2, 3])
65
- function doubleAll(arr) {
66
- return arr.map(transform);
67
- }
68
-
69
- // 3. 基础箭头函数 Mock - reduce
70
- // @nudo:mock reducer = (a, b) => a + b
71
- // @nudo:case "reduce" ([1, 2, 3, 4])
72
- function sumAll(arr) {
73
- return arr.reduce(reducer, 0);
74
- }
75
-
76
- // 4. 多参数 Mock
77
- // @nudo:mock combine = (a, b) => a + b * 10
78
- // @nudo:case "combine" (3, 4)
79
- function combineNums(a, b) {
80
- return combine(a, b);
81
- }
82
-
83
- // 5. 函数组合
84
- // @nudo:mock f = (x) => x + 1
85
- // @nudo:mock g = (x) => x * 2
86
- // @nudo:case "compose" (5)
87
- function compose(x) {
88
- return f(g(x));
89
- }
90
-
91
- // 6. 回调模式
92
- // @nudo:mock callback = (result) => result * 2
93
- // @nudo:case "callback" (21)
94
- function processWithCallback(x) {
95
- return callback(x);
96
- }
97
-
98
- // 7. 类型收窄 - string
99
- // @nudo:mock processor = (x) => typeof x === "string" ? x.toUpperCase() : x
100
- // @nudo:case "string" ("hello")
101
- // @nudo:case "number" (42)
102
- function process(x) {
103
- return processor(x);
104
- }
105
-
106
- // 8. 对象返回
107
- // @nudo:mock makeUser = (name, age) => ({ name, age, isAdult: age >= 18 })
108
- // @nudo:case "user" ("Alice", 25)
109
- function createUser(name, age) {
110
- return makeUser(name, age);
111
- }
112
-
113
- // 9. 数组解构
114
- // @nudo:mock swap = ([a, b]) => [b, a]
115
- // @nudo:case "swap" ([1, 2])
116
- function swapPair(pair) {
117
- return swap(pair);
118
- }
119
-
120
- // 10. 对象解构
121
- // @nudo:mock getFullName = ({first, last}) => first + " " + last
122
- // @nudo:case "name" ({first: "John", last: "Doe"})
123
- function fullName(obj) {
124
- return getFullName(obj);
125
- }
126
-
127
- // 11. Rest 参数
128
- // @nudo:mock sum = (...args) => args.length
129
- // @nudo:case "rest" (1, 2, 3)
130
- function countArgs() {
131
- return sum(1, 2, 3);
132
- }
133
-
134
- // 12. 条件逻辑
135
- // @nudo:mock validator = (x) => x > 0 && x < 100
136
- // @nudo:case "valid" (50)
137
- // @nudo:case "invalid" (150)
138
- function validate(x) {
139
- return validator(x);
140
- }
141
-
142
- // 13. 嵌套函数调用
143
- // @nudo:mock double = (x) => x * 2
144
- // @nudo:mock addTen = (x) => x + 10
145
- // @nudo:case "nested" (5)
146
- function nestedCalls(x) {
147
- return addTen(double(x));
148
- }
149
-
150
- // 14. 无参数 Mock
151
- // @nudo:mock getRandom = () => 42
152
- // @nudo:case "noargs" ()
153
- function getValue() {
154
- return getRandom();
155
- }
156
-
157
- // 15. Sinon Mock
158
- // @nudo:mock fetch = sinon.stub()
159
- // @nudo:case "sinon" ("/api/data")
160
- function getData(url) {
161
- return fetch(url);
162
- }
163
- `;
164
-
165
- let results: { name: string; caseName: string; result: string }[];
166
-
167
- beforeAll(() => {
168
- results = runTest(source);
169
- });
170
-
171
- it("1. filter with predicate", () => {
172
- const r = results.find(r => r.caseName === "filter")!;
173
- expect(r.result).toBe("[4, 5]");
174
- });
175
-
176
- it("2. map with transform", () => {
177
- const r = results.find(r => r.caseName === "map")!;
178
- expect(r.result).toBe("[2, 4, 6]");
179
- });
180
-
181
- it("3. reduce with reducer", () => {
182
- const r = results.find(r => r.caseName === "reduce")!;
183
- expect(r.result).toBe("10");
184
- });
185
-
186
- it("4. multi-parameter mock", () => {
187
- const r = results.find(r => r.caseName === "combine")!;
188
- expect(r.result).toBe("43");
189
- });
190
-
191
- it("5. function composition", () => {
192
- const r = results.find(r => r.caseName === "compose")!;
193
- expect(r.result).toBe("11");
194
- });
195
-
196
- it("6. callback pattern", () => {
197
- const r = results.find(r => r.caseName === "callback")!;
198
- expect(r.result).toBe("42");
199
- });
200
-
201
- it("7a. type narrowing - string", () => {
202
- const r = results.find(r => r.caseName === "string")!;
203
- expect(r.result).toBe('"HELLO"');
204
- });
205
-
206
- it("7b. type narrowing - number", () => {
207
- const r = results.find(r => r.caseName === "number")!;
208
- expect(r.result).toBe("42");
209
- });
210
-
211
- it("8. object return", () => {
212
- const r = results.find(r => r.caseName === "user")!;
213
- expect(r.result).toBe('{ name: "Alice", age: 25, isAdult: true }');
214
- });
215
-
216
- it("9. array destructuring", () => {
217
- const r = results.find(r => r.caseName === "swap")!;
218
- expect(r.result).toBe("[2, 1]");
219
- });
220
-
221
- it("10. object destructuring", () => {
222
- const r = results.find(r => r.caseName === "name")!;
223
- expect(r.result).toBe('"John Doe"');
224
- });
225
-
226
- it("11. rest parameters", () => {
227
- const r = results.find(r => r.caseName === "rest")!;
228
- expect(r.result).toBe("3");
229
- });
230
-
231
- it("12a. conditional - valid", () => {
232
- const r = results.find(r => r.caseName === "valid")!;
233
- expect(r.result).toBe("true");
234
- });
235
-
236
- it("12b. conditional - invalid", () => {
237
- const r = results.find(r => r.caseName === "invalid")!;
238
- expect(r.result).toBe("false");
239
- });
240
-
241
- it("13. nested function calls", () => {
242
- const r = results.find(r => r.caseName === "nested")!;
243
- expect(r.result).toBe("20");
244
- });
245
-
246
- it("14. no-args mock", () => {
247
- const r = results.find(r => r.caseName === "noargs")!;
248
- expect(r.result).toBe("42");
249
- });
250
-
251
- it("15. sinon stub (returns unknown)", () => {
252
- const r = results.find(r => r.caseName === "sinon")!;
253
- expect(r.result).toBe("unknown");
254
- });
255
-
256
- it("all tests passed", () => {
257
- console.log("\n=== 最终测试结果 ===");
258
- for (const r of results) {
259
- console.log(`${r.name} - ${r.caseName}: ${r.result}`);
260
- }
261
- console.log(`\n总计: ${results.length} 个测试用例`);
262
- });
263
- });
@@ -1,174 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { parse, extractDirectives, type CaseDirective, parseTypeValueExpr } from "@nudojs/parser";
3
- import { typeValueToString, createEnvironment, T, stub, spy, mock, mockHelperToTypeValue } from "@nudojs/core";
4
- import { evaluateFunctionFull } from "../evaluator.js";
5
-
6
- function runNudoTest(source: string): { name: string; caseName: string; result: string }[] {
7
- const ast = parse(source);
8
- const directives = extractDirectives(ast);
9
- const env = createEnvironment();
10
- const results: { name: string; caseName: string; result: string }[] = [];
11
-
12
- for (const fn of directives) {
13
- for (const d of fn.directives) {
14
- if (d.kind === "mock") {
15
- if (d.arrowFn) {
16
- const fnType = T.fn(d.arrowFn.params, d.arrowFn.body, env);
17
- (fnType as any)._paramPatterns = d.arrowFn.paramPatterns;
18
- env.bind(d.name, fnType);
19
- } else if (d.nudoMock) {
20
- const typeVal = mockHelperToTypeValue(d.nudoMock, env);
21
- env.bind(d.name, typeVal);
22
- } else if (d.expression) {
23
- env.bind(d.name, parseTypeValueExpr(d.expression));
24
- }
25
- }
26
- }
27
-
28
- const caseDirectives = fn.directives.filter((d): d is CaseDirective => d.kind === "case");
29
- for (const dir of caseDirectives) {
30
- const result = evaluateFunctionFull(fn.node, dir.args, env);
31
- results.push({
32
- name: fn.name,
33
- caseName: dir.name,
34
- result: typeValueToString(result.value),
35
- });
36
- }
37
- }
38
- return results;
39
- }
40
-
41
- describe("Mock Helper Functions", () => {
42
- describe("mockHelperToTypeValue", () => {
43
- it("stub() should create a function returning unknown", () => {
44
- const env = createEnvironment();
45
- const helper = stub();
46
- const typeVal = mockHelperToTypeValue(helper, env);
47
- expect(typeVal.kind).toBe("function");
48
- expect((typeVal as any)._directReturn.kind).toBe("unknown");
49
- });
50
-
51
- it("stub().returns(T.number) should create a function returning number", () => {
52
- const env = createEnvironment();
53
- const helper = stub.returns(T.number);
54
- const typeVal = mockHelperToTypeValue(helper, env);
55
- expect(typeVal.kind).toBe("function");
56
- expect((typeVal as any)._directReturn.kind).toBe("primitive");
57
- });
58
-
59
- it("stub().resolves(T.string) should create a function returning promise<string>", () => {
60
- const env = createEnvironment();
61
- const helper = stub.resolves(T.string);
62
- const typeVal = mockHelperToTypeValue(helper, env);
63
- expect(typeVal.kind).toBe("function");
64
- expect((typeVal as any)._directReturn.kind).toBe("promise");
65
- });
66
-
67
- it("spy() should create a function returning unknown", () => {
68
- const env = createEnvironment();
69
- const helper = spy();
70
- const typeVal = mockHelperToTypeValue(helper, env);
71
- expect(typeVal.kind).toBe("function");
72
- });
73
-
74
- it("mock() should create a function returning unknown", () => {
75
- const env = createEnvironment();
76
- const helper = mock();
77
- const typeVal = mockHelperToTypeValue(helper, env);
78
- expect(typeVal.kind).toBe("function");
79
- });
80
- });
81
-
82
- describe("Mock helpers through evaluator", () => {
83
- it("stub().returns with arrow function mock should work", () => {
84
- // The existing arrow function syntax already works - this is the baseline
85
- const results = runNudoTest(`
86
- // @nudo:mock handler = (x) => x * 2
87
- // @nudo:case "double" (21)
88
- function double(x) {
89
- return handler(x);
90
- }
91
- `);
92
- expect(results[0].result).toBe("42");
93
- });
94
-
95
- it("stub with _directReturn should work in evaluator", () => {
96
- // Simulate what happens when a mock helper is bound to an env var
97
- const env = createEnvironment();
98
- const helper = stub.returns(T.number);
99
- const typeVal = mockHelperToTypeValue(helper, env);
100
- env.bind("myStub", typeVal);
101
-
102
- // The evaluator should see _directReturn and return number
103
- const ast = parse(`
104
- // @nudo:case "test" ()
105
- function testFn() {
106
- return myStub();
107
- }
108
- `);
109
- const directives = extractDirectives(ast);
110
- const fn = directives[0];
111
- const caseDir = fn.directives.find((d): d is CaseDirective => d.kind === "case")!;
112
- const result = evaluateFunctionFull(fn.node, caseDir.args, env);
113
- expect(typeValueToString(result.value)).toBe("number");
114
- });
115
- });
116
-
117
- describe("stub().callsFake executes the fake with actual args (sinon semantics)", () => {
118
- it("mockHelperToTypeValue binds the fake function itself, not a direct return of it", () => {
119
- const env = createEnvironment();
120
- const fake = parseTypeValueExpr("(x) => ({ v: x })");
121
- expect(fake.kind).toBe("function");
122
- const typeVal = mockHelperToTypeValue(stub.callsFake(fake), env);
123
- // 调用语义 = 以实参执行 fake:直接绑定 fake 本身(同 @nudo:mock 箭头机制),
124
- // 而非把 fake 函数值当 _directReturn 传播
125
- expect(typeVal).toBe(fake);
126
- });
127
-
128
- it("stub().callsFake((x) => ({ v: x })) called with 21 yields { v: 21 }", () => {
129
- const results = runNudoTest(`
130
- // @nudo:mock transform = stub().callsFake((x) => ({ v: x }))
131
- // @nudo:case "direct" (21)
132
- function applyTransform(x) {
133
- return transform(x);
134
- }
135
- `);
136
- expect(results[0].result).toBe("{ v: 21 }");
137
- });
138
-
139
- it("sinon.stub().callsFake((x) => ({ v: x })) called with 21 yields { v: 21 }", () => {
140
- const results = runNudoTest(`
141
- // @nudo:mock transform = sinon.stub().callsFake((x) => ({ v: x }))
142
- // @nudo:case "direct" (21)
143
- function applyTransform(x) {
144
- return transform(x);
145
- }
146
- `);
147
- expect(results[0].result).toBe("{ v: 21 }");
148
- });
149
-
150
- it("callsFake propagates precisely through arr.map(transform) HOF", () => {
151
- const results = runNudoTest(`
152
- // @nudo:mock transform = stub().callsFake((x) => ({ v: x }))
153
- // @nudo:case "hof" ([1, 2, 3])
154
- function mapAll(arr) {
155
- return arr.map(transform);
156
- }
157
- `);
158
- expect(results[0].result).toBe("[{ v: 1 }, { v: 2 }, { v: 3 }]");
159
- });
160
-
161
- it("withArgs(...).returns(...) matched args take priority; unmatched fall back to stub default", () => {
162
- const results = runNudoTest(`
163
- // @nudo:mock handler = stub().withArgs(21).returns("hit")
164
- // @nudo:case "match" (21)
165
- // @nudo:case "miss" (22)
166
- function call(x) {
167
- return handler(x);
168
- }
169
- `);
170
- expect(results[0].result).toBe('"hit"');
171
- expect(results[1].result).toBe("unknown");
172
- });
173
- });
174
- });
@@ -1,191 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { parse, extractDirectives, type CaseDirective, type MockDirective, parseTypeValueExpr } from "@nudojs/parser";
3
- import { typeValueToString, createEnvironment, T } from "@nudojs/core";
4
- import { evaluateFunctionFull } from "../evaluator.js";
5
-
6
- function inferWithMocks(source: string): { name: string; caseName: string; result: string }[] {
7
- const ast = parse(source);
8
- const directives = extractDirectives(ast);
9
- const env = createEnvironment();
10
- const results: { name: string; caseName: string; result: string }[] = [];
11
-
12
- for (const fn of directives) {
13
- for (const d of fn.directives) {
14
- if (d.kind === "mock") {
15
- if (d.arrowFn) {
16
- const fnType = T.fn(d.arrowFn.params, d.arrowFn.body, env);
17
- (fnType as any)._paramPatterns = d.arrowFn.paramPatterns;
18
- env.bind(d.name, fnType);
19
- } else if (d.expression) {
20
- env.bind(d.name, parseTypeValueExpr(d.expression));
21
- }
22
- }
23
- }
24
-
25
- const caseDirectives = fn.directives.filter((d): d is CaseDirective => d.kind === "case");
26
- for (const dir of caseDirectives) {
27
- const result = evaluateFunctionFull(fn.node, dir.args, env);
28
- results.push({
29
- name: fn.name,
30
- caseName: dir.name,
31
- result: typeValueToString(result.value),
32
- });
33
- }
34
- }
35
- return results;
36
- }
37
-
38
- describe("Real-world Mock Tests", () => {
39
- // 测试1: 基础 filter
40
- it("filter with predicate", () => {
41
- const results = inferWithMocks(`
42
- // @nudo:mock predicate = (x) => x > 3
43
- // @nudo:case "nums" ([1, 2, 3, 4, 5])
44
- function filterGreater(arr) {
45
- const result = [];
46
- for (const item of arr) {
47
- if (predicate(item)) result.push(item);
48
- }
49
- return result;
50
- }
51
- `);
52
- expect(results[0].result).toBe("[4, 5]");
53
- });
54
-
55
- // 测试2: map
56
- it("map with transform", () => {
57
- const results = inferWithMocks(`
58
- // @nudo:mock transform = (x) => x * 2
59
- // @nudo:case "nums" ([1, 2, 3])
60
- function doubleAll(arr) {
61
- return arr.map(transform);
62
- }
63
- `);
64
- expect(results[0].result).toBe("[2, 4, 6]");
65
- });
66
-
67
- // 测试3: reduce
68
- it("reduce with reducer", () => {
69
- const results = inferWithMocks(`
70
- // @nudo:mock reducer = (a, b) => a + b
71
- // @nudo:case "nums" ([1, 2, 3, 4])
72
- function sumAll(arr) {
73
- return arr.reduce(reducer, 0);
74
- }
75
- `);
76
- expect(results[0].result).toBe("10");
77
- });
78
-
79
- // 测试4: 多参数
80
- it("multi-parameter mock", () => {
81
- const results = inferWithMocks(`
82
- // @nudo:mock combine = (a, b) => a + b * 10
83
- // @nudo:case "nums" (3, 4)
84
- function combineNums(a, b) {
85
- return combine(a, b);
86
- }
87
- `);
88
- expect(results[0].result).toBe("43");
89
- });
90
-
91
- // 测试5: 函数组合
92
- it("function composition", () => {
93
- const results = inferWithMocks(`
94
- // @nudo:mock f = (x) => x + 1
95
- // @nudo:mock g = (x) => x * 2
96
- // @nudo:case "num" (5)
97
- function compose(x) {
98
- return f(g(x));
99
- }
100
- `);
101
- expect(results[0].result).toBe("11");
102
- });
103
-
104
- // 测试6: 回调模式
105
- it("callback pattern", () => {
106
- const results = inferWithMocks(`
107
- // @nudo:mock callback = (result) => result * 2
108
- // @nudo:case "num" (21)
109
- function processWithCallback(x) {
110
- return callback(x);
111
- }
112
- `);
113
- expect(results[0].result).toBe("42");
114
- });
115
-
116
- // 测试7: 字符串操作
117
- it("string operations", () => {
118
- const results = inferWithMocks(`
119
- // @nudo:mock transform = (s) => s.toUpperCase()
120
- // @nudo:case "str" ("hello")
121
- function transformStr(s) {
122
- return transform(s);
123
- }
124
- `);
125
- expect(results[0].result).toBe('"HELLO"');
126
- });
127
-
128
- // 测试8: 条件逻辑
129
- it("conditional logic", () => {
130
- const results = inferWithMocks(`
131
- // @nudo:mock validator = (x) => x > 0 && x < 100
132
- // @nudo:case "valid" (50)
133
- // @nudo:case "invalid" (150)
134
- function validate(x) {
135
- return validator(x);
136
- }
137
- `);
138
- expect(results[0].result).toBe("true");
139
- expect(results[1].result).toBe("false");
140
- });
141
-
142
- // 测试9: 返回数组
143
- it("return array", () => {
144
- const results = inferWithMocks(`
145
- // @nudo:mock generator = (n) => [n, n * 2, n * 3]
146
- // @nudo:case "num" (5)
147
- function generateTriples(n) {
148
- return generator(n);
149
- }
150
- `);
151
- expect(results[0].result).toBe("[5, 10, 15]");
152
- });
153
-
154
- // 测试10: 类型收窄
155
- it("type narrowing", () => {
156
- const results = inferWithMocks(`
157
- // @nudo:mock processor = (x) => typeof x === "string" ? x.toUpperCase() : x
158
- // @nudo:case "str" ("hello")
159
- // @nudo:case "num" (42)
160
- function process(x) {
161
- return processor(x);
162
- }
163
- `);
164
- expect(results[0].result).toBe('"HELLO"');
165
- expect(results[1].result).toBe("42");
166
- });
167
-
168
- // 测试11: 无参数 mock
169
- it("no-parameter mock", () => {
170
- const results = inferWithMocks(`
171
- // @nudo:mock getter = () => 42
172
- // @nudo:case "empty" ()
173
- function getValue() {
174
- return getter();
175
- }
176
- `);
177
- expect(results[0].result).toBe("42");
178
- });
179
-
180
- // 测试12: 复杂表达式
181
- it("complex expressions", () => {
182
- const results = inferWithMocks(`
183
- // @nudo:mock calc = (a, b) => (a + b) * (a - b)
184
- // @nudo:case "nums" (5, 3)
185
- function calculate(a, b) {
186
- return calc(a, b);
187
- }
188
- `);
189
- expect(results[0].result).toBe("16");
190
- });
191
- });