@mcp-abap-adt/adt-clients 37.0.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.
- package/README.md +56 -4
- package/dist/core/class/index.d.ts +1 -1
- package/dist/core/class/index.d.ts.map +1 -1
- package/dist/core/class/index.js +2 -1
- package/dist/core/class/run.d.ts +11 -0
- package/dist/core/class/run.d.ts.map +1 -1
- package/dist/core/class/run.js +18 -0
- package/dist/core/shared/abapUnit.d.ts +46 -0
- package/dist/core/shared/abapUnit.d.ts.map +1 -1
- package/dist/core/shared/abapUnit.js +98 -0
- package/dist/executors/abapUnitRunner.d.ts +9 -0
- package/dist/executors/abapUnitRunner.d.ts.map +1 -1
- package/dist/executors/abapUnitRunner.js +14 -0
- package/dist/executors/class/ClassTestRunner.d.ts +27 -1
- package/dist/executors/class/ClassTestRunner.d.ts.map +1 -1
- package/dist/executors/class/ClassTestRunner.js +31 -0
- package/dist/executors/class/ClassTestRunnerLegacy.d.ts +6 -0
- package/dist/executors/class/ClassTestRunnerLegacy.d.ts.map +1 -1
- package/dist/executors/class/ClassTestRunnerLegacy.js +12 -5
- package/dist/executors/functionGroup/FunctionGroupTestRunner.d.ts +25 -1
- package/dist/executors/functionGroup/FunctionGroupTestRunner.d.ts.map +1 -1
- package/dist/executors/functionGroup/FunctionGroupTestRunner.js +30 -1
- package/dist/executors/functionModule/FunctionModuleTestRunner.d.ts +47 -2
- package/dist/executors/functionModule/FunctionModuleTestRunner.d.ts.map +1 -1
- package/dist/executors/functionModule/FunctionModuleTestRunner.js +48 -1
- package/dist/executors/functionModule/index.d.ts +1 -1
- package/dist/executors/functionModule/index.d.ts.map +1 -1
- package/dist/executors/index.d.ts +1 -1
- package/dist/executors/index.d.ts.map +1 -1
- package/dist/executors/program/ProgramTestRunner.d.ts +30 -3
- package/dist/executors/program/ProgramTestRunner.d.ts.map +1 -1
- package/dist/executors/program/ProgramTestRunner.js +33 -3
- package/dist/executors/program/ProgramTestRunnerLegacy.d.ts +7 -4
- package/dist/executors/program/ProgramTestRunnerLegacy.d.ts.map +1 -1
- package/dist/executors/program/ProgramTestRunnerLegacy.js +9 -4
- package/dist/index.executors.d.ts +1 -1
- package/dist/index.executors.d.ts.map +1 -1
- package/docs/usage/OBJECT_LIFECYCLE.md +2 -2
- package/package.json +25 -18
- package/dist/core/class/runLegacy.d.ts +0 -42
- package/dist/core/class/runLegacy.d.ts.map +0 -1
- package/dist/core/class/runLegacy.js +0 -74
package/README.md
CHANGED
|
@@ -157,9 +157,9 @@ npm install @mcp-abap-adt/adt-clients
|
|
|
157
157
|
- Typed execution API based on `IExecutor`
|
|
158
158
|
- Executors:
|
|
159
159
|
- `getClassExecutor()` for `classrun`
|
|
160
|
-
- `getClassTestRunner()` for a class's ABAP Unit tests: `run`, `getStatus`, `getResult`
|
|
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
|
|
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 — `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
|
|
@@ -440,13 +440,65 @@ const result = await runner.getResult(runId, { analyse: analyseUnitTest });
|
|
|
440
440
|
`{ containerClass, testClass }`. On a legacy system the runner's `run` answers
|
|
441
441
|
the finished result, and `getStatus`/`getResult` refuse without a request.
|
|
442
442
|
|
|
443
|
+
**The synchronous runner, `runSync`.** `run` starts a run on
|
|
444
|
+
`/sap/bc/adt/abapunit/runs`, which is then polled; that stays the default.
|
|
445
|
+
`runSync` is the other runner ADT has — one `POST /sap/bc/adt/abapunit/testruns`
|
|
446
|
+
answering the finished `aunit:runResult` — chosen explicitly by the caller.
|
|
447
|
+
Some systems have only this one (an on-prem S/4HANA 2023, SAP_BASIS 758, was
|
|
448
|
+
measured without `/abapunit/runs`); whether a system has `/runs` is in its
|
|
449
|
+
discovery, and reading that is the caller's — the library picks no runner by
|
|
450
|
+
release or by discovery.
|
|
451
|
+
|
|
452
|
+
```typescript
|
|
453
|
+
const result = await runner.runSync('ZCL_UNDER_TEST', { analyse: analyseUnitTest });
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
Its answer is read by the runner's `result` strategy, the one `getResult` uses:
|
|
457
|
+
on the measured systems (on premise and ABAP Cloud, 2026-10-22) both runners
|
|
458
|
+
answer the same document — `aunit:runResult` in `http://www.sap.com/adt/aunit`
|
|
459
|
+
— with the same methods and alerts. Two differences: the endpoint addresses
|
|
460
|
+
whole classes, so `{ containerClass, testClass }` targets run each distinct
|
|
461
|
+
container whole; and `title` and `context` are not sent. Scope, risk levels and
|
|
462
|
+
durations are, with `run`'s defaults. On a legacy system `runSync` is the
|
|
463
|
+
request `run` already sends there, read by `result`.
|
|
464
|
+
|
|
443
465
|
A report's tests are local classes in its source or in an include it pulls in —
|
|
444
466
|
written through `getProgram().update()` or `getInclude().update()` — and run
|
|
445
467
|
through `executor.getProgramTestRunner().run(programName)`, with the same
|
|
446
468
|
`getStatus`/`getResult`. A function group's are written in an include of the
|
|
447
469
|
group (`getFunctionInclude()`) and run through `getFunctionGroupTestRunner()`
|
|
448
470
|
for the whole group or `getFunctionModuleTestRunner()` for one module. Below
|
|
449
|
-
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.
|
|
450
502
|
|
|
451
503
|
**AdtUtils read type safety:**
|
|
452
504
|
`readObjectMetadata` and `readObjectSource` accept strict object type unions to prevent invalid inputs like `view:ZOBJ`.
|
|
@@ -6,6 +6,6 @@ export { AdtLocalDefinitions, type ILocalDefinitionsConfig, } from './AdtLocalDe
|
|
|
6
6
|
export { AdtLocalMacros, type ILocalMacrosConfig } from './AdtLocalMacros';
|
|
7
7
|
export { AdtLocalTestClass, type ILocalTestClassConfig, } from './AdtLocalTestClass';
|
|
8
8
|
export { AdtLocalTypes, type ILocalTypesConfig } from './AdtLocalTypes';
|
|
9
|
-
export { getClassUnitTestResult, getClassUnitTestStatus, IClassUnitTestDefinition, IClassUnitTestRunOptions, startClassUnitTestRun, startClassUnitTestRunByObject, } from './run';
|
|
9
|
+
export { getClassUnitTestResult, getClassUnitTestStatus, IClassUnitTestDefinition, IClassUnitTestRunOptions, startClassUnitTestRun, startClassUnitTestRunByObject, startClassUnitTestRunSync, } from './run';
|
|
10
10
|
export * from './types';
|
|
11
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/class/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EACL,mBAAmB,EACnB,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EACL,iBAAiB,EACjB,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,qBAAqB,EACrB,6BAA6B,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/class/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EACL,mBAAmB,EACnB,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EACL,iBAAiB,EACjB,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,qBAAqB,EACrB,6BAA6B,EAC7B,yBAAyB,GAC1B,MAAM,OAAO,CAAC;AACf,cAAc,SAAS,CAAC"}
|
package/dist/core/class/index.js
CHANGED
|
@@ -17,7 +17,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
17
17
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.startClassUnitTestRunByObject = exports.startClassUnitTestRun = exports.getClassUnitTestStatus = exports.getClassUnitTestResult = exports.AdtLocalTypes = exports.AdtLocalTestClass = exports.AdtLocalMacros = exports.AdtLocalDefinitions = exports.AdtClass = void 0;
|
|
20
|
+
exports.startClassUnitTestRunSync = exports.startClassUnitTestRunByObject = exports.startClassUnitTestRun = exports.getClassUnitTestStatus = exports.getClassUnitTestResult = exports.AdtLocalTypes = exports.AdtLocalTestClass = exports.AdtLocalMacros = exports.AdtLocalDefinitions = exports.AdtClass = void 0;
|
|
21
21
|
var AdtClass_1 = require("./AdtClass");
|
|
22
22
|
Object.defineProperty(exports, "AdtClass", { enumerable: true, get: function () { return AdtClass_1.AdtClass; } });
|
|
23
23
|
var AdtLocalDefinitions_1 = require("./AdtLocalDefinitions");
|
|
@@ -33,4 +33,5 @@ Object.defineProperty(exports, "getClassUnitTestResult", { enumerable: true, get
|
|
|
33
33
|
Object.defineProperty(exports, "getClassUnitTestStatus", { enumerable: true, get: function () { return run_1.getClassUnitTestStatus; } });
|
|
34
34
|
Object.defineProperty(exports, "startClassUnitTestRun", { enumerable: true, get: function () { return run_1.startClassUnitTestRun; } });
|
|
35
35
|
Object.defineProperty(exports, "startClassUnitTestRunByObject", { enumerable: true, get: function () { return run_1.startClassUnitTestRunByObject; } });
|
|
36
|
+
Object.defineProperty(exports, "startClassUnitTestRunSync", { enumerable: true, get: function () { return run_1.startClassUnitTestRunSync; } });
|
|
36
37
|
__exportStar(require("./types"), exports);
|
package/dist/core/class/run.d.ts
CHANGED
|
@@ -61,4 +61,15 @@ export declare const getClassUnitTestResult: typeof getUnitTestRunResult;
|
|
|
61
61
|
* container runs without the caller naming one.
|
|
62
62
|
*/
|
|
63
63
|
export declare function startClassUnitTestRunByObject(connection: IAbapConnection, className: string, options?: IClassUnitTestRunOptions): Promise<IAdtWireResponse>;
|
|
64
|
+
/**
|
|
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. The
|
|
67
|
+
* request is `startUnitTestRunSync` (`core/shared/abapUnit`), given each
|
|
68
|
+
* class's URI; see there for the format and what was measured.
|
|
69
|
+
*
|
|
70
|
+
* The regular runner's `runSync` and the legacy runner's `run` both send it.
|
|
71
|
+
* `options` absent sends no `<options>` element — the body the legacy runner
|
|
72
|
+
* has always sent, unchanged.
|
|
73
|
+
*/
|
|
74
|
+
export declare function startClassUnitTestRunSync(connection: IAbapConnection, classNames: string[], options?: IClassUnitTestRunOptions): Promise<IAdtWireResponse>;
|
|
64
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;
|
|
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"}
|
package/dist/core/class/run.js
CHANGED
|
@@ -7,6 +7,8 @@ exports.getClassUnitTestResult = exports.getClassUnitTestStatus = void 0;
|
|
|
7
7
|
exports.runClass = runClass;
|
|
8
8
|
exports.startClassUnitTestRun = startClassUnitTestRun;
|
|
9
9
|
exports.startClassUnitTestRunByObject = startClassUnitTestRunByObject;
|
|
10
|
+
exports.startClassUnitTestRunSync = startClassUnitTestRunSync;
|
|
11
|
+
const objects_1 = require("../../endpoints/objects");
|
|
10
12
|
const passport_1 = require("../../runtime/debugger/passport");
|
|
11
13
|
const xml_1 = require("../../utils/xml");
|
|
12
14
|
/**
|
|
@@ -126,3 +128,19 @@ exports.getClassUnitTestResult = abapUnit_1.getUnitTestRunResult;
|
|
|
126
128
|
async function startClassUnitTestRunByObject(connection, className, options) {
|
|
127
129
|
return (0, abapUnit_1.startUnitTestRunByObject)(connection, { name: className, type: 'CLAS' }, options);
|
|
128
130
|
}
|
|
131
|
+
// =============================================================================
|
|
132
|
+
// The synchronous runner: /abapunit/testruns
|
|
133
|
+
// =============================================================================
|
|
134
|
+
/**
|
|
135
|
+
* Run the ABAP Unit tests of whole classes and answer the finished result —
|
|
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.
|
|
139
|
+
*
|
|
140
|
+
* The regular runner's `runSync` and the legacy runner's `run` both send it.
|
|
141
|
+
* `options` absent sends no `<options>` element — the body the legacy runner
|
|
142
|
+
* has always sent, unchanged.
|
|
143
|
+
*/
|
|
144
|
+
async function startClassUnitTestRunSync(connection, classNames, options) {
|
|
145
|
+
return (0, abapUnit_1.startUnitTestRunSync)(connection, classNames.map((name) => objects_1.CLASS.uri(name)), options);
|
|
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;
|
|
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.
|
|
@@ -27,7 +27,12 @@ import { AbapUnitRunner, type IAbapUnitRunnerResults } from '../abapUnitRunner';
|
|
|
27
27
|
* whose every test class runs.
|
|
28
28
|
*/
|
|
29
29
|
export type IClassTestRunTarget = IClassUnitTestDefinition[] | string;
|
|
30
|
-
/**
|
|
30
|
+
/** The distinct containers a target names: what `/testruns` addresses. */
|
|
31
|
+
export declare function containersOf(target: IClassTestRunTarget): string[];
|
|
32
|
+
/**
|
|
33
|
+
* One strategy per distinct answer: starting a run, polling it, its result.
|
|
34
|
+
* `runSync` answers the result document itself, so it is read by `result`.
|
|
35
|
+
*/
|
|
31
36
|
export type IClassTestRunnerResults = IAbapUnitRunnerResults;
|
|
32
37
|
/** The shipped default: documents as they arrived. */
|
|
33
38
|
export declare const classTestRunnerDocuments: {
|
|
@@ -49,5 +54,26 @@ export declare class ClassTestRunner<R extends IClassTestRunnerResults = typeof
|
|
|
49
54
|
* read as a failure.
|
|
50
55
|
*/
|
|
51
56
|
run<E extends IAdtError = IAdtError>(target: IClassTestRunTarget, options?: IClassUnitTestRunOptions & IAdtAnalyseOptions<E>): Promise<IAdtResponse<ReturnType<R['run']>, E>>;
|
|
57
|
+
/**
|
|
58
|
+
* Run the tests and answer the finished result. One POST, to
|
|
59
|
+
* `/sap/bc/adt/abapunit/testruns` — the synchronous runner, beside the
|
|
60
|
+
* asynchronous `run` + `getStatus` + `getResult`, which stays the default.
|
|
61
|
+
*
|
|
62
|
+
* An explicit choice of the caller's: nothing here asks the system which
|
|
63
|
+
* runner it has. A system without `/abapunit/runs` (an on-prem S/4HANA 2023
|
|
64
|
+
* was measured with `/testruns` alone) needs this one; whether a system has
|
|
65
|
+
* it is in its discovery, which is the caller's to read.
|
|
66
|
+
*
|
|
67
|
+
* The answer is the `aunit:runResult` document, so it is read by this
|
|
68
|
+
* runner's `result` strategy — the one `getResult` uses — and a failing test
|
|
69
|
+
* is in it as an `alert`; whether that is a failure is `options.analyse`'s
|
|
70
|
+
* (`analyseUnitTest` from @mcp-abap-adt/adt-strategies reads it so).
|
|
71
|
+
*
|
|
72
|
+
* Differences from `run`: the endpoint addresses whole classes, so a target
|
|
73
|
+
* of test definitions runs each distinct container whole, and `title` and
|
|
74
|
+
* `context` are not sent; scope, risk levels and durations are, with the
|
|
75
|
+
* same defaults.
|
|
76
|
+
*/
|
|
77
|
+
runSync<E extends IAdtError = IAdtError>(target: IClassTestRunTarget, options?: IClassUnitTestRunOptions & IAdtAnalyseOptions<E>): Promise<IAdtResponse<ReturnType<R['result']>, E>>;
|
|
52
78
|
}
|
|
53
79
|
//# sourceMappingURL=ClassTestRunner.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClassTestRunner.d.ts","sourceRoot":"","sources":["../../../src/executors/class/ClassTestRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,wBAAwB,EACxB,wBAAwB,EACxB,eAAe,EAChB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"ClassTestRunner.d.ts","sourceRoot":"","sources":["../../../src/executors/class/ClassTestRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,wBAAwB,EACxB,wBAAwB,EACxB,eAAe,EAChB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAM9D,OAAO,EACL,cAAc,EAEd,KAAK,sBAAsB,EAC5B,MAAM,mBAAmB,CAAC;AAE3B;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,wBAAwB,EAAE,GAAG,MAAM,CAAC;AAEtE,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,EAAE,CAIlE;AAED;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,sBAAsB,CAAC;AAE7D,sDAAsD;AACtD,eAAO,MAAM,wBAAwB;;;;CAA0B,CAAC;AAEhE,qBAAa,eAAe,CACxB,CAAC,SAAS,uBAAuB,GAAG,OAAO,wBAAwB,CAErE,SAAQ,cAAc,CAAC,CAAC,CACxB,YACE,YAAY,CACV,mBAAmB,EACnB,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EACpB,wBAAwB,CACzB;gBAGD,UAAU,EAAE,eAAe,EAC3B,MAAM,CAAC,EAAE,OAAO,EAEhB,OAAO,GAAE,CAA4C;IAKvD;;;;;;;;;;OAUG;IACG,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EACvC,MAAM,EAAE,mBAAmB,EAC3B,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;IAWjD;;;;;;;;;;;;;;;;;;;OAmBG;IACG,OAAO,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAC3C,MAAM,EAAE,mBAAmB,EAC3B,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;CAarD"}
|
|
@@ -21,9 +21,16 @@
|
|
|
21
21
|
*/
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
23
|
exports.ClassTestRunner = exports.classTestRunnerDocuments = void 0;
|
|
24
|
+
exports.containersOf = containersOf;
|
|
24
25
|
const run_1 = require("../../core/class/run");
|
|
25
26
|
const adtResponse_1 = require("../../utils/adtResponse");
|
|
26
27
|
const abapUnitRunner_1 = require("../abapUnitRunner");
|
|
28
|
+
/** The distinct containers a target names: what `/testruns` addresses. */
|
|
29
|
+
function containersOf(target) {
|
|
30
|
+
return typeof target === 'string'
|
|
31
|
+
? [target]
|
|
32
|
+
: [...new Set(target.map((test) => test.containerClass))];
|
|
33
|
+
}
|
|
27
34
|
/** The shipped default: documents as they arrived. */
|
|
28
35
|
exports.classTestRunnerDocuments = abapUnitRunner_1.abapUnitRunnerDocuments;
|
|
29
36
|
class ClassTestRunner extends abapUnitRunner_1.AbapUnitRunner {
|
|
@@ -49,5 +56,29 @@ class ClassTestRunner extends abapUnitRunner_1.AbapUnitRunner {
|
|
|
49
56
|
}
|
|
50
57
|
return (0, adtResponse_1.answering)(() => (0, run_1.startClassUnitTestRun)(this.connection, target, options), this.results.run, options?.analyse);
|
|
51
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Run the tests and answer the finished result. One POST, to
|
|
61
|
+
* `/sap/bc/adt/abapunit/testruns` — the synchronous runner, beside the
|
|
62
|
+
* asynchronous `run` + `getStatus` + `getResult`, which stays the default.
|
|
63
|
+
*
|
|
64
|
+
* An explicit choice of the caller's: nothing here asks the system which
|
|
65
|
+
* runner it has. A system without `/abapunit/runs` (an on-prem S/4HANA 2023
|
|
66
|
+
* was measured with `/testruns` alone) needs this one; whether a system has
|
|
67
|
+
* it is in its discovery, which is the caller's to read.
|
|
68
|
+
*
|
|
69
|
+
* The answer is the `aunit:runResult` document, so it is read by this
|
|
70
|
+
* runner's `result` strategy — the one `getResult` uses — and a failing test
|
|
71
|
+
* is in it as an `alert`; whether that is a failure is `options.analyse`'s
|
|
72
|
+
* (`analyseUnitTest` from @mcp-abap-adt/adt-strategies reads it so).
|
|
73
|
+
*
|
|
74
|
+
* Differences from `run`: the endpoint addresses whole classes, so a target
|
|
75
|
+
* of test definitions runs each distinct container whole, and `title` and
|
|
76
|
+
* `context` are not sent; scope, risk levels and durations are, with the
|
|
77
|
+
* same defaults.
|
|
78
|
+
*/
|
|
79
|
+
async runSync(target, options) {
|
|
80
|
+
const { analyse, ...runOptions } = options ?? {};
|
|
81
|
+
return (0, adtResponse_1.answering)(() => (0, run_1.startClassUnitTestRunSync)(this.connection, containersOf(target), runOptions), this.results.result, analyse);
|
|
82
|
+
}
|
|
52
83
|
}
|
|
53
84
|
exports.ClassTestRunner = ClassTestRunner;
|
|
@@ -21,6 +21,12 @@ export declare class ClassTestRunnerLegacy<R extends IClassTestRunnerResults = t
|
|
|
21
21
|
* result document itself, not an id.
|
|
22
22
|
*/
|
|
23
23
|
run<E extends IAdtError = IAdtError>(target: IClassTestRunTarget, options?: IClassUnitTestRunOptions & IAdtAnalyseOptions<E>): Promise<IAdtResponse<ReturnType<R['run']>, E>>;
|
|
24
|
+
/**
|
|
25
|
+
* The same request as `run` — on a legacy system `run` is already the
|
|
26
|
+
* synchronous one — answered through the `result` strategy, as the regular
|
|
27
|
+
* runner's `runSync` is.
|
|
28
|
+
*/
|
|
29
|
+
runSync<E extends IAdtError = IAdtError>(target: IClassTestRunTarget, options?: IClassUnitTestRunOptions & IAdtAnalyseOptions<E>): Promise<IAdtResponse<ReturnType<R['result']>, E>>;
|
|
24
30
|
/**
|
|
25
31
|
* Refused without a request: a legacy system finishes a run before it
|
|
26
32
|
* answers and exposes no run to poll. `run`'s own answer is the result.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClassTestRunnerLegacy.d.ts","sourceRoot":"","sources":["../../../src/executors/class/ClassTestRunnerLegacy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,wBAAwB,EAEzB,MAAM,8BAA8B,CAAC;AAItC,OAAO,EACL,eAAe,EACf,KAAK,wBAAwB,
|
|
1
|
+
{"version":3,"file":"ClassTestRunnerLegacy.d.ts","sourceRoot":"","sources":["../../../src/executors/class/ClassTestRunnerLegacy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,wBAAwB,EAEzB,MAAM,8BAA8B,CAAC;AAItC,OAAO,EACL,eAAe,EACf,KAAK,wBAAwB,EAE7B,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACzB,MAAM,mBAAmB,CAAC;AAE3B,qBAAa,qBAAqB,CAChC,CAAC,SAAS,uBAAuB,GAAG,OAAO,wBAAwB,CACnE,SAAQ,eAAe,CAAC,CAAC,CAAC;IAC1B;;;;;OAKG;IACY,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAChD,MAAM,EAAE,mBAAmB,EAC3B,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;IAUjD;;;;OAIG;IACY,OAAO,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EACpD,MAAM,EAAE,mBAAmB,EAC3B,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;IAQpD;;;OAGG;IACY,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAClE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;IASD,0EAA0E;IAC3D,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,KAAK,OAAO,CAClE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CACzC;CAQF"}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.ClassTestRunnerLegacy = void 0;
|
|
17
17
|
const interfaces_adt_1 = require("@mcp-abap-adt/interfaces-adt");
|
|
18
|
-
const
|
|
18
|
+
const run_1 = require("../../core/class/run");
|
|
19
19
|
const adtResponse_1 = require("../../utils/adtResponse");
|
|
20
20
|
const ClassTestRunner_1 = require("./ClassTestRunner");
|
|
21
21
|
class ClassTestRunnerLegacy extends ClassTestRunner_1.ClassTestRunner {
|
|
@@ -26,10 +26,17 @@ class ClassTestRunnerLegacy extends ClassTestRunner_1.ClassTestRunner {
|
|
|
26
26
|
* result document itself, not an id.
|
|
27
27
|
*/
|
|
28
28
|
async run(target, options) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
// No options: the body a legacy system has always been sent — the
|
|
30
|
+
// `<options>` element `runSync` sends is unmeasured there.
|
|
31
|
+
return (0, adtResponse_1.answering)(() => (0, run_1.startClassUnitTestRunSync)(this.connection, (0, ClassTestRunner_1.containersOf)(target)), this.results.run, options?.analyse);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The same request as `run` — on a legacy system `run` is already the
|
|
35
|
+
* synchronous one — answered through the `result` strategy, as the regular
|
|
36
|
+
* runner's `runSync` is.
|
|
37
|
+
*/
|
|
38
|
+
async runSync(target, options) {
|
|
39
|
+
return (0, adtResponse_1.answering)(() => (0, run_1.startClassUnitTestRunSync)(this.connection, (0, ClassTestRunner_1.containersOf)(target)), this.results.result, options?.analyse);
|
|
33
40
|
}
|
|
34
41
|
/**
|
|
35
42
|
* Refused without a request: a legacy system finishes a run before it
|
|
@@ -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
|
|
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"}
|