@cspeach/cli 0.6.4 → 0.7.0
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/agent/intent-system-prompt.js +46 -0
- package/dist/agent/loop.js +180 -18
- package/dist/agent/parallel-write-guard.js +71 -0
- package/dist/agent/repair-partial.js +88 -1
- package/dist/agent/retry-cap.js +121 -0
- package/dist/agent/summarise-via-provider.js +51 -0
- package/dist/approvals/jwt.js +33 -12
- package/dist/commands/auto-compact.js +94 -0
- package/dist/commands/compact.js +265 -0
- package/dist/commands/cost.js +56 -0
- package/dist/commands/help.js +21 -14
- package/dist/config/loader.js +39 -0
- package/dist/cost/cost-log.js +113 -0
- package/dist/cost/pricing.js +91 -0
- package/dist/index.js +0 -0
- package/dist/one-shot.js +1 -1
- package/dist/renderer/markdown.js +7 -1
- package/dist/renderer/status-footer.js +37 -14
- package/dist/renderer/thinking-heartbeat.js +15 -3
- package/dist/renderer/tool-widget.js +6 -1
- package/dist/renderer/tty.js +27 -0
- package/dist/repl/cspeach-shell-detect.js +33 -0
- package/dist/repl/post-turn-status.js +68 -0
- package/dist/repl/slash-completer.js +2 -0
- package/dist/repl/slash-picker.js +2 -0
- package/dist/repl.js +371 -46
- package/dist/sap-errors/parse-adt-exception.js +149 -0
- package/dist/session/schema.js +2 -1
- package/dist/session/store.js +19 -0
- package/dist/tools/_filesystem-shared.js +9 -1
- package/dist/tools/ask-question.js +19 -0
- package/dist/tools/sap-read.js +56 -4
- package/dist/tools/sap-write.js +19 -0
- package/dist/tools/subagent/schedule_draft_create.js +137 -0
- package/dist/ui/alt-screen.js +120 -0
- package/dist/ui/app.js +39 -15
- package/dist/ui/ask-question-emitter.js +13 -0
- package/dist/ui/body.js +39 -23
- package/dist/ui/coaching-picker-classic.js +8 -1
- package/dist/ui/footer.js +6 -1
- package/dist/ui/header.js +19 -4
- package/dist/ui/sap-state-store.js +13 -1
- package/dist/ui/sidebar.js +5 -3
- package/dist/ui/status-emitter.js +19 -0
- package/dist/ui/status-row.js +30 -4
- package/dist/ui/widgets/ask-question-modal.js +132 -0
- package/dist/ui/widgets/coaching-picker.js +55 -8
- package/package.json +86 -82
- package/dist/agent/__tests__/crash-recover.integration.test.js +0 -254
- package/dist/agent/__tests__/loop-save-hook.test.js +0 -188
- package/dist/agent/__tests__/maybe-build-project-context.test.js +0 -247
- package/dist/agent/__tests__/project-context-injection.test.js +0 -161
- package/dist/agent/__tests__/repair-partial.test.js +0 -79
- package/dist/agent/__tests__/retry-key.test.js +0 -77
- package/dist/agent/__tests__/sap-connection-adapter.test.js +0 -132
- package/dist/agent/__tests__/skill-checkpoint.test.js +0 -154
- package/dist/agent/__tests__/turn-assistant-text.test.js +0 -73
- package/dist/agent/__tests__/turn-error-ux.test.js +0 -145
- package/dist/agent/__tests__/turn-stream.test.js +0 -100
- package/dist/agent/__tests__/turn-watchdog.test.js +0 -126
- package/dist/agent/providers/__tests__/ai-hub-provider.test.js +0 -30
- package/dist/agent/providers/__tests__/byok-provider.test.js +0 -32
- package/dist/agent/providers/__tests__/factory.test.js +0 -33
- package/dist/agent/providers/__tests__/local-provider.test.js +0 -55
- package/dist/approvals/__tests__/advisory-prompt.test.js +0 -57
- package/dist/approvals/__tests__/advisory-render.test.js +0 -54
- package/dist/auth/__tests__/auth-file.test.js +0 -42
- package/dist/auth/__tests__/me.test.js +0 -43
- package/dist/classifier/__tests__/client.test.js +0 -70
- package/dist/commands/__tests__/config-set-write-mode.test.js +0 -14
- package/dist/commands/__tests__/login.test.js +0 -152
- package/dist/commands/__tests__/logout.test.js +0 -39
- package/dist/commands/__tests__/project-context-impact.test.js +0 -173
- package/dist/commands/__tests__/spec-gap-status.test.js +0 -31
- package/dist/commands/__tests__/whoami.test.js +0 -91
- package/dist/config/__tests__/llm-config.test.js +0 -28
- package/dist/config/__tests__/shell-exec-config.test.js +0 -76
- package/dist/config/__tests__/write-mode.test.js +0 -36
- package/dist/doctor/__tests__/check-forge-rules.test.js +0 -134
- package/dist/doctor/__tests__/check-llm-mode.test.js +0 -21
- package/dist/doctor/__tests__/check-write-mode.test.js +0 -34
- package/dist/project-context/__tests__/conventions.test.js +0 -221
- package/dist/project-context/__tests__/detect.test.js +0 -177
- package/dist/project-context/__tests__/domain-abap-cloud.test.js +0 -119
- package/dist/project-context/__tests__/domain-abapgit.test.js +0 -161
- package/dist/project-context/__tests__/domain-cap.test.js +0 -168
- package/dist/project-context/__tests__/domain-fiori.test.js +0 -282
- package/dist/project-context/__tests__/git.test.js +0 -131
- package/dist/project-context/__tests__/index-files.test.js +0 -195
- package/dist/project-context/__tests__/index.test.js +0 -133
- package/dist/project-context/__tests__/render.test.js +0 -322
- package/dist/project-context/__tests__/types.test.js +0 -73
- package/dist/projects/__tests__/build.test.js +0 -52
- package/dist/projects/__tests__/canonicalize.test.js +0 -47
- package/dist/projects/__tests__/email-template.test.js +0 -71
- package/dist/projects/__tests__/expand-text-attachments.test.js +0 -105
- package/dist/projects/__tests__/extract-cca.test.js +0 -141
- package/dist/projects/__tests__/extract-design.test.js +0 -62
- package/dist/projects/__tests__/extract-estimate.test.js +0 -58
- package/dist/projects/__tests__/extract-modernize.test.js +0 -127
- package/dist/projects/__tests__/extract-spec-gap.test.js +0 -122
- package/dist/projects/__tests__/extract-test-coverage.test.js +0 -133
- package/dist/projects/__tests__/filename.test.js +0 -32
- package/dist/projects/__tests__/promote-command.test.js +0 -170
- package/dist/projects/__tests__/promote.test.js +0 -181
- package/dist/projects/__tests__/save-command.test.js +0 -216
- package/dist/projects/__tests__/save.test.js +0 -41
- package/dist/projects/__tests__/status.test.js +0 -208
- package/dist/projects/__tests__/types.test.js +0 -41
- package/dist/projects/__tests__/validate.test.js +0 -165
- package/dist/projects/__tests__/workspace.test.js +0 -337
- package/dist/repl/__tests__/current-transport.test.js +0 -43
- package/dist/repl/__tests__/diff-display.test.js +0 -59
- package/dist/repl/__tests__/file-picker.test.js +0 -97
- package/dist/repl/__tests__/rule8-detector.test.js +0 -114
- package/dist/repl/__tests__/safety-confirm.test.js +0 -130
- package/dist/repl/__tests__/safety-mode-state.test.js +0 -42
- package/dist/sap/__tests__/system-info.test.js +0 -344
- package/dist/session/__tests__/store-discovery.test.js +0 -114
- package/dist/session/__tests__/time-ago.test.js +0 -53
- package/dist/skills/__tests__/canonical.test.js +0 -20
- package/dist/skills/__tests__/manifest-client.test.js +0 -88
- package/dist/skills/__tests__/promotion-dispatch.test.js +0 -28
- package/dist/skills/__tests__/source-managed.test.js +0 -60
- package/dist/tools/__tests__/_background-shared.test.js +0 -69
- package/dist/tools/__tests__/_command-shared.test.js +0 -59
- package/dist/tools/__tests__/_filesystem-shared.test.js +0 -42
- package/dist/tools/__tests__/_flag.test.js +0 -66
- package/dist/tools/__tests__/_helpers.js +0 -17
- package/dist/tools/__tests__/_web-shared.test.js +0 -143
- package/dist/tools/__tests__/agent_run.test.js +0 -166
- package/dist/tools/__tests__/approval-advisory.test.js +0 -66
- package/dist/tools/__tests__/background_run.test.js +0 -113
- package/dist/tools/__tests__/convention_get.test.js +0 -53
- package/dist/tools/__tests__/file-edit.test.js +0 -72
- package/dist/tools/__tests__/file-read.test.js +0 -81
- package/dist/tools/__tests__/file-write.test.js +0 -68
- package/dist/tools/__tests__/glob.test.js +0 -128
- package/dist/tools/__tests__/grep.test.js +0 -71
- package/dist/tools/__tests__/monitor_emit.test.js +0 -96
- package/dist/tools/__tests__/playbook_get.test.js +0 -109
- package/dist/tools/__tests__/project_context_get.test.js +0 -71
- package/dist/tools/__tests__/registry-category.test.js +0 -60
- package/dist/tools/__tests__/sap-read-extras.test.js +0 -196
- package/dist/tools/__tests__/sap-write-extras.test.js +0 -573
- package/dist/tools/__tests__/schedule_create.test.js +0 -85
- package/dist/tools/__tests__/shell_exec.test.js +0 -135
- package/dist/tools/__tests__/transport-safety.test.js +0 -106
- package/dist/tools/__tests__/update-method-intercept.test.js +0 -128
- package/dist/tools/__tests__/web_fetch.test.js +0 -329
- package/dist/tools/__tests__/web_search.test.js +0 -215
- package/dist/tools/__tests__/write-mode.test.js +0 -32
- package/dist/ui/__tests__/login-banner.test.js +0 -69
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { registerTool, listTools, getToolsByCategory } from '../index.js';
|
|
3
|
-
import { TOOL_FLAG_PREFIX } from '../_flag.js';
|
|
4
|
-
const FLAG = `${TOOL_FLAG_PREFIX}DEMO_NEW_TOOL`;
|
|
5
|
-
beforeEach(() => { delete process.env[FLAG]; });
|
|
6
|
-
afterEach(() => { delete process.env[FLAG]; });
|
|
7
|
-
describe('Tool.category + getToolsByCategory', () => {
|
|
8
|
-
it('a tool registered without category defaults to "sap" (back-compat)', () => {
|
|
9
|
-
registerTool({
|
|
10
|
-
name: 'demo_legacy_tool',
|
|
11
|
-
description: 'legacy',
|
|
12
|
-
input_schema: { type: 'object', properties: {}, required: [] },
|
|
13
|
-
handler: async () => ({ content: 'ok' }),
|
|
14
|
-
isMutating: false,
|
|
15
|
-
});
|
|
16
|
-
const t = listTools().find((x) => x.name === 'demo_legacy_tool');
|
|
17
|
-
expect(t?.category).toBe('sap');
|
|
18
|
-
});
|
|
19
|
-
it('a tool registered with explicit category preserves it', () => {
|
|
20
|
-
registerTool({
|
|
21
|
-
name: 'demo_fs_tool',
|
|
22
|
-
description: 'fs',
|
|
23
|
-
input_schema: { type: 'object', properties: {}, required: [] },
|
|
24
|
-
handler: async () => ({ content: 'ok' }),
|
|
25
|
-
isMutating: false,
|
|
26
|
-
category: 'filesystem',
|
|
27
|
-
});
|
|
28
|
-
const t = listTools().find((x) => x.name === 'demo_fs_tool');
|
|
29
|
-
expect(t?.category).toBe('filesystem');
|
|
30
|
-
expect(getToolsByCategory('filesystem').map((x) => x.name)).toContain('demo_fs_tool');
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
describe('listTools — Phase 3 visibility gate', () => {
|
|
34
|
-
it('a flag-gated new tool is INVISIBLE when its env flag is unset', () => {
|
|
35
|
-
registerTool({
|
|
36
|
-
name: 'demo_new_tool',
|
|
37
|
-
description: 'gated',
|
|
38
|
-
input_schema: { type: 'object', properties: {}, required: [] },
|
|
39
|
-
handler: async () => ({ content: 'ok' }),
|
|
40
|
-
isMutating: false,
|
|
41
|
-
category: 'filesystem',
|
|
42
|
-
flagGated: true,
|
|
43
|
-
});
|
|
44
|
-
expect(listTools().some((t) => t.name === 'demo_new_tool')).toBe(false);
|
|
45
|
-
});
|
|
46
|
-
it('the same tool is VISIBLE when its env flag is on', () => {
|
|
47
|
-
process.env[FLAG] = 'on';
|
|
48
|
-
expect(listTools().some((t) => t.name === 'demo_new_tool')).toBe(true);
|
|
49
|
-
});
|
|
50
|
-
it('a tool without flagGated is ALWAYS visible (back-compat for existing 30+ tools)', () => {
|
|
51
|
-
registerTool({
|
|
52
|
-
name: 'demo_visible_no_flag',
|
|
53
|
-
description: 'always-visible',
|
|
54
|
-
input_schema: { type: 'object', properties: {}, required: [] },
|
|
55
|
-
handler: async () => ({ content: 'ok' }),
|
|
56
|
-
isMutating: false,
|
|
57
|
-
});
|
|
58
|
-
expect(listTools().some((t) => t.name === 'demo_visible_no_flag')).toBe(true);
|
|
59
|
-
});
|
|
60
|
-
});
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the 8 additional read-only SAP tools added in Phase 3-Lite A.4:
|
|
3
|
-
* sap_class_includes, sap_inactive_objects, sap_syntax_check, sap_diff,
|
|
4
|
-
* sap_preview_change, sap_run_unit_test, sap_odata_test, sap_badi_list
|
|
5
|
-
*
|
|
6
|
-
* Pattern: partial mock as `{ method: vi.fn() } as unknown as AdtClient`.
|
|
7
|
-
* Each tool gets a happy-path test and an error-path test (16 tests total).
|
|
8
|
-
*/
|
|
9
|
-
import '../sap-read.js'; // triggers registration side-effect
|
|
10
|
-
import { getTool } from '../index.js';
|
|
11
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
12
|
-
// ---------------------------------------------------------------------------
|
|
13
|
-
// Helper: build a minimal ToolContext stub
|
|
14
|
-
// ---------------------------------------------------------------------------
|
|
15
|
-
function makeCtx(adt) {
|
|
16
|
-
return {
|
|
17
|
-
adt: adt,
|
|
18
|
-
sapAlias: 'dev',
|
|
19
|
-
session: {},
|
|
20
|
-
cwd: '.',
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
// 11. sap_class_includes
|
|
25
|
-
// ---------------------------------------------------------------------------
|
|
26
|
-
describe('sap_class_includes', () => {
|
|
27
|
-
it('returns JSON array when no includeType is given', async () => {
|
|
28
|
-
const adt = {
|
|
29
|
-
classIncludes: vi.fn().mockResolvedValue([{ name: 'definitions' }, { name: 'implementations' }]),
|
|
30
|
-
};
|
|
31
|
-
const tool = getTool('sap_class_includes');
|
|
32
|
-
const result = await tool.handler({ className: 'ZCL_FOO' }, makeCtx(adt));
|
|
33
|
-
expect(adt.classIncludes).toHaveBeenCalledWith('ZCL_FOO', undefined);
|
|
34
|
-
expect(JSON.parse(result.content)).toEqual([{ name: 'definitions' }, { name: 'implementations' }]);
|
|
35
|
-
});
|
|
36
|
-
it('propagates error when classIncludes throws', async () => {
|
|
37
|
-
const adt = {
|
|
38
|
-
classIncludes: vi.fn().mockRejectedValue(new Error('ADT 404')),
|
|
39
|
-
};
|
|
40
|
-
const tool = getTool('sap_class_includes');
|
|
41
|
-
await expect(tool.handler({ className: 'ZCL_MISSING' }, makeCtx(adt))).rejects.toThrow('ADT 404');
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
// ---------------------------------------------------------------------------
|
|
45
|
-
// 12. sap_inactive_objects
|
|
46
|
-
// ---------------------------------------------------------------------------
|
|
47
|
-
describe('sap_inactive_objects', () => {
|
|
48
|
-
it('returns JSON list of inactive objects', async () => {
|
|
49
|
-
const adt = {
|
|
50
|
-
inactiveObjects: vi.fn().mockResolvedValue([{ name: 'ZCL_FOO', type: 'CLAS' }]),
|
|
51
|
-
};
|
|
52
|
-
const tool = getTool('sap_inactive_objects');
|
|
53
|
-
const result = await tool.handler({}, makeCtx(adt));
|
|
54
|
-
expect(adt.inactiveObjects).toHaveBeenCalledWith();
|
|
55
|
-
expect(JSON.parse(result.content)).toEqual([{ name: 'ZCL_FOO', type: 'CLAS' }]);
|
|
56
|
-
});
|
|
57
|
-
it('propagates error when inactiveObjects throws', async () => {
|
|
58
|
-
const adt = {
|
|
59
|
-
inactiveObjects: vi.fn().mockRejectedValue(new Error('ADT 503')),
|
|
60
|
-
};
|
|
61
|
-
const tool = getTool('sap_inactive_objects');
|
|
62
|
-
await expect(tool.handler({}, makeCtx(adt))).rejects.toThrow('ADT 503');
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
// ---------------------------------------------------------------------------
|
|
66
|
-
// 13. sap_syntax_check
|
|
67
|
-
// ---------------------------------------------------------------------------
|
|
68
|
-
describe('sap_syntax_check', () => {
|
|
69
|
-
it('calls syntaxCheck with type first and returns JSON result', async () => {
|
|
70
|
-
const fakeSyntaxResult = { hasErrors: false, messages: [] };
|
|
71
|
-
const adt = {
|
|
72
|
-
syntaxCheck: vi.fn().mockResolvedValue(fakeSyntaxResult),
|
|
73
|
-
};
|
|
74
|
-
const tool = getTool('sap_syntax_check');
|
|
75
|
-
const result = await tool.handler({ type: 'CLAS', name: 'ZCL_FOO' }, makeCtx(adt));
|
|
76
|
-
expect(adt.syntaxCheck).toHaveBeenCalledWith('CLAS', 'ZCL_FOO');
|
|
77
|
-
expect(JSON.parse(result.content)).toEqual(fakeSyntaxResult);
|
|
78
|
-
});
|
|
79
|
-
it('propagates error when syntaxCheck throws', async () => {
|
|
80
|
-
const adt = {
|
|
81
|
-
syntaxCheck: vi.fn().mockRejectedValue(new Error('connection refused')),
|
|
82
|
-
};
|
|
83
|
-
const tool = getTool('sap_syntax_check');
|
|
84
|
-
await expect(tool.handler({ type: 'CLAS', name: 'ZCL_FOO' }, makeCtx(adt))).rejects.toThrow('connection refused');
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
// ---------------------------------------------------------------------------
|
|
88
|
-
// 14. sap_diff
|
|
89
|
-
// ---------------------------------------------------------------------------
|
|
90
|
-
describe('sap_diff', () => {
|
|
91
|
-
it('calls diff with type first and returns JSON result', async () => {
|
|
92
|
-
const fakeDiff = { unified: '--- a\n+++ b\n@@ -1 +1 @@\n-old\n+new' };
|
|
93
|
-
const adt = {
|
|
94
|
-
diff: vi.fn().mockResolvedValue(fakeDiff),
|
|
95
|
-
};
|
|
96
|
-
const tool = getTool('sap_diff');
|
|
97
|
-
const result = await tool.handler({ type: 'PROG', name: 'ZTEST', version1: 'old', version2: 'new' }, makeCtx(adt));
|
|
98
|
-
expect(adt.diff).toHaveBeenCalledWith('PROG', 'ZTEST', 'old', 'new');
|
|
99
|
-
expect(JSON.parse(result.content)).toEqual(fakeDiff);
|
|
100
|
-
});
|
|
101
|
-
it('propagates error when diff throws', async () => {
|
|
102
|
-
const adt = {
|
|
103
|
-
diff: vi.fn().mockRejectedValue(new Error('ADT 401')),
|
|
104
|
-
};
|
|
105
|
-
const tool = getTool('sap_diff');
|
|
106
|
-
await expect(tool.handler({ type: 'PROG', name: 'ZTEST' }, makeCtx(adt))).rejects.toThrow('ADT 401');
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
// ---------------------------------------------------------------------------
|
|
110
|
-
// 15. sap_preview_change
|
|
111
|
-
// ---------------------------------------------------------------------------
|
|
112
|
-
describe('sap_preview_change', () => {
|
|
113
|
-
it('calls previewChange with type first and returns JSON result', async () => {
|
|
114
|
-
const fakeDiff = { unified: '@@ -1 +1 @@\n-old\n+new' };
|
|
115
|
-
const adt = {
|
|
116
|
-
previewChange: vi.fn().mockResolvedValue(fakeDiff),
|
|
117
|
-
};
|
|
118
|
-
const tool = getTool('sap_preview_change');
|
|
119
|
-
const result = await tool.handler({ type: 'CLAS', name: 'ZCL_FOO', newSource: 'CLASS ZCL_FOO...' }, makeCtx(adt));
|
|
120
|
-
expect(adt.previewChange).toHaveBeenCalledWith('CLAS', 'ZCL_FOO', 'CLASS ZCL_FOO...');
|
|
121
|
-
expect(JSON.parse(result.content)).toEqual(fakeDiff);
|
|
122
|
-
});
|
|
123
|
-
it('propagates error when previewChange throws', async () => {
|
|
124
|
-
const adt = {
|
|
125
|
-
previewChange: vi.fn().mockRejectedValue(new Error('object locked')),
|
|
126
|
-
};
|
|
127
|
-
const tool = getTool('sap_preview_change');
|
|
128
|
-
await expect(tool.handler({ type: 'CLAS', name: 'ZCL_FOO', newSource: 'x' }, makeCtx(adt))).rejects.toThrow('object locked');
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
// ---------------------------------------------------------------------------
|
|
132
|
-
// 16. sap_run_unit_test
|
|
133
|
-
// ---------------------------------------------------------------------------
|
|
134
|
-
describe('sap_run_unit_test', () => {
|
|
135
|
-
it('calls runUnitTest with type first and returns JSON result', async () => {
|
|
136
|
-
const fakeResult = { passed: 3, failed: 0, errors: 0, testClasses: [] };
|
|
137
|
-
const adt = {
|
|
138
|
-
runUnitTest: vi.fn().mockResolvedValue(fakeResult),
|
|
139
|
-
};
|
|
140
|
-
const tool = getTool('sap_run_unit_test');
|
|
141
|
-
const result = await tool.handler({ type: 'CLAS', name: 'ZCL_ORDER' }, makeCtx(adt));
|
|
142
|
-
expect(adt.runUnitTest).toHaveBeenCalledWith('CLAS', 'ZCL_ORDER');
|
|
143
|
-
expect(JSON.parse(result.content)).toEqual(fakeResult);
|
|
144
|
-
});
|
|
145
|
-
it('propagates error when runUnitTest throws', async () => {
|
|
146
|
-
const adt = {
|
|
147
|
-
runUnitTest: vi.fn().mockRejectedValue(new Error('ADT 500')),
|
|
148
|
-
};
|
|
149
|
-
const tool = getTool('sap_run_unit_test');
|
|
150
|
-
await expect(tool.handler({ type: 'CLAS', name: 'ZCL_ORDER' }, makeCtx(adt))).rejects.toThrow('ADT 500');
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
// ---------------------------------------------------------------------------
|
|
154
|
-
// 17. sap_odata_test
|
|
155
|
-
// ---------------------------------------------------------------------------
|
|
156
|
-
describe('sap_odata_test', () => {
|
|
157
|
-
it('calls odataTest with correct args and returns JSON result', async () => {
|
|
158
|
-
const fakeResult = { status: 200, body: '<service/>' };
|
|
159
|
-
const adt = {
|
|
160
|
-
odataTest: vi.fn().mockResolvedValue(fakeResult),
|
|
161
|
-
};
|
|
162
|
-
const tool = getTool('sap_odata_test');
|
|
163
|
-
const result = await tool.handler({ servicePath: '/sap/opu/odata/sap/ZSALES_SRV', entity: 'SalesOrder', method: 'GET' }, makeCtx(adt));
|
|
164
|
-
expect(adt.odataTest).toHaveBeenCalledWith('/sap/opu/odata/sap/ZSALES_SRV', 'SalesOrder', 'GET');
|
|
165
|
-
expect(JSON.parse(result.content)).toEqual(fakeResult);
|
|
166
|
-
});
|
|
167
|
-
it('propagates error when odataTest throws', async () => {
|
|
168
|
-
const adt = {
|
|
169
|
-
odataTest: vi.fn().mockRejectedValue(new Error('service not found')),
|
|
170
|
-
};
|
|
171
|
-
const tool = getTool('sap_odata_test');
|
|
172
|
-
await expect(tool.handler({ servicePath: '/sap/opu/odata/sap/ZMISSING_SRV' }, makeCtx(adt))).rejects.toThrow('service not found');
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
// ---------------------------------------------------------------------------
|
|
176
|
-
// 18. sap_badi_list
|
|
177
|
-
// ---------------------------------------------------------------------------
|
|
178
|
-
describe('sap_badi_list', () => {
|
|
179
|
-
it('calls badiList with correct args and returns JSON result', async () => {
|
|
180
|
-
const fakeResult = { badiDefinitions: [{ name: 'MD_PURCH_REQ_SAVE' }], enhancementSpots: [] };
|
|
181
|
-
const adt = {
|
|
182
|
-
badiList: vi.fn().mockResolvedValue(fakeResult),
|
|
183
|
-
};
|
|
184
|
-
const tool = getTool('sap_badi_list');
|
|
185
|
-
const result = await tool.handler({ query: 'MD_PURCH*', enhancementSpot: 'ES_MD_PURCH', maxResults: 25 }, makeCtx(adt));
|
|
186
|
-
expect(adt.badiList).toHaveBeenCalledWith('MD_PURCH*', 'ES_MD_PURCH', 25);
|
|
187
|
-
expect(JSON.parse(result.content)).toEqual(fakeResult);
|
|
188
|
-
});
|
|
189
|
-
it('propagates error when badiList throws', async () => {
|
|
190
|
-
const adt = {
|
|
191
|
-
badiList: vi.fn().mockRejectedValue(new Error('ADT 403')),
|
|
192
|
-
};
|
|
193
|
-
const tool = getTool('sap_badi_list');
|
|
194
|
-
await expect(tool.handler({ query: 'ZBADI*' }, makeCtx(adt))).rejects.toThrow('ADT 403');
|
|
195
|
-
});
|
|
196
|
-
});
|