@mcp-abap-adt/adt-clients 37.1.0 → 37.2.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.
Files changed (30) hide show
  1. package/README.md +33 -3
  2. package/dist/core/class/run.d.ts +5 -29
  3. package/dist/core/class/run.d.ts.map +1 -1
  4. package/dist/core/class/run.js +6 -76
  5. package/dist/core/shared/abapUnit.d.ts +46 -0
  6. package/dist/core/shared/abapUnit.d.ts.map +1 -1
  7. package/dist/core/shared/abapUnit.js +98 -0
  8. package/dist/executors/abapUnitRunner.d.ts +9 -0
  9. package/dist/executors/abapUnitRunner.d.ts.map +1 -1
  10. package/dist/executors/abapUnitRunner.js +14 -0
  11. package/dist/executors/functionGroup/FunctionGroupTestRunner.d.ts +25 -1
  12. package/dist/executors/functionGroup/FunctionGroupTestRunner.d.ts.map +1 -1
  13. package/dist/executors/functionGroup/FunctionGroupTestRunner.js +30 -1
  14. package/dist/executors/functionModule/FunctionModuleTestRunner.d.ts +47 -2
  15. package/dist/executors/functionModule/FunctionModuleTestRunner.d.ts.map +1 -1
  16. package/dist/executors/functionModule/FunctionModuleTestRunner.js +48 -1
  17. package/dist/executors/functionModule/index.d.ts +1 -1
  18. package/dist/executors/functionModule/index.d.ts.map +1 -1
  19. package/dist/executors/index.d.ts +1 -1
  20. package/dist/executors/index.d.ts.map +1 -1
  21. package/dist/executors/program/ProgramTestRunner.d.ts +30 -3
  22. package/dist/executors/program/ProgramTestRunner.d.ts.map +1 -1
  23. package/dist/executors/program/ProgramTestRunner.js +33 -3
  24. package/dist/executors/program/ProgramTestRunnerLegacy.d.ts +7 -4
  25. package/dist/executors/program/ProgramTestRunnerLegacy.d.ts.map +1 -1
  26. package/dist/executors/program/ProgramTestRunnerLegacy.js +9 -4
  27. package/dist/index.executors.d.ts +1 -1
  28. package/dist/index.executors.d.ts.map +1 -1
  29. package/docs/usage/OBJECT_LIFECYCLE.md +2 -2
  30. package/package.json +25 -18
package/README.md CHANGED
@@ -158,8 +158,8 @@ npm install @mcp-abap-adt/adt-clients
158
158
  - Executors:
159
159
  - `getClassExecutor()` for `classrun`
160
160
  - `getClassTestRunner()` for a class's ABAP Unit tests: `run`, `getStatus`, `getResult` (asynchronous, the default), or `runSync` (synchronous)
161
- - `getProgramTestRunner()` for a report's ABAP Unit tests, in its source or its includes
162
- - `getFunctionGroupTestRunner()` / `getFunctionModuleTestRunner()` for a function group's tests, or the ones exercising one module
161
+ - `getProgramTestRunner()` for a report's ABAP Unit tests, in its source or its includes — `run` (asynchronous, the default) or `runSync`
162
+ - `getFunctionGroupTestRunner()` / `getFunctionModuleTestRunner()` for a function group's tests, or a module's — `run` (asynchronous, the default) or `runSync`
163
163
  - `getProgramExecutor()` for `programrun` (on-premise systems)
164
164
  - Methods: `run`, `runWithProfiler`, and trace scheduling (`scheduleTrace`, `listRequests`, `getRequestsByUri`, `listObjectTypes`, `listProcessTypes`)
165
165
  - Each executor factory takes an optional result set, like the runtime client's
@@ -468,7 +468,37 @@ through `executor.getProgramTestRunner().run(programName)`, with the same
468
468
  `getStatus`/`getResult`. A function group's are written in an include of the
469
469
  group (`getFunctionInclude()`) and run through `getFunctionGroupTestRunner()`
470
470
  for the whole group or `getFunctionModuleTestRunner()` for one module. Below
471
- 7.50 these three runners refuse without a request.
471
+ 7.50 these three runners refuse without a request, `runSync` included.
472
+
473
+ All three have `runSync` as well — the same `/abapunit/testruns` request as a
474
+ class's, naming the object by its URI, read by `result` and judged by
475
+ `options.analyse`:
476
+
477
+ ```typescript
478
+ await executor.getProgramTestRunner().runSync('ZREPORT', { analyse: analyseUnitTest });
479
+ await executor.getFunctionGroupTestRunner().runSync('ZGROUP', { analyse: analyseUnitTest });
480
+ await executor
481
+ .getFunctionModuleTestRunner()
482
+ .runSync({ functionGroupName: 'ZGROUP', functionModuleName: 'Z_MODULE' }, { analyse: analyseUnitTest });
483
+ ```
484
+
485
+ Their run configuration always carries `<options>` (scope, risk levels and
486
+ durations, with `run`'s defaults). Measured on premise (SAP_BASIS 816,
487
+ 2026-10-23): with it, a report (test class in its own source or in an include),
488
+ a function group and a function module each ran the same tests with the same
489
+ alerts as `run`; without it the endpoint answered `200` with an empty
490
+ `aunit:runResult`. Name the report, not the include: an include's own URI ran
491
+ nothing, its tests run through the report.
492
+
493
+ **A module's `runSync` runs its whole group's tests.** The module's URI lies
494
+ under its group's, so the target names both. On the measured system it ran
495
+ every test of the group — a test class that calls no module included — and so
496
+ did the run of a module that no test calls; the result names the group
497
+ (`FUGR/F`). `run` (`FUNC`) did the same there. The library filters nothing: a
498
+ caller who wants one module's tests reads them out of the result. With an ABAP
499
+ Doc test relation (`"! @testing FUNC:<module>`) on a test class, the default
500
+ scope answered the group's tests as a preview (`isForeign="true"`, nothing
501
+ executed) and `scope: { foreignTests: true }` ran them.
472
502
 
473
503
  **AdtUtils read type safety:**
474
504
  `readObjectMetadata` and `readObjectSource` accept strict object type unions to prevent invalid inputs like `view:ZOBJ`.
@@ -63,37 +63,13 @@ export declare const getClassUnitTestResult: typeof getUnitTestRunResult;
63
63
  export declare function startClassUnitTestRunByObject(connection: IAbapConnection, className: string, options?: IClassUnitTestRunOptions): Promise<IAdtWireResponse>;
64
64
  /**
65
65
  * Run the ABAP Unit tests of whole classes and answer the finished result —
66
- * `POST /sap/bc/adt/abapunit/testruns`, one request, no run to poll.
67
- *
68
- * The one implementation of this endpoint: the regular runner's `runSync` and
69
- * the legacy runner's `run` both send it.
70
- *
71
- * **Measured:** synchronous on a modern and a legacy on-prem system, over HTTP
72
- * and over RFC — `<aunit:runResult>` in the POST's answer, no `Location` — and
73
- * the typed and `application/xml` bodies byte-identical; the legacy system
74
- * ignores a typed `Accept` and answers `application/xml` either way. Advertised
75
- * (2026-10-22) by an on-prem system and an ABAP Cloud system alike, beside
76
- * `/abapunit/runs`; and on an on-prem S/4HANA 2023 that has no `/runs` at all
77
- * (fr0ster/mcp-abap-adt#286).
78
- *
79
- * **Reading the result: `kind` carries the distinction, `severity` does not.**
80
- * A failed assertion and an uncaught exception both come back
81
- * `severity="critical"`, so a parser classifying on severity reports a short
82
- * dump as a failed test. `kind` separates them: `failedAssertion`,
83
- * `exception`, `noTestClasses`.
84
- *
85
- * The format differs from `/runs`:
86
- * - root `aunit:runConfiguration` in `http://www.sap.com/adt/aunit` (not
87
- * `aunit:run` in `http://www.sap.com/adt/api/aunit`);
88
- * - objects by URI in `adtcore:objectReferences` — so a run covers whole
89
- * classes: the format has no way to name one test class inside its
90
- * container;
91
- * - `application/xml` for `Content-Type` and `Accept`.
66
+ * `POST /sap/bc/adt/abapunit/testruns`, one request, no run to poll. The
67
+ * request is `startUnitTestRunSync` (`core/shared/abapUnit`), given each
68
+ * class's URI; see there for the format and what was measured.
92
69
  *
70
+ * The regular runner's `runSync` and the legacy runner's `run` both send it.
93
71
  * `options` absent sends no `<options>` element — the body the legacy runner
94
- * has always sent, unchanged. Given, the scope, risk levels and durations go in
95
- * `<options>` with the same defaults `/runs` gets; `title` and `context` have
96
- * no place in this format and are not sent.
72
+ * has always sent, unchanged.
97
73
  */
98
74
  export declare function startClassUnitTestRunSync(connection: IAbapConnection, classNames: string[], options?: IClassUnitTestRunOptions): Promise<IAdtWireResponse>;
99
75
  //# sourceMappingURL=run.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/core/class/run.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EACjB,MAAM,yCAAyC,CAAC;AAKjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAsB,QAAQ,CAC5B,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,OAAc,EACxB,UAAU,CAAC,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,YAAY,GACtB,OAAO,CAAC,gBAAgB,CAAC,CAoB3B;AAOD,YAAY,EACV,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,8BAA8B,CAAC;AAMtC,OAAO,KAAK,EACV,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EAErB,MAAM,oBAAoB,CAAC;AAE5B,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,eAAe,EAC3B,KAAK,EAAE,wBAAwB,EAAE,EACjC,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,gBAAgB,CAAC,CA6C3B;AAED,mFAAmF;AACnF,eAAO,MAAM,sBAAsB,6BAAuB,CAAC;AAE3D,qEAAqE;AACrE,eAAO,MAAM,sBAAsB,6BAAuB,CAAC;AAE3D;;;;GAIG;AACH,wBAAsB,6BAA6B,CACjD,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,gBAAgB,CAAC,CAM3B;AASD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,eAAe,EAC3B,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,gBAAgB,CAAC,CA8B3B"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/core/class/run.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EACjB,MAAM,yCAAyC,CAAC;AAKjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAsB,QAAQ,CAC5B,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,OAAc,EACxB,UAAU,CAAC,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,YAAY,GACtB,OAAO,CAAC,gBAAgB,CAAC,CAoB3B;AAOD,YAAY,EACV,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,8BAA8B,CAAC;AAMtC,OAAO,KAAK,EACV,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EAGrB,MAAM,oBAAoB,CAAC;AAE5B,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,eAAe,EAC3B,KAAK,EAAE,wBAAwB,EAAE,EACjC,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,gBAAgB,CAAC,CA6C3B;AAED,mFAAmF;AACnF,eAAO,MAAM,sBAAsB,6BAAuB,CAAC;AAE3D,qEAAqE;AACrE,eAAO,MAAM,sBAAsB,6BAAuB,CAAC;AAE3D;;;;GAIG;AACH,wBAAsB,6BAA6B,CACjD,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,gBAAgB,CAAC,CAM3B;AAMD;;;;;;;;;GASG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,eAAe,EAC3B,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,gBAAgB,CAAC,CAM3B"}
@@ -131,86 +131,16 @@ async function startClassUnitTestRunByObject(connection, className, options) {
131
131
  // =============================================================================
132
132
  // The synchronous runner: /abapunit/testruns
133
133
  // =============================================================================
134
- const CT_TESTRUNS = 'application/xml';
135
- const ACCEPT_TESTRUNS = 'application/xml';
136
134
  /**
137
135
  * Run the ABAP Unit tests of whole classes and answer the finished result —
138
- * `POST /sap/bc/adt/abapunit/testruns`, one request, no run to poll.
139
- *
140
- * The one implementation of this endpoint: the regular runner's `runSync` and
141
- * the legacy runner's `run` both send it.
142
- *
143
- * **Measured:** synchronous on a modern and a legacy on-prem system, over HTTP
144
- * and over RFC — `<aunit:runResult>` in the POST's answer, no `Location` — and
145
- * the typed and `application/xml` bodies byte-identical; the legacy system
146
- * ignores a typed `Accept` and answers `application/xml` either way. Advertised
147
- * (2026-10-22) by an on-prem system and an ABAP Cloud system alike, beside
148
- * `/abapunit/runs`; and on an on-prem S/4HANA 2023 that has no `/runs` at all
149
- * (fr0ster/mcp-abap-adt#286).
150
- *
151
- * **Reading the result: `kind` carries the distinction, `severity` does not.**
152
- * A failed assertion and an uncaught exception both come back
153
- * `severity="critical"`, so a parser classifying on severity reports a short
154
- * dump as a failed test. `kind` separates them: `failedAssertion`,
155
- * `exception`, `noTestClasses`.
156
- *
157
- * The format differs from `/runs`:
158
- * - root `aunit:runConfiguration` in `http://www.sap.com/adt/aunit` (not
159
- * `aunit:run` in `http://www.sap.com/adt/api/aunit`);
160
- * - objects by URI in `adtcore:objectReferences` — so a run covers whole
161
- * classes: the format has no way to name one test class inside its
162
- * container;
163
- * - `application/xml` for `Content-Type` and `Accept`.
136
+ * `POST /sap/bc/adt/abapunit/testruns`, one request, no run to poll. The
137
+ * request is `startUnitTestRunSync` (`core/shared/abapUnit`), given each
138
+ * class's URI; see there for the format and what was measured.
164
139
  *
140
+ * The regular runner's `runSync` and the legacy runner's `run` both send it.
165
141
  * `options` absent sends no `<options>` element — the body the legacy runner
166
- * has always sent, unchanged. Given, the scope, risk levels and durations go in
167
- * `<options>` with the same defaults `/runs` gets; `title` and `context` have
168
- * no place in this format and are not sent.
142
+ * has always sent, unchanged.
169
143
  */
170
144
  async function startClassUnitTestRunSync(connection, classNames, options) {
171
- const objectRefs = classNames
172
- .map((name) => {
173
- return ` <adtcore:objectReference adtcore:uri="${(0, xml_1.escapeXmlAttr)(objects_1.CLASS.uri(name))}"/>`;
174
- })
175
- .join('\n');
176
- const xml = `<?xml version="1.0" encoding="UTF-8"?><aunit:runConfiguration xmlns:aunit="http://www.sap.com/adt/aunit">
177
- <external>
178
- <coverage active="false"/>
179
- </external>
180
- ${options ? testRunsOptions(options) : ''} <adtcore:objectSets xmlns:adtcore="http://www.sap.com/adt/core">
181
- <objectSet kind="inclusive">
182
- <adtcore:objectReferences>
183
- ${objectRefs}
184
- </adtcore:objectReferences>
185
- </objectSet>
186
- </adtcore:objectSets>
187
- </aunit:runConfiguration>`;
188
- return connection.makeAdtRequest({
189
- url: '/sap/bc/adt/abapunit/testruns',
190
- method: 'POST',
191
- timeout: 0,
192
- data: xml,
193
- headers: {
194
- 'Content-Type': CT_TESTRUNS,
195
- Accept: ACCEPT_TESTRUNS,
196
- },
197
- });
198
- }
199
- /**
200
- * `<options>` of a `runConfiguration`, as Eclipse sends it. The scope's three
201
- * flags are `testDeterminationStrategy`'s: own tests are `sameProgram`,
202
- * foreign tests `assignedTests`, their preview `appendAssignedTestsPreview`.
203
- */
204
- function testRunsOptions(options) {
205
- const scope = options.scope ?? {};
206
- const risk = options.riskLevel ?? {};
207
- const duration = options.duration ?? {};
208
- return ` <options>
209
- <uriType value="semantic"/>
210
- <testDeterminationStrategy sameProgram="${boolAttr(scope.ownTests, true)}" assignedTests="${boolAttr(scope.foreignTests, false)}" appendAssignedTestsPreview="${boolAttr(scope.addForeignTestsAsPreview, true)}"/>
211
- <testRiskLevels harmless="${boolAttr(risk.harmless, true)}" dangerous="${boolAttr(risk.dangerous, true)}" critical="${boolAttr(risk.critical, true)}"/>
212
- <testDurations short="${boolAttr(duration.short, true)}" medium="${boolAttr(duration.medium, true)}" long="${boolAttr(duration.long, true)}"/>
213
- <withNavigationUri enabled="true"/>
214
- </options>
215
- `;
145
+ return (0, abapUnit_1.startUnitTestRunSync)(connection, classNames.map((name) => objects_1.CLASS.uri(name)), options);
216
146
  }
@@ -29,4 +29,50 @@ export declare function getUnitTestRunResult(connection: IAbapConnection, runId:
29
29
  withNavigationUris?: boolean;
30
30
  format?: 'abapunit' | 'junit';
31
31
  }): Promise<IAdtWireResponse>;
32
+ /**
33
+ * Run the ABAP Unit tests of whole objects and answer the finished result —
34
+ * `POST /sap/bc/adt/abapunit/testruns`, one request, no run to poll. The
35
+ * objects are named by their ADT URIs: a class, a report, a function group, a
36
+ * function module.
37
+ *
38
+ * The one implementation of this endpoint: every runner's `runSync`, and the
39
+ * legacy class runner's `run`, send it.
40
+ *
41
+ * **Measured:** synchronous on a modern and a legacy on-prem system, over HTTP
42
+ * and over RFC — `<aunit:runResult>` in the POST's answer, no `Location` — and
43
+ * the typed and `application/xml` bodies byte-identical; the legacy system
44
+ * ignores a typed `Accept` and answers `application/xml` either way. Advertised
45
+ * (2026-10-22) by an on-prem system and an ABAP Cloud system alike, beside
46
+ * `/abapunit/runs`; and on an on-prem S/4HANA 2023 that has no `/runs` at all
47
+ * (fr0ster/mcp-abap-adt#286).
48
+ *
49
+ * **`<options>` decides whether anything runs for a report or a function
50
+ * group.** Measured on premise (SAP_BASIS 816, 2026-10-23): with `<options>`, a
51
+ * report (test class in its own source or in an include it pulls in), a
52
+ * function group and a function module each ran the same tests with the same
53
+ * alerts as `/abapunit/runs`; the same body without `<options>` answered `200`
54
+ * with an empty `<aunit:runResult/>` for all four. An include's own URI
55
+ * answered empty even with `<options>` — its tests run through the report. So
56
+ * every runner but the legacy class runner sends `<options>`.
57
+ *
58
+ * **Reading the result: `kind` carries the distinction, `severity` does not.**
59
+ * A failed assertion and an uncaught exception both come back
60
+ * `severity="critical"`, so a parser classifying on severity reports a short
61
+ * dump as a failed test. `kind` separates them: `failedAssertion`,
62
+ * `exception`, `noTestClasses`.
63
+ *
64
+ * The format differs from `/runs`:
65
+ * - root `aunit:runConfiguration` in `http://www.sap.com/adt/aunit` (not
66
+ * `aunit:run` in `http://www.sap.com/adt/api/aunit`);
67
+ * - objects by URI in `adtcore:objectReferences` — so a run covers whole
68
+ * objects: the format has no way to name one test class inside its
69
+ * container;
70
+ * - `application/xml` for `Content-Type` and `Accept`.
71
+ *
72
+ * `options` absent sends no `<options>` element — the body the legacy class
73
+ * runner has always sent, unchanged. Given (`{}` included), the scope, risk
74
+ * levels and durations go in `<options>` with the same defaults `/runs` gets;
75
+ * `title` and `context` have no place in this format and are not sent.
76
+ */
77
+ export declare function startUnitTestRunSync(connection: IAbapConnection, objectUris: string[], options?: IClassUnitTestRunOptions): Promise<IAdtWireResponse>;
32
78
  //# sourceMappingURL=abapUnit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"abapUnit.d.ts","sourceRoot":"","sources":["../../../src/core/shared/abapUnit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAC7E,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EACjB,MAAM,yCAAyC,CAAC;AAajD,6DAA6D;AAC7D,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wDAAwD;AACxD,wBAAsB,wBAAwB,CAC5C,UAAU,EAAE,eAAe,EAC3B,MAAM,EAAE,kBAAkB,EAC1B,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,gBAAgB,CAAC,CA2C3B;AAED,kBAAkB;AAClB,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,eAAe,EAC3B,KAAK,EAAE,MAAM,EACb,eAAe,GAAE,OAAc,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAU3B;AAED,wCAAwC;AACxC,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,eAAe,EAC3B,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,CAAA;CAAE,GACxE,OAAO,CAAC,gBAAgB,CAAC,CAkB3B"}
1
+ {"version":3,"file":"abapUnit.d.ts","sourceRoot":"","sources":["../../../src/core/shared/abapUnit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAC7E,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EACjB,MAAM,yCAAyC,CAAC;AAajD,6DAA6D;AAC7D,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wDAAwD;AACxD,wBAAsB,wBAAwB,CAC5C,UAAU,EAAE,eAAe,EAC3B,MAAM,EAAE,kBAAkB,EAC1B,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,gBAAgB,CAAC,CA2C3B;AAED,kBAAkB;AAClB,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,eAAe,EAC3B,KAAK,EAAE,MAAM,EACb,eAAe,GAAE,OAAc,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAU3B;AAED,wCAAwC;AACxC,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,eAAe,EAC3B,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,CAAA;CAAE,GACxE,OAAO,CAAC,gBAAgB,CAAC,CAkB3B;AASD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,eAAe,EAC3B,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,gBAAgB,CAAC,CA8B3B"}
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.startUnitTestRunByObject = startUnitTestRunByObject;
18
18
  exports.getUnitTestRunStatus = getUnitTestRunStatus;
19
19
  exports.getUnitTestRunResult = getUnitTestRunResult;
20
+ exports.startUnitTestRunSync = startUnitTestRunSync;
20
21
  const contentTypes_1 = require("../../constants/contentTypes");
21
22
  const xml_1 = require("../../utils/xml");
22
23
  function boolAttr(value, fallback) {
@@ -95,3 +96,100 @@ async function getUnitTestRunResult(connection, runId, options) {
95
96
  },
96
97
  });
97
98
  }
99
+ // =============================================================================
100
+ // The synchronous runner: /abapunit/testruns
101
+ // =============================================================================
102
+ const CT_TESTRUNS = 'application/xml';
103
+ const ACCEPT_TESTRUNS = 'application/xml';
104
+ /**
105
+ * Run the ABAP Unit tests of whole objects and answer the finished result —
106
+ * `POST /sap/bc/adt/abapunit/testruns`, one request, no run to poll. The
107
+ * objects are named by their ADT URIs: a class, a report, a function group, a
108
+ * function module.
109
+ *
110
+ * The one implementation of this endpoint: every runner's `runSync`, and the
111
+ * legacy class runner's `run`, send it.
112
+ *
113
+ * **Measured:** synchronous on a modern and a legacy on-prem system, over HTTP
114
+ * and over RFC — `<aunit:runResult>` in the POST's answer, no `Location` — and
115
+ * the typed and `application/xml` bodies byte-identical; the legacy system
116
+ * ignores a typed `Accept` and answers `application/xml` either way. Advertised
117
+ * (2026-10-22) by an on-prem system and an ABAP Cloud system alike, beside
118
+ * `/abapunit/runs`; and on an on-prem S/4HANA 2023 that has no `/runs` at all
119
+ * (fr0ster/mcp-abap-adt#286).
120
+ *
121
+ * **`<options>` decides whether anything runs for a report or a function
122
+ * group.** Measured on premise (SAP_BASIS 816, 2026-10-23): with `<options>`, a
123
+ * report (test class in its own source or in an include it pulls in), a
124
+ * function group and a function module each ran the same tests with the same
125
+ * alerts as `/abapunit/runs`; the same body without `<options>` answered `200`
126
+ * with an empty `<aunit:runResult/>` for all four. An include's own URI
127
+ * answered empty even with `<options>` — its tests run through the report. So
128
+ * every runner but the legacy class runner sends `<options>`.
129
+ *
130
+ * **Reading the result: `kind` carries the distinction, `severity` does not.**
131
+ * A failed assertion and an uncaught exception both come back
132
+ * `severity="critical"`, so a parser classifying on severity reports a short
133
+ * dump as a failed test. `kind` separates them: `failedAssertion`,
134
+ * `exception`, `noTestClasses`.
135
+ *
136
+ * The format differs from `/runs`:
137
+ * - root `aunit:runConfiguration` in `http://www.sap.com/adt/aunit` (not
138
+ * `aunit:run` in `http://www.sap.com/adt/api/aunit`);
139
+ * - objects by URI in `adtcore:objectReferences` — so a run covers whole
140
+ * objects: the format has no way to name one test class inside its
141
+ * container;
142
+ * - `application/xml` for `Content-Type` and `Accept`.
143
+ *
144
+ * `options` absent sends no `<options>` element — the body the legacy class
145
+ * runner has always sent, unchanged. Given (`{}` included), the scope, risk
146
+ * levels and durations go in `<options>` with the same defaults `/runs` gets;
147
+ * `title` and `context` have no place in this format and are not sent.
148
+ */
149
+ async function startUnitTestRunSync(connection, objectUris, options) {
150
+ const objectRefs = objectUris
151
+ .map((uri) => {
152
+ return ` <adtcore:objectReference adtcore:uri="${(0, xml_1.escapeXmlAttr)(uri)}"/>`;
153
+ })
154
+ .join('\n');
155
+ const xml = `<?xml version="1.0" encoding="UTF-8"?><aunit:runConfiguration xmlns:aunit="http://www.sap.com/adt/aunit">
156
+ <external>
157
+ <coverage active="false"/>
158
+ </external>
159
+ ${options ? testRunsOptions(options) : ''} <adtcore:objectSets xmlns:adtcore="http://www.sap.com/adt/core">
160
+ <objectSet kind="inclusive">
161
+ <adtcore:objectReferences>
162
+ ${objectRefs}
163
+ </adtcore:objectReferences>
164
+ </objectSet>
165
+ </adtcore:objectSets>
166
+ </aunit:runConfiguration>`;
167
+ return connection.makeAdtRequest({
168
+ url: '/sap/bc/adt/abapunit/testruns',
169
+ method: 'POST',
170
+ timeout: 0,
171
+ data: xml,
172
+ headers: {
173
+ 'Content-Type': CT_TESTRUNS,
174
+ Accept: ACCEPT_TESTRUNS,
175
+ },
176
+ });
177
+ }
178
+ /**
179
+ * `<options>` of a `runConfiguration`, as Eclipse sends it. The scope's three
180
+ * flags are `testDeterminationStrategy`'s: own tests are `sameProgram`,
181
+ * foreign tests `assignedTests`, their preview `appendAssignedTestsPreview`.
182
+ */
183
+ function testRunsOptions(options) {
184
+ const scope = options.scope ?? {};
185
+ const risk = options.riskLevel ?? {};
186
+ const duration = options.duration ?? {};
187
+ return ` <options>
188
+ <uriType value="semantic"/>
189
+ <testDeterminationStrategy sameProgram="${boolAttr(scope.ownTests, true)}" assignedTests="${boolAttr(scope.foreignTests, false)}" appendAssignedTestsPreview="${boolAttr(scope.addForeignTestsAsPreview, true)}"/>
190
+ <testRiskLevels harmless="${boolAttr(risk.harmless, true)}" dangerous="${boolAttr(risk.dangerous, true)}" critical="${boolAttr(risk.critical, true)}"/>
191
+ <testDurations short="${boolAttr(duration.short, true)}" medium="${boolAttr(duration.medium, true)}" long="${boolAttr(duration.long, true)}"/>
192
+ <withNavigationUri enabled="true"/>
193
+ </options>
194
+ `;
195
+ }
@@ -39,6 +39,15 @@ export declare abstract class AbapUnitRunner<R extends IAbapUnitRunnerResults> i
39
39
  constructor(connection: IAbapConnection, logger: ILogger | undefined, results: R);
40
40
  /** Start a run of every test class the one named object holds. */
41
41
  protected startByObject<E extends IAdtError>(name: string, type: string, options?: IClassUnitTestRunOptions & IAdtAnalyseOptions<E>): Promise<IAdtResponse<ReturnType<R['run']>, E>>;
42
+ /**
43
+ * Run the tests of whole objects, named by their ADT URIs, and answer the
44
+ * finished result: one POST to `/abapunit/testruns`. Always with
45
+ * `<options>` — without it a report's, a function group's and a function
46
+ * module's run answered an empty result (see `core/shared/abapUnit`). The
47
+ * answer is the result document, so it is read by `result`, the strategy
48
+ * `getResult` uses; `options.analyse` judges it.
49
+ */
50
+ protected startSync<E extends IAdtError>(objectUris: string[], options?: IClassUnitTestRunOptions & IAdtAnalyseOptions<E>): Promise<IAdtResponse<ReturnType<R['result']>, E>>;
42
51
  /**
43
52
  * Poll a run. Takes the run it is about: nothing here remembers the last one
44
53
  * started, because ADT does not either — any holder of the id may ask.
@@ -1 +1 @@
1
- {"version":3,"file":"abapUnitRunner.d.ts","sourceRoot":"","sources":["../../src/executors/abapUnitRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,wBAAwB,EACxB,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAS9D,gFAAgF;AAChF,MAAM,WAAW,sBAAsB;IACrC,mFAAmF;IACnF,QAAQ,CAAC,GAAG,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACvC,kCAAkC;IAClC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAC1C,qDAAqD;IACrD,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;CAC3C;AAED;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB;;;;CAIF,CAAC;AAEnC,8BAAsB,cAAc,CAAC,CAAC,SAAS,sBAAsB,CACnE,YACE,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEvE,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IAC/C,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IACpC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;gBAG5B,UAAU,EAAE,eAAe,EAC3B,MAAM,EAAE,OAAO,GAAG,SAAS,EAC3B,OAAO,EAAE,CAAC;IAOZ,kEAAkE;IAClE,SAAS,CAAC,aAAa,CAAC,CAAC,SAAS,SAAS,EACzC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,wBAAwB,GAAG,kBAAkB,CAAC,CAAC,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAQjD;;;OAGG;IACG,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAC7C,KAAK,EAAE,MAAM,EACb,eAAe,GAAE,OAAO,GAAG,SAAgB,EAC3C,OAAO,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAC9B,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IASpD,6CAA6C;IACvC,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAC7C,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,sBAAsB,GAAG,kBAAkB,CAAC,CAAC,CAAC,GACvD,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CAOrD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,SAAS,SAAS,EACpD,IAAI,EAAE,MAAM,GACX,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAMpB"}
1
+ {"version":3,"file":"abapUnitRunner.d.ts","sourceRoot":"","sources":["../../src/executors/abapUnitRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,wBAAwB,EACxB,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAU9D,gFAAgF;AAChF,MAAM,WAAW,sBAAsB;IACrC,mFAAmF;IACnF,QAAQ,CAAC,GAAG,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACvC,kCAAkC;IAClC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAC1C,qDAAqD;IACrD,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;CAC3C;AAED;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB;;;;CAIF,CAAC;AAEnC,8BAAsB,cAAc,CAAC,CAAC,SAAS,sBAAsB,CACnE,YACE,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEvE,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IAC/C,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IACpC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;gBAG5B,UAAU,EAAE,eAAe,EAC3B,MAAM,EAAE,OAAO,GAAG,SAAS,EAC3B,OAAO,EAAE,CAAC;IAOZ,kEAAkE;IAClE,SAAS,CAAC,aAAa,CAAC,CAAC,SAAS,SAAS,EACzC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,wBAAwB,GAAG,kBAAkB,CAAC,CAAC,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAQjD;;;;;;;OAOG;IACH,SAAS,CAAC,SAAS,CAAC,CAAC,SAAS,SAAS,EACrC,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,CAAC,EAAE,wBAAwB,GAAG,kBAAkB,CAAC,CAAC,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAWpD;;;OAGG;IACG,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAC7C,KAAK,EAAE,MAAM,EACb,eAAe,GAAE,OAAO,GAAG,SAAgB,EAC3C,OAAO,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAC9B,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IASpD,6CAA6C;IACvC,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAC7C,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,sBAAsB,GAAG,kBAAkB,CAAC,CAAC,CAAC,GACvD,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CAOrD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,SAAS,SAAS,EACpD,IAAI,EAAE,MAAM,GACX,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAMpB"}
@@ -41,6 +41,20 @@ class AbapUnitRunner {
41
41
  startByObject(name, type, options) {
42
42
  return (0, adtResponse_1.answering)(() => (0, abapUnit_1.startUnitTestRunByObject)(this.connection, { name, type }, options), this.results.run, options?.analyse);
43
43
  }
44
+ /**
45
+ * Run the tests of whole objects, named by their ADT URIs, and answer the
46
+ * finished result: one POST to `/abapunit/testruns`. Always with
47
+ * `<options>` — without it a report's, a function group's and a function
48
+ * module's run answered an empty result (see `core/shared/abapUnit`). The
49
+ * answer is the result document, so it is read by `result`, the strategy
50
+ * `getResult` uses; `options.analyse` judges it.
51
+ */
52
+ startSync(objectUris, options) {
53
+ // `runOptions` is an object even when the caller gave none, so the
54
+ // `<options>` element is always sent.
55
+ const { analyse, ...runOptions } = options ?? {};
56
+ return (0, adtResponse_1.answering)(() => (0, abapUnit_1.startUnitTestRunSync)(this.connection, objectUris, runOptions), this.results.result, analyse);
57
+ }
44
58
  /**
45
59
  * Poll a run. Takes the run it is about: nothing here remembers the last one
46
60
  * started, because ADT does not either — any holder of the id may ask.
@@ -9,6 +9,11 @@
9
9
  * `osl:object type="FUGR"` ran all seven test methods of a group whose test
10
10
  * include covers two test classes. Running one module's tests only is
11
11
  * `FunctionModuleTestRunner`.
12
+ *
13
+ * Measured on premise (SAP_BASIS 816, 2026-10-23): `/abapunit/testruns` given
14
+ * the group's URI runs the same tests with the same alerts as `/runs` — with
15
+ * the Eclipse-style `<options>` only; without it, an empty result. `runSync`
16
+ * always sends `<options>`.
12
17
  */
13
18
  import type { IAdtAnalyseOptions, IAdtError, IAdtResponse, IAdtRunnable, IClassUnitTestRunOptions } from '@mcp-abap-adt/interfaces-adt';
14
19
  import type { IAbapConnection } from '@mcp-abap-adt/interfaces-adt-connection';
@@ -24,13 +29,32 @@ export declare class FunctionGroupTestRunner<R extends IFunctionGroupTestRunnerR
24
29
  constructor(connection: IAbapConnection, logger?: ILogger, results?: R);
25
30
  /** Run every test class of the group. One POST. */
26
31
  run<E extends IAdtError = IAdtError>(functionGroupName: string, options?: IClassUnitTestRunOptions & IAdtAnalyseOptions<E>): Promise<IAdtResponse<ReturnType<R['run']>, E>>;
32
+ /**
33
+ * Run every test class of the group and answer the finished result. One
34
+ * POST, to `/sap/bc/adt/abapunit/testruns` — the synchronous runner, beside
35
+ * the asynchronous `run` + `getStatus` + `getResult`, which stays the
36
+ * default.
37
+ *
38
+ * An explicit choice of the caller's: nothing here asks the system which
39
+ * runner it has. The group is named by its URI and the run configuration
40
+ * always carries `<options>` (scope, risk levels and durations, with `run`'s
41
+ * defaults) — without it the endpoint answered an empty result for a group
42
+ * with tests. `title` and `context` are not sent.
43
+ *
44
+ * The answer is the `aunit:runResult` document, read by this runner's
45
+ * `result` strategy; whether a failing test is a failure is
46
+ * `options.analyse`'s.
47
+ */
48
+ runSync<E extends IAdtError = IAdtError>(functionGroupName: string, options?: IClassUnitTestRunOptions & IAdtAnalyseOptions<E>): Promise<IAdtResponse<ReturnType<R['result']>, E>>;
27
49
  }
28
50
  /**
29
51
  * Below 7.50: refused without a request, as a report's run is — the legacy
30
- * endpoint has not been measured to find a group's tests.
52
+ * endpoint has not been measured to find a group's tests, with `<options>` or
53
+ * without. `runSync` is refused the same way.
31
54
  */
32
55
  export declare class FunctionGroupTestRunnerLegacy<R extends IFunctionGroupTestRunnerResults = typeof functionGroupTestRunnerDocuments> extends FunctionGroupTestRunner<R> {
33
56
  run<E extends IAdtError = IAdtError>(): Promise<IAdtResponse<ReturnType<R['run']>, E>>;
57
+ runSync<E extends IAdtError = IAdtError>(): Promise<IAdtResponse<ReturnType<R['result']>, E>>;
34
58
  getStatus<E extends IAdtError = IAdtError>(): Promise<IAdtResponse<ReturnType<R['status']>, E>>;
35
59
  getResult<E extends IAdtError = IAdtError>(): Promise<IAdtResponse<ReturnType<R['result']>, E>>;
36
60
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FunctionGroupTestRunner.d.ts","sourceRoot":"","sources":["../../../src/executors/functionGroup/FunctionGroupTestRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,wBAAwB,EACzB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EACL,cAAc,EAEd,KAAK,sBAAsB,EAE5B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,+BAA+B,GAAG,sBAAsB,CAAC;AACrE,eAAO,MAAM,gCAAgC;;;;CAA0B,CAAC;AAExE,qBAAa,uBAAuB,CAChC,CAAC,SACC,+BAA+B,GAAG,OAAO,gCAAgC,CAE7E,SAAQ,cAAc,CAAC,CAAC,CACxB,YACE,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,wBAAwB,CAAC;gBAGpE,UAAU,EAAE,eAAe,EAC3B,MAAM,CAAC,EAAE,OAAO,EAEhB,OAAO,GAAE,CAAoD;IAK/D,mDAAmD;IAC7C,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EACvC,iBAAiB,EAAE,MAAM,EACzB,OAAO,CAAC,EAAE,wBAAwB,GAAG,kBAAkB,CAAC,CAAC,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CAGlD;AAED;;;GAGG;AACH,qBAAa,6BAA6B,CACxC,CAAC,SACC,+BAA+B,GAAG,OAAO,gCAAgC,CAC3E,SAAQ,uBAAuB,CAAC,CAAC,CAAC;IACnB,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAC5D,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CACtC;IAIc,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAClE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;IAIc,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAClE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;CAGF"}
1
+ {"version":3,"file":"FunctionGroupTestRunner.d.ts","sourceRoot":"","sources":["../../../src/executors/functionGroup/FunctionGroupTestRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,wBAAwB,EACzB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAE9D,OAAO,EACL,cAAc,EAEd,KAAK,sBAAsB,EAE5B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,+BAA+B,GAAG,sBAAsB,CAAC;AACrE,eAAO,MAAM,gCAAgC;;;;CAA0B,CAAC;AAExE,qBAAa,uBAAuB,CAChC,CAAC,SACC,+BAA+B,GAAG,OAAO,gCAAgC,CAE7E,SAAQ,cAAc,CAAC,CAAC,CACxB,YACE,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,wBAAwB,CAAC;gBAGpE,UAAU,EAAE,eAAe,EAC3B,MAAM,CAAC,EAAE,OAAO,EAEhB,OAAO,GAAE,CAAoD;IAK/D,mDAAmD;IAC7C,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EACvC,iBAAiB,EAAE,MAAM,EACzB,OAAO,CAAC,EAAE,wBAAwB,GAAG,kBAAkB,CAAC,CAAC,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAIjD;;;;;;;;;;;;;;;OAeG;IACG,OAAO,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAC3C,iBAAiB,EAAE,MAAM,EACzB,OAAO,CAAC,EAAE,wBAAwB,GAAG,kBAAkB,CAAC,CAAC,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CAGrD;AAED;;;;GAIG;AACH,qBAAa,6BAA6B,CACxC,CAAC,SACC,+BAA+B,GAAG,OAAO,gCAAgC,CAC3E,SAAQ,uBAAuB,CAAC,CAAC,CAAC;IACnB,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAC5D,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CACtC;IAIc,OAAO,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAChE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;IAIc,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAClE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;IAIc,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAClE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;CAGF"}
@@ -10,9 +10,15 @@
10
10
  * `osl:object type="FUGR"` ran all seven test methods of a group whose test
11
11
  * include covers two test classes. Running one module's tests only is
12
12
  * `FunctionModuleTestRunner`.
13
+ *
14
+ * Measured on premise (SAP_BASIS 816, 2026-10-23): `/abapunit/testruns` given
15
+ * the group's URI runs the same tests with the same alerts as `/runs` — with
16
+ * the Eclipse-style `<options>` only; without it, an empty result. `runSync`
17
+ * always sends `<options>`.
13
18
  */
14
19
  Object.defineProperty(exports, "__esModule", { value: true });
15
20
  exports.FunctionGroupTestRunnerLegacy = exports.FunctionGroupTestRunner = exports.functionGroupTestRunnerDocuments = void 0;
21
+ const objects_1 = require("../../endpoints/objects");
16
22
  const abapUnitRunner_1 = require("../abapUnitRunner");
17
23
  exports.functionGroupTestRunnerDocuments = abapUnitRunner_1.abapUnitRunnerDocuments;
18
24
  class FunctionGroupTestRunner extends abapUnitRunner_1.AbapUnitRunner {
@@ -25,16 +31,39 @@ class FunctionGroupTestRunner extends abapUnitRunner_1.AbapUnitRunner {
25
31
  async run(functionGroupName, options) {
26
32
  return this.startByObject(functionGroupName, 'FUGR', options);
27
33
  }
34
+ /**
35
+ * Run every test class of the group and answer the finished result. One
36
+ * POST, to `/sap/bc/adt/abapunit/testruns` — the synchronous runner, beside
37
+ * the asynchronous `run` + `getStatus` + `getResult`, which stays the
38
+ * default.
39
+ *
40
+ * An explicit choice of the caller's: nothing here asks the system which
41
+ * runner it has. The group is named by its URI and the run configuration
42
+ * always carries `<options>` (scope, risk levels and durations, with `run`'s
43
+ * defaults) — without it the endpoint answered an empty result for a group
44
+ * with tests. `title` and `context` are not sent.
45
+ *
46
+ * The answer is the `aunit:runResult` document, read by this runner's
47
+ * `result` strategy; whether a failing test is a failure is
48
+ * `options.analyse`'s.
49
+ */
50
+ async runSync(functionGroupName, options) {
51
+ return this.startSync([objects_1.FUNCTION_GROUP.uri(functionGroupName)], options);
52
+ }
28
53
  }
29
54
  exports.FunctionGroupTestRunner = FunctionGroupTestRunner;
30
55
  /**
31
56
  * Below 7.50: refused without a request, as a report's run is — the legacy
32
- * endpoint has not been measured to find a group's tests.
57
+ * endpoint has not been measured to find a group's tests, with `<options>` or
58
+ * without. `runSync` is refused the same way.
33
59
  */
34
60
  class FunctionGroupTestRunnerLegacy extends FunctionGroupTestRunner {
35
61
  async run() {
36
62
  return (0, abapUnitRunner_1.refusedBelow750)("a function group's");
37
63
  }
64
+ async runSync() {
65
+ return (0, abapUnitRunner_1.refusedBelow750)("a function group's");
66
+ }
38
67
  async getStatus() {
39
68
  return (0, abapUnitRunner_1.refusedBelow750)("a function group's");
40
69
  }
@@ -10,11 +10,24 @@
10
10
  * that exercise it, and answered an empty result for another module of the
11
11
  * same group that none of them exercises. The whole group's tests are
12
12
  * `FunctionGroupTestRunner`.
13
+ *
14
+ * Measured on premise again (SAP_BASIS 816, 2026-10-23), with a group whose
15
+ * test include holds one test class that calls the module and one that calls
16
+ * no module: `run` (`FUNC`) ran every test of the group — both classes — and
17
+ * so did the run of a second module that no test calls. That does not
18
+ * reproduce the 2026-09-30 filter; what made the difference is not known.
19
+ * Which tests a module's run covers is ADT's to decide, and nothing here
20
+ * filters them.
13
21
  */
14
- import type { IAdtAnalyseOptions, IAdtError, IAdtResponse, IAdtRunnable, IClassUnitTestRunOptions } from '@mcp-abap-adt/interfaces-adt';
22
+ import type { IAdtAnalyseOptions, IAdtError, IAdtResponse, IAdtRunnable, IClassUnitTestRunOptions, IFunctionModuleConfig } from '@mcp-abap-adt/interfaces-adt';
15
23
  import type { IAbapConnection } from '@mcp-abap-adt/interfaces-adt-connection';
16
24
  import type { ILogger } from '@mcp-abap-adt/interfaces-utils';
17
25
  import { AbapUnitRunner, type IAbapUnitRunnerResults } from '../abapUnitRunner';
26
+ /**
27
+ * What `runSync` is given: the module and its group — the module's URI, which
28
+ * `/abapunit/testruns` addresses, lies under its group's.
29
+ */
30
+ export type IFunctionModuleTestRunSyncTarget = Pick<IFunctionModuleConfig, 'functionGroupName' | 'functionModuleName'>;
18
31
  export type IFunctionModuleTestRunnerResults = IAbapUnitRunnerResults;
19
32
  export declare const functionModuleTestRunnerDocuments: {
20
33
  run: import("@mcp-abap-adt/interfaces-adt").IResultStrategy<string>;
@@ -25,13 +38,45 @@ export declare class FunctionModuleTestRunner<R extends IFunctionModuleTestRunne
25
38
  constructor(connection: IAbapConnection, logger?: ILogger, results?: R);
26
39
  /** Run the test classes that exercise the module. One POST. */
27
40
  run<E extends IAdtError = IAdtError>(functionModuleName: string, options?: IClassUnitTestRunOptions & IAdtAnalyseOptions<E>): Promise<IAdtResponse<ReturnType<R['run']>, E>>;
41
+ /**
42
+ * Run the module's tests and answer the finished result. One POST, to
43
+ * `/sap/bc/adt/abapunit/testruns` — the synchronous runner, beside the
44
+ * asynchronous `run` + `getStatus` + `getResult`, which stays the default.
45
+ *
46
+ * An explicit choice of the caller's: nothing here asks the system which
47
+ * runner it has. The module is named by its URI, which lies under its
48
+ * group's, so the target names both. The run configuration always carries
49
+ * `<options>` (scope, risk levels and durations, with `run`'s defaults) —
50
+ * without it the endpoint answered an empty result. `title` and `context`
51
+ * are not sent.
52
+ *
53
+ * **It does not keep to the module's tests.** Measured on premise
54
+ * (SAP_BASIS 816, 2026-10-23): the module's URI ran every test of its group —
55
+ * the result names the group (`adtcore:type="FUGR/F"`) — including a test
56
+ * class that calls no module, and the run of a module that no test calls
57
+ * answered the same. `run` answered the same there too. Nothing here filters
58
+ * the result; a caller who wants one module's tests reads them out of it.
59
+ *
60
+ * With an ABAP Doc test relation (`"! @testing FUNC:<module>`) on a test
61
+ * class of the group, the same request with the default scope answered the
62
+ * group's tests as a preview — `isForeign="true"`, nothing executed, no
63
+ * alerts — and with `scope: { foreignTests: true }` ran them all (measured
64
+ * once, 2026-10-23, same system).
65
+ *
66
+ * The answer is the `aunit:runResult` document, read by this runner's
67
+ * `result` strategy; whether a failing test is a failure is
68
+ * `options.analyse`'s.
69
+ */
70
+ runSync<E extends IAdtError = IAdtError>(target: IFunctionModuleTestRunSyncTarget, options?: IClassUnitTestRunOptions & IAdtAnalyseOptions<E>): Promise<IAdtResponse<ReturnType<R['result']>, E>>;
28
71
  }
29
72
  /**
30
73
  * Below 7.50: refused without a request, as a report's run is — the legacy
31
- * endpoint has not been measured to find a module's tests.
74
+ * endpoint has not been measured to find a module's tests, with `<options>` or
75
+ * without. `runSync` is refused the same way.
32
76
  */
33
77
  export declare class FunctionModuleTestRunnerLegacy<R extends IFunctionModuleTestRunnerResults = typeof functionModuleTestRunnerDocuments> extends FunctionModuleTestRunner<R> {
34
78
  run<E extends IAdtError = IAdtError>(): Promise<IAdtResponse<ReturnType<R['run']>, E>>;
79
+ runSync<E extends IAdtError = IAdtError>(): Promise<IAdtResponse<ReturnType<R['result']>, E>>;
35
80
  getStatus<E extends IAdtError = IAdtError>(): Promise<IAdtResponse<ReturnType<R['status']>, E>>;
36
81
  getResult<E extends IAdtError = IAdtError>(): Promise<IAdtResponse<ReturnType<R['result']>, E>>;
37
82
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FunctionModuleTestRunner.d.ts","sourceRoot":"","sources":["../../../src/executors/functionModule/FunctionModuleTestRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,wBAAwB,EACzB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EACL,cAAc,EAEd,KAAK,sBAAsB,EAE5B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,gCAAgC,GAAG,sBAAsB,CAAC;AACtE,eAAO,MAAM,iCAAiC;;;;CAA0B,CAAC;AAEzE,qBAAa,wBAAwB,CACjC,CAAC,SACC,gCAAgC,GAAG,OAAO,iCAAiC,CAE/E,SAAQ,cAAc,CAAC,CAAC,CACxB,YACE,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,wBAAwB,CAAC;gBAGpE,UAAU,EAAE,eAAe,EAC3B,MAAM,CAAC,EAAE,OAAO,EAEhB,OAAO,GAAE,CAAqD;IAKhE,+DAA+D;IACzD,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EACvC,kBAAkB,EAAE,MAAM,EAC1B,OAAO,CAAC,EAAE,wBAAwB,GAAG,kBAAkB,CAAC,CAAC,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CAGlD;AAED;;;GAGG;AACH,qBAAa,8BAA8B,CACzC,CAAC,SACC,gCAAgC,GAAG,OAAO,iCAAiC,CAC7E,SAAQ,wBAAwB,CAAC,CAAC,CAAC;IACpB,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAC5D,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CACtC;IAIc,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAClE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;IAIc,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAClE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;CAGF"}
1
+ {"version":3,"file":"FunctionModuleTestRunner.d.ts","sourceRoot":"","sources":["../../../src/executors/functionModule/FunctionModuleTestRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,wBAAwB,EACxB,qBAAqB,EACtB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAE9D,OAAO,EACL,cAAc,EAEd,KAAK,sBAAsB,EAE5B,MAAM,mBAAmB,CAAC;AAE3B;;;GAGG;AACH,MAAM,MAAM,gCAAgC,GAAG,IAAI,CACjD,qBAAqB,EACrB,mBAAmB,GAAG,oBAAoB,CAC3C,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG,sBAAsB,CAAC;AACtE,eAAO,MAAM,iCAAiC;;;;CAA0B,CAAC;AAEzE,qBAAa,wBAAwB,CACjC,CAAC,SACC,gCAAgC,GAAG,OAAO,iCAAiC,CAE/E,SAAQ,cAAc,CAAC,CAAC,CACxB,YACE,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,wBAAwB,CAAC;gBAGpE,UAAU,EAAE,eAAe,EAC3B,MAAM,CAAC,EAAE,OAAO,EAEhB,OAAO,GAAE,CAAqD;IAKhE,+DAA+D;IACzD,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EACvC,kBAAkB,EAAE,MAAM,EAC1B,OAAO,CAAC,EAAE,wBAAwB,GAAG,kBAAkB,CAAC,CAAC,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAIjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACG,OAAO,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAC3C,MAAM,EAAE,gCAAgC,EACxC,OAAO,CAAC,EAAE,wBAAwB,GAAG,kBAAkB,CAAC,CAAC,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CAWrD;AAED;;;;GAIG;AACH,qBAAa,8BAA8B,CACzC,CAAC,SACC,gCAAgC,GAAG,OAAO,iCAAiC,CAC7E,SAAQ,wBAAwB,CAAC,CAAC,CAAC;IACpB,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAC5D,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CACtC;IAIc,OAAO,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAChE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;IAIc,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAClE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;IAIc,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAClE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;CAGF"}
@@ -11,9 +11,18 @@
11
11
  * that exercise it, and answered an empty result for another module of the
12
12
  * same group that none of them exercises. The whole group's tests are
13
13
  * `FunctionGroupTestRunner`.
14
+ *
15
+ * Measured on premise again (SAP_BASIS 816, 2026-10-23), with a group whose
16
+ * test include holds one test class that calls the module and one that calls
17
+ * no module: `run` (`FUNC`) ran every test of the group — both classes — and
18
+ * so did the run of a second module that no test calls. That does not
19
+ * reproduce the 2026-09-30 filter; what made the difference is not known.
20
+ * Which tests a module's run covers is ADT's to decide, and nothing here
21
+ * filters them.
14
22
  */
15
23
  Object.defineProperty(exports, "__esModule", { value: true });
16
24
  exports.FunctionModuleTestRunnerLegacy = exports.FunctionModuleTestRunner = exports.functionModuleTestRunnerDocuments = void 0;
25
+ const objects_1 = require("../../endpoints/objects");
17
26
  const abapUnitRunner_1 = require("../abapUnitRunner");
18
27
  exports.functionModuleTestRunnerDocuments = abapUnitRunner_1.abapUnitRunnerDocuments;
19
28
  class FunctionModuleTestRunner extends abapUnitRunner_1.AbapUnitRunner {
@@ -26,16 +35,54 @@ class FunctionModuleTestRunner extends abapUnitRunner_1.AbapUnitRunner {
26
35
  async run(functionModuleName, options) {
27
36
  return this.startByObject(functionModuleName, 'FUNC', options);
28
37
  }
38
+ /**
39
+ * Run the module's tests and answer the finished result. One POST, to
40
+ * `/sap/bc/adt/abapunit/testruns` — the synchronous runner, beside the
41
+ * asynchronous `run` + `getStatus` + `getResult`, which stays the default.
42
+ *
43
+ * An explicit choice of the caller's: nothing here asks the system which
44
+ * runner it has. The module is named by its URI, which lies under its
45
+ * group's, so the target names both. The run configuration always carries
46
+ * `<options>` (scope, risk levels and durations, with `run`'s defaults) —
47
+ * without it the endpoint answered an empty result. `title` and `context`
48
+ * are not sent.
49
+ *
50
+ * **It does not keep to the module's tests.** Measured on premise
51
+ * (SAP_BASIS 816, 2026-10-23): the module's URI ran every test of its group —
52
+ * the result names the group (`adtcore:type="FUGR/F"`) — including a test
53
+ * class that calls no module, and the run of a module that no test calls
54
+ * answered the same. `run` answered the same there too. Nothing here filters
55
+ * the result; a caller who wants one module's tests reads them out of it.
56
+ *
57
+ * With an ABAP Doc test relation (`"! @testing FUNC:<module>`) on a test
58
+ * class of the group, the same request with the default scope answered the
59
+ * group's tests as a preview — `isForeign="true"`, nothing executed, no
60
+ * alerts — and with `scope: { foreignTests: true }` ran them all (measured
61
+ * once, 2026-10-23, same system).
62
+ *
63
+ * The answer is the `aunit:runResult` document, read by this runner's
64
+ * `result` strategy; whether a failing test is a failure is
65
+ * `options.analyse`'s.
66
+ */
67
+ async runSync(target, options) {
68
+ return this.startSync([
69
+ objects_1.FUNCTION_MODULE.uri(target.functionGroupName, target.functionModuleName),
70
+ ], options);
71
+ }
29
72
  }
30
73
  exports.FunctionModuleTestRunner = FunctionModuleTestRunner;
31
74
  /**
32
75
  * Below 7.50: refused without a request, as a report's run is — the legacy
33
- * endpoint has not been measured to find a module's tests.
76
+ * endpoint has not been measured to find a module's tests, with `<options>` or
77
+ * without. `runSync` is refused the same way.
34
78
  */
35
79
  class FunctionModuleTestRunnerLegacy extends FunctionModuleTestRunner {
36
80
  async run() {
37
81
  return (0, abapUnitRunner_1.refusedBelow750)("a function module's");
38
82
  }
83
+ async runSync() {
84
+ return (0, abapUnitRunner_1.refusedBelow750)("a function module's");
85
+ }
39
86
  async getStatus() {
40
87
  return (0, abapUnitRunner_1.refusedBelow750)("a function module's");
41
88
  }
@@ -1,2 +1,2 @@
1
- export { FunctionModuleTestRunner, FunctionModuleTestRunnerLegacy, functionModuleTestRunnerDocuments, type IFunctionModuleTestRunnerResults, } from './FunctionModuleTestRunner';
1
+ export { FunctionModuleTestRunner, FunctionModuleTestRunnerLegacy, functionModuleTestRunnerDocuments, type IFunctionModuleTestRunnerResults, type IFunctionModuleTestRunSyncTarget, } from './FunctionModuleTestRunner';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/executors/functionModule/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,8BAA8B,EAC9B,iCAAiC,EACjC,KAAK,gCAAgC,GACtC,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/executors/functionModule/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,8BAA8B,EAC9B,iCAAiC,EACjC,KAAK,gCAAgC,EACrC,KAAK,gCAAgC,GACtC,MAAM,4BAA4B,CAAC"}
@@ -1,7 +1,7 @@
1
1
  export { AbapUnitRunner, abapUnitRunnerDocuments, type IAbapUnitRunnerResults, } from './abapUnitRunner';
2
2
  export { ClassExecutor, ClassTestRunner, ClassTestRunnerLegacy, classExecutorDocuments, classTestRunnerDocuments, type IClassExecutorResults, type IClassTestRunnerResults, type IClassTestRunTarget, } from './class';
3
3
  export { FunctionGroupTestRunner, FunctionGroupTestRunnerLegacy, functionGroupTestRunnerDocuments, type IFunctionGroupTestRunnerResults, } from './functionGroup';
4
- export { FunctionModuleTestRunner, FunctionModuleTestRunnerLegacy, functionModuleTestRunnerDocuments, type IFunctionModuleTestRunnerResults, } from './functionModule';
4
+ export { FunctionModuleTestRunner, FunctionModuleTestRunnerLegacy, functionModuleTestRunnerDocuments, type IFunctionModuleTestRunnerResults, type IFunctionModuleTestRunSyncTarget, } from './functionModule';
5
5
  export { type IProgramExecutorResults, type IProgramTestRunnerResults, ProgramExecutor, ProgramTestRunner, ProgramTestRunnerLegacy, programExecutorDocuments, programTestRunnerDocuments, } from './program';
6
6
  export { type ITraceSchedulingResults, TraceScheduling, traceSchedulingDocuments, } from './traceScheduling';
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/executors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,KAAK,sBAAsB,GAC5B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,GACzB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,uBAAuB,EACvB,6BAA6B,EAC7B,gCAAgC,EAChC,KAAK,+BAA+B,GACrC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,wBAAwB,EACxB,8BAA8B,EAC9B,iCAAiC,EACjC,KAAK,gCAAgC,GACtC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC9B,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,KAAK,uBAAuB,EAC5B,eAAe,EACf,wBAAwB,GACzB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/executors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,KAAK,sBAAsB,GAC5B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,GACzB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,uBAAuB,EACvB,6BAA6B,EAC7B,gCAAgC,EAChC,KAAK,+BAA+B,GACrC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,wBAAwB,EACxB,8BAA8B,EAC9B,iCAAiC,EACjC,KAAK,gCAAgC,EACrC,KAAK,gCAAgC,GACtC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC9B,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,KAAK,uBAAuB,EAC5B,eAAe,EACf,wBAAwB,GACzB,MAAM,mBAAmB,CAAC"}
@@ -10,9 +10,16 @@
10
10
  *
11
11
  * Measured on premise (2026-09-30): one `POST /abapunit/runs` naming the report
12
12
  * as `osl:object type="PROG"` runs its test classes wherever they sit — own
13
- * source or include. `/abapunit/testruns` given the report's URI answered an
14
- * empty result for the same report, so the legacy runner refuses rather than
15
- * send it (`ProgramTestRunnerLegacy`).
13
+ * source or include.
14
+ *
15
+ * Measured on premise again (SAP_BASIS 816, 2026-10-23): `/abapunit/testruns`
16
+ * given the report's URI runs the same tests with the same alerts — but only
17
+ * with the Eclipse-style `<options>` in the run configuration. Without it, the
18
+ * body sent on 2026-09-30, it answers `200` with an empty result: that, not the
19
+ * endpoint, was why that run found nothing. `runSync` therefore always sends
20
+ * `<options>`. An include's own URI answers empty even with `<options>`; its
21
+ * tests run through the report. The legacy runner still refuses: no legacy
22
+ * system has been measured with `<options>` (`ProgramTestRunnerLegacy`).
16
23
  */
17
24
  import type { IAdtAnalyseOptions, IAdtError, IAdtResponse, IAdtRunnable, IClassUnitTestRunOptions } from '@mcp-abap-adt/interfaces-adt';
18
25
  import type { IAbapConnection } from '@mcp-abap-adt/interfaces-adt-connection';
@@ -28,5 +35,25 @@ export declare class ProgramTestRunner<R extends IProgramTestRunnerResults = typ
28
35
  constructor(connection: IAbapConnection, logger?: ILogger, results?: R);
29
36
  /** Run every test class of the report. One POST. */
30
37
  run<E extends IAdtError = IAdtError>(programName: string, options?: IClassUnitTestRunOptions & IAdtAnalyseOptions<E>): Promise<IAdtResponse<ReturnType<R['run']>, E>>;
38
+ /**
39
+ * Run every test class of the report and answer the finished result. One
40
+ * POST, to `/sap/bc/adt/abapunit/testruns` — the synchronous runner, beside
41
+ * the asynchronous `run` + `getStatus` + `getResult`, which stays the
42
+ * default.
43
+ *
44
+ * An explicit choice of the caller's: nothing here asks the system which
45
+ * runner it has. The report is named by its URI and the run configuration
46
+ * always carries `<options>` (scope, risk levels and durations, with `run`'s
47
+ * defaults) — without it the endpoint answered an empty result for a report
48
+ * with tests. `title` and `context` have no place in this format and are not
49
+ * sent. Name the report, not an include: an include's tests run through the
50
+ * report that pulls it in.
51
+ *
52
+ * The answer is the `aunit:runResult` document, read by this runner's
53
+ * `result` strategy — the one `getResult` uses; whether a failing test is a
54
+ * failure is `options.analyse`'s (`analyseUnitTest` from
55
+ * @mcp-abap-adt/adt-strategies reads it so).
56
+ */
57
+ runSync<E extends IAdtError = IAdtError>(programName: string, options?: IClassUnitTestRunOptions & IAdtAnalyseOptions<E>): Promise<IAdtResponse<ReturnType<R['result']>, E>>;
31
58
  }
32
59
  //# sourceMappingURL=ProgramTestRunner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProgramTestRunner.d.ts","sourceRoot":"","sources":["../../../src/executors/program/ProgramTestRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,wBAAwB,EACzB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EACL,cAAc,EAEd,KAAK,sBAAsB,EAC5B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,yBAAyB,GAAG,sBAAsB,CAAC;AAC/D,eAAO,MAAM,0BAA0B;;;;CAA0B,CAAC;AAElE,qBAAa,iBAAiB,CAC1B,CAAC,SAAS,yBAAyB,GAAG,OAAO,0BAA0B,CAEzE,SAAQ,cAAc,CAAC,CAAC,CACxB,YACE,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,wBAAwB,CAAC;gBAGpE,UAAU,EAAE,eAAe,EAC3B,MAAM,CAAC,EAAE,OAAO,EAEhB,OAAO,GAAE,CAA8C;IAKzD,oDAAoD;IAC9C,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EACvC,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,wBAAwB,GAAG,kBAAkB,CAAC,CAAC,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CAGlD"}
1
+ {"version":3,"file":"ProgramTestRunner.d.ts","sourceRoot":"","sources":["../../../src/executors/program/ProgramTestRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,wBAAwB,EACzB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAE9D,OAAO,EACL,cAAc,EAEd,KAAK,sBAAsB,EAC5B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,yBAAyB,GAAG,sBAAsB,CAAC;AAC/D,eAAO,MAAM,0BAA0B;;;;CAA0B,CAAC;AAElE,qBAAa,iBAAiB,CAC1B,CAAC,SAAS,yBAAyB,GAAG,OAAO,0BAA0B,CAEzE,SAAQ,cAAc,CAAC,CAAC,CACxB,YACE,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,wBAAwB,CAAC;gBAGpE,UAAU,EAAE,eAAe,EAC3B,MAAM,CAAC,EAAE,OAAO,EAEhB,OAAO,GAAE,CAA8C;IAKzD,oDAAoD;IAC9C,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EACvC,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,wBAAwB,GAAG,kBAAkB,CAAC,CAAC,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAIjD;;;;;;;;;;;;;;;;;;OAkBG;IACG,OAAO,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAC3C,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,wBAAwB,GAAG,kBAAkB,CAAC,CAAC,CAAC,GACzD,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CAGrD"}
@@ -11,12 +11,20 @@
11
11
  *
12
12
  * Measured on premise (2026-09-30): one `POST /abapunit/runs` naming the report
13
13
  * as `osl:object type="PROG"` runs its test classes wherever they sit — own
14
- * source or include. `/abapunit/testruns` given the report's URI answered an
15
- * empty result for the same report, so the legacy runner refuses rather than
16
- * send it (`ProgramTestRunnerLegacy`).
14
+ * source or include.
15
+ *
16
+ * Measured on premise again (SAP_BASIS 816, 2026-10-23): `/abapunit/testruns`
17
+ * given the report's URI runs the same tests with the same alerts — but only
18
+ * with the Eclipse-style `<options>` in the run configuration. Without it, the
19
+ * body sent on 2026-09-30, it answers `200` with an empty result: that, not the
20
+ * endpoint, was why that run found nothing. `runSync` therefore always sends
21
+ * `<options>`. An include's own URI answers empty even with `<options>`; its
22
+ * tests run through the report. The legacy runner still refuses: no legacy
23
+ * system has been measured with `<options>` (`ProgramTestRunnerLegacy`).
17
24
  */
18
25
  Object.defineProperty(exports, "__esModule", { value: true });
19
26
  exports.ProgramTestRunner = exports.programTestRunnerDocuments = void 0;
27
+ const objects_1 = require("../../endpoints/objects");
20
28
  const abapUnitRunner_1 = require("../abapUnitRunner");
21
29
  exports.programTestRunnerDocuments = abapUnitRunner_1.abapUnitRunnerDocuments;
22
30
  class ProgramTestRunner extends abapUnitRunner_1.AbapUnitRunner {
@@ -29,5 +37,27 @@ class ProgramTestRunner extends abapUnitRunner_1.AbapUnitRunner {
29
37
  async run(programName, options) {
30
38
  return this.startByObject(programName, 'PROG', options);
31
39
  }
40
+ /**
41
+ * Run every test class of the report and answer the finished result. One
42
+ * POST, to `/sap/bc/adt/abapunit/testruns` — the synchronous runner, beside
43
+ * the asynchronous `run` + `getStatus` + `getResult`, which stays the
44
+ * default.
45
+ *
46
+ * An explicit choice of the caller's: nothing here asks the system which
47
+ * runner it has. The report is named by its URI and the run configuration
48
+ * always carries `<options>` (scope, risk levels and durations, with `run`'s
49
+ * defaults) — without it the endpoint answered an empty result for a report
50
+ * with tests. `title` and `context` have no place in this format and are not
51
+ * sent. Name the report, not an include: an include's tests run through the
52
+ * report that pulls it in.
53
+ *
54
+ * The answer is the `aunit:runResult` document, read by this runner's
55
+ * `result` strategy — the one `getResult` uses; whether a failing test is a
56
+ * failure is `options.analyse`'s (`analyseUnitTest` from
57
+ * @mcp-abap-adt/adt-strategies reads it so).
58
+ */
59
+ async runSync(programName, options) {
60
+ return this.startSync([objects_1.PROGRAM.uri(programName)], options);
61
+ }
32
62
  }
33
63
  exports.ProgramTestRunner = ProgramTestRunner;
@@ -3,15 +3,18 @@
3
3
  * (BASIS < 7.50), which has no `/abapunit/runs`.
4
4
  *
5
5
  * Refused without a request. The legacy endpoint, `/abapunit/testruns`, was
6
- * given a report's URI on premise (2026-09-30) and answered an empty result for
7
- * a report whose tests `/abapunit/runs` found — so sending it would answer "no
8
- * tests" where there are some. It stays refused until a legacy system is
9
- * measured.
6
+ * given a report's URI on premise (2026-09-30) without `<options>` — the body a
7
+ * legacy system is sent — and answered an empty result for a report whose
8
+ * tests `/abapunit/runs` found, so sending it would answer "no tests" where
9
+ * there are some. With `<options>` it runs them on SAP_BASIS 816 (2026-10-23),
10
+ * but no legacy system has been measured with that body: `run` and `runSync`
11
+ * stay refused until one is.
10
12
  */
11
13
  import type { IAdtError, IAdtResponse } from '@mcp-abap-adt/interfaces-adt';
12
14
  import { type IProgramTestRunnerResults, ProgramTestRunner, type programTestRunnerDocuments } from './ProgramTestRunner';
13
15
  export declare class ProgramTestRunnerLegacy<R extends IProgramTestRunnerResults = typeof programTestRunnerDocuments> extends ProgramTestRunner<R> {
14
16
  run<E extends IAdtError = IAdtError>(): Promise<IAdtResponse<ReturnType<R['run']>, E>>;
17
+ runSync<E extends IAdtError = IAdtError>(): Promise<IAdtResponse<ReturnType<R['result']>, E>>;
15
18
  getStatus<E extends IAdtError = IAdtError>(): Promise<IAdtResponse<ReturnType<R['status']>, E>>;
16
19
  getResult<E extends IAdtError = IAdtError>(): Promise<IAdtResponse<ReturnType<R['result']>, E>>;
17
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ProgramTestRunnerLegacy.d.ts","sourceRoot":"","sources":["../../../src/executors/program/ProgramTestRunnerLegacy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5E,OAAO,EACL,KAAK,yBAAyB,EAC9B,iBAAiB,EACjB,KAAK,0BAA0B,EAChC,MAAM,qBAAqB,CAAC;AAE7B,qBAAa,uBAAuB,CAClC,CAAC,SAAS,yBAAyB,GAAG,OAAO,0BAA0B,CACvE,SAAQ,iBAAiB,CAAC,CAAC,CAAC;IACb,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAC5D,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CACtC;IAIc,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAClE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;IAIc,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAClE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;CAGF"}
1
+ {"version":3,"file":"ProgramTestRunnerLegacy.d.ts","sourceRoot":"","sources":["../../../src/executors/program/ProgramTestRunnerLegacy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5E,OAAO,EACL,KAAK,yBAAyB,EAC9B,iBAAiB,EACjB,KAAK,0BAA0B,EAChC,MAAM,qBAAqB,CAAC;AAE7B,qBAAa,uBAAuB,CAClC,CAAC,SAAS,yBAAyB,GAAG,OAAO,0BAA0B,CACvE,SAAQ,iBAAiB,CAAC,CAAC,CAAC;IACb,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAC5D,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CACtC;IAIc,OAAO,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAChE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;IAIc,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAClE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;IAIc,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAClE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;CAGF"}
@@ -4,10 +4,12 @@
4
4
  * (BASIS < 7.50), which has no `/abapunit/runs`.
5
5
  *
6
6
  * Refused without a request. The legacy endpoint, `/abapunit/testruns`, was
7
- * given a report's URI on premise (2026-09-30) and answered an empty result for
8
- * a report whose tests `/abapunit/runs` found — so sending it would answer "no
9
- * tests" where there are some. It stays refused until a legacy system is
10
- * measured.
7
+ * given a report's URI on premise (2026-09-30) without `<options>` — the body a
8
+ * legacy system is sent — and answered an empty result for a report whose
9
+ * tests `/abapunit/runs` found, so sending it would answer "no tests" where
10
+ * there are some. With `<options>` it runs them on SAP_BASIS 816 (2026-10-23),
11
+ * but no legacy system has been measured with that body: `run` and `runSync`
12
+ * stay refused until one is.
11
13
  */
12
14
  Object.defineProperty(exports, "__esModule", { value: true });
13
15
  exports.ProgramTestRunnerLegacy = void 0;
@@ -17,6 +19,9 @@ class ProgramTestRunnerLegacy extends ProgramTestRunner_1.ProgramTestRunner {
17
19
  async run() {
18
20
  return (0, abapUnitRunner_1.refusedBelow750)("a report's");
19
21
  }
22
+ async runSync() {
23
+ return (0, abapUnitRunner_1.refusedBelow750)("a report's");
24
+ }
20
25
  async getStatus() {
21
26
  return (0, abapUnitRunner_1.refusedBelow750)("a report's");
22
27
  }
@@ -10,7 +10,7 @@ export { createAdtExecutor } from './clients/createAdtExecutor';
10
10
  export { classExecutorDocuments, type IClassExecutorResults, } from './executors/class/ClassExecutor';
11
11
  export { classTestRunnerDocuments, type IClassTestRunnerResults, type IClassTestRunTarget, } from './executors/class/ClassTestRunner';
12
12
  export { functionGroupTestRunnerDocuments, type IFunctionGroupTestRunnerResults, } from './executors/functionGroup/FunctionGroupTestRunner';
13
- export { functionModuleTestRunnerDocuments, type IFunctionModuleTestRunnerResults, } from './executors/functionModule/FunctionModuleTestRunner';
13
+ export { functionModuleTestRunnerDocuments, type IFunctionModuleTestRunnerResults, type IFunctionModuleTestRunSyncTarget, } from './executors/functionModule/FunctionModuleTestRunner';
14
14
  export { type IProgramExecutorResults, programExecutorDocuments, } from './executors/program/ProgramExecutor';
15
15
  export { type IProgramTestRunnerResults, programTestRunnerDocuments, } from './executors/program/ProgramTestRunner';
16
16
  export { type ITraceSchedulingResults, traceSchedulingDocuments, } from './executors/traceScheduling';
@@ -1 +1 @@
1
- {"version":3,"file":"index.executors.d.ts","sourceRoot":"","sources":["../src/index.executors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EACL,sBAAsB,EACtB,KAAK,qBAAqB,GAC3B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,wBAAwB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,GACzB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,gCAAgC,EAChC,KAAK,+BAA+B,GACrC,MAAM,mDAAmD,CAAC;AAC3D,OAAO,EACL,iCAAiC,EACjC,KAAK,gCAAgC,GACtC,MAAM,qDAAqD,CAAC;AAC7D,OAAO,EACL,KAAK,uBAAuB,EAC5B,wBAAwB,GACzB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,KAAK,yBAAyB,EAC9B,0BAA0B,GAC3B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,KAAK,uBAAuB,EAC5B,wBAAwB,GACzB,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.executors.d.ts","sourceRoot":"","sources":["../src/index.executors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EACL,sBAAsB,EACtB,KAAK,qBAAqB,GAC3B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,wBAAwB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,GACzB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,gCAAgC,EAChC,KAAK,+BAA+B,GACrC,MAAM,mDAAmD,CAAC;AAC3D,OAAO,EACL,iCAAiC,EACjC,KAAK,gCAAgC,EACrC,KAAK,gCAAgC,GACtC,MAAM,qDAAqD,CAAC;AAC7D,OAAO,EACL,KAAK,uBAAuB,EAC5B,wBAAwB,GACzB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,KAAK,yBAAyB,EAC9B,0BAA0B,GAC3B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,KAAK,uBAAuB,EAC5B,wBAAwB,GACzB,MAAM,6BAA6B,CAAC"}
@@ -586,5 +586,5 @@ INTERFACE … does not exist."*, *"Data definition … of version does not
586
586
  exist"*. All mean the same thing, and none is worth matching on: branch on the
587
587
  failure your own `analyse` decided.
588
588
 
589
- Reproduce with `npx ts-node scripts/probe-inactive-metadata.ts` and
590
- `npx ts-node scripts/probe-unfinished-create.ts`.
589
+ Reproduce with `node_modules/.bin/ts-node scripts/probe-inactive-metadata.ts` and
590
+ `node_modules/.bin/ts-node scripts/probe-unfinished-create.ts`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-abap-adt/adt-clients",
3
- "version": "37.1.0",
3
+ "version": "37.2.0",
4
4
  "description": "ADT clients for SAP ABAP systems - AdtClient and AdtRuntimeClient",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -80,34 +80,35 @@
80
80
  "scripts": {
81
81
  "chrono": "./tools/version-stats.sh",
82
82
  "clean": "node -e \"const fs=require('fs');['dist','tsconfig.tsbuildinfo'].forEach(p=>{try{fs.rmSync(p,{recursive:true,force:true})}catch{}})\"",
83
- "lint": "npx biome check --write src packages",
84
- "lint:check": "npx biome check src packages && npm run --silent check:docs",
83
+ "lint": "biome check --write src packages",
84
+ "lint:check": "biome check src packages && npm run --silent check:docs",
85
85
  "check:docs": "node scripts/check-doc-imports.js",
86
- "format": "npx biome format --write src packages",
87
- "build": "npm run --silent clean && npx biome check src packages --diagnostic-level=error && npx tsc -p tsconfig.json",
88
- "build:fast": "npx tsc -p tsconfig.json",
86
+ "format": "biome format --write src packages",
87
+ "build": "npm run --silent clean && biome check src packages --diagnostic-level=error && tsc -p tsconfig.json",
88
+ "build:fast": "tsc -p tsconfig.json",
89
89
  "test:init": "node -e \"const fs=require('fs'),s='src/__tests__/helpers/test-config.yaml',t=s+'.template';if(fs.existsSync(s)){console.log(s+' already exists, skipping (use test:reinit to overwrite)')}else{fs.copyFileSync(t,s);console.log('Created '+s+' — edit lines marked CHANGE')}\"",
90
90
  "test:reinit": "node -e \"const fs=require('fs'),s='src/__tests__/helpers/test-config.yaml',t=s+'.template';fs.copyFileSync(t,s);console.log('Recreated '+s+' from template')\"",
91
- "test": "npx jest --runInBand",
91
+ "test": "jest --runInBand",
92
+ "test:unit": "jest src/__tests__/unit",
92
93
  "test:detached": "bash scripts/run-detached.sh",
93
- "test:check": "npx tsc --noEmit --project tsconfig.test.json",
94
+ "test:check": "tsc --noEmit --project tsconfig.test.json",
94
95
  "test:type-check": "npm run test:check",
95
- "test:check:integration": "npx tsc --noEmit --project tsconfig.test.integration.json",
96
+ "test:check:integration": "tsc --noEmit --project tsconfig.test.integration.json",
96
97
  "test:sequential": "node scripts/run-tests-sequential.js",
97
98
  "test:module": "node scripts/test-module.js",
98
- "test:long-polling-read": "npx ts-node scripts/test-long-polling-read.ts",
99
- "package:contents": "npx ts-node scripts/show-package-contents.ts",
100
- "discovery:markdown": "npx ts-node tools/discovery-to-markdown.ts",
101
- "header:discovery": "npx ts-node tools/header-probe/errorCorpus.ts",
99
+ "test:long-polling-read": "ts-node scripts/test-long-polling-read.ts",
100
+ "package:contents": "ts-node scripts/show-package-contents.ts",
101
+ "discovery:markdown": "ts-node tools/discovery-to-markdown.ts",
102
+ "header:discovery": "ts-node tools/header-probe/errorCorpus.ts",
102
103
  "adt:entities": "node tools/adt-object-entities.js",
103
- "shared:setup": "npx jest --testPathIgnorePatterns node_modules --testPathPatterns admin/shared-deps/setup",
104
- "shared:teardown": "npx jest --testPathIgnorePatterns node_modules --testPathPatterns admin/shared-deps/teardown",
105
- "shared:check": "npx jest --testPathIgnorePatterns node_modules --testPathPatterns admin/shared-deps/check",
104
+ "shared:setup": "jest --testPathIgnorePatterns node_modules --testPathPatterns admin/shared-deps/setup",
105
+ "shared:teardown": "jest --testPathIgnorePatterns node_modules --testPathPatterns admin/shared-deps/teardown",
106
+ "shared:check": "jest --testPathIgnorePatterns node_modules --testPathPatterns admin/shared-deps/check",
106
107
  "pretest": "npm run test:check:integration && npm run --silent check:config",
107
108
  "prepublishOnly": "npm run build",
108
109
  "prepare": "husky",
109
110
  "check:config": "node scripts/check-config-drift.js",
110
- "corpus:capture": "npx ts-node scripts/capture-adt-corpus.ts",
111
+ "corpus:capture": "ts-node scripts/capture-adt-corpus.ts",
111
112
  "build:packages": "npm --prefix packages/adt-strategies run build",
112
113
  "test:packages": "npm --prefix packages/adt-strategies test",
113
114
  "release:publish": "bash scripts/publish-changed.sh",
@@ -139,9 +140,15 @@
139
140
  "husky": "^9.1.7",
140
141
  "jest": "^30.0.5",
141
142
  "jest-util": "^30.2.0",
142
- "markdown-it": "^14.3.1",
143
+ "markdown-it": "^14.3.3",
143
144
  "ts-jest": "^29.4.1",
145
+ "ts-node": "^10.9.2",
144
146
  "typescript": "^5.9.2",
145
147
  "yaml": "^2.8.1"
148
+ },
149
+ "allowScripts": {
150
+ "@mcp-abap-adt/sap-rfc-lite": false,
151
+ "@parcel/watcher": false,
152
+ "unrs-resolver": false
146
153
  }
147
154
  }