Skip to content

feat(adt-contracts): implement RAP contracts for behavior definitions, DDLS, and generator#92

Closed
kilo-code-bot[bot] wants to merge 1 commit intomainfrom
gt/toast/7cba11a0
Closed

feat(adt-contracts): implement RAP contracts for behavior definitions, DDLS, and generator#92
kilo-code-bot[bot] wants to merge 1 commit intomainfrom
gt/toast/7cba11a0

Conversation

@kilo-code-bot
Copy link
Copy Markdown

@kilo-code-bot kilo-code-bot bot commented Apr 4, 2026

Summary

  • Implement RAP contracts for Behavior Definitions (BDEF), CDS View/Entity (DDLS), and RAP Generator workspace
  • Add comprehensive contract definition tests (26 tests passing)

Changes

  • packages/adt-contracts/src/adt/rap/ - New RAP contracts directory
    • behavdeft.ts - Behavior Definition contract for /sap/bc/adt/rap/behavdeft
    • ddls.ts - CDS View/Entity contract for /sap/bc/adt/ddl/ddls
    • generator.ts - RAP Generator workspace contract for /sap/bc/adt/rap/generator
    • index.ts - Module exports
  • packages/adt-contracts/src/adt/index.ts - Updated to export RAP contracts
  • packages/adt-contracts/tests/adt/rap/rap.test.ts - Contract tests

RAP Contracts Features

  • Full CRUD operations (get, post, put, delete)
  • Lock/unlock operations for editing
  • Source code access (get/put)
  • Object structure operations

Open with Devin

…, DDLS, and generator

- Add Behavior Definition (BDEF) contract for /sap/bc/adt/rap/behavdeft
- Add CDS View/Entity (DDLS) contract for /sap/bc/adt/ddl/ddls
- Add RAP Generator workspace contract for /sap/bc/adt/rap/generator
- Export all contracts from adt/index.ts
- Add comprehensive contract tests

Implements RAP contract support for:
- Full CRUD operations (get, post, put, delete)
- Lock/unlock operations for editing
- Source code access (get/put)
- Object structure operations

All 26 contract definition tests pass.
@kilo-code-bot
Copy link
Copy Markdown
Author

kilo-code-bot bot commented Apr 4, 2026

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (4 files)
  • packages/adt-contracts/src/adt/rap/behavdeft.ts - Behavior Definition contract
  • packages/adt-contracts/src/adt/rap/ddls.ts - CDS View/Entity contract
  • packages/adt-contracts/src/adt/rap/generator.ts - RAP Generator workspace contract
  • packages/adt-contracts/src/adt/index.ts - Module exports
  • packages/adt-contracts/tests/adt/rap/rap.test.ts - 26 contract tests

Review Notes:

The implementation adds RAP (RESTful ABAP Programming) contracts covering:

  • Behavior Definitions (BDEF) - /sap/bc/adt/rap/behavdeft
  • CDS Views/Entities (DDLS) - /sap/bc/adt/ddl/ddls
  • RAP Generator - /sap/bc/adt/rap/generator

All contracts follow existing codebase patterns with proper CRUD operations, lock/unlock mechanisms, and source code access. The test coverage is comprehensive with 26 tests passing.

No security vulnerabilities, runtime errors, or logic bugs detected.


Reviewed by minimax-m2.5-20260211 · 163,229 tokens

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 4, 2026

@nx-cloud
Copy link
Copy Markdown
Contributor

nx-cloud bot commented Apr 4, 2026

View your CI Pipeline Execution ↗ for commit f72f9cc

Command Status Duration Result
nx affected -t lint test build e2e-ci --verbose... ✅ Succeeded 24s View ↗

☁️ Nx Cloud last updated this comment at 2026-04-04 23:26:16 UTC

@kilo-code-bot
Copy link
Copy Markdown
Author

kilo-code-bot bot commented Apr 4, 2026

Refinery code review passed. All quality gates pass (26 tests, typecheck, lint, format).

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 3 additional findings in Devin Review.

Open in Devin Review

Comment on lines +1 to +310
/**
* RAP Contracts Integration Tests
*
* These tests verify that the RAP contracts are properly defined.
* All tests run using contract definitions without live system.
*
* Run with: bun test packages/adt-contracts/tests/adt/rap/rap.test.ts
*/

import { describe, it, expect } from 'vitest';
import { adtContract } from '../../../src/adt';

describe('RAP Contracts - Contract Definition Tests', () => {
describe('Behavior Definition (BDEF) Contract', () => {
it('should define GET contract for BDEF', () => {
const contract = adtContract.rap.behavdeft;

const descriptor = contract.get('zcl_test_behav');

expect(descriptor.method).toBe('GET');
expect(descriptor.path).toContain('/sap/bc/adt/rap/behavdeft/');
expect(descriptor.path).toContain('zcl_test_behav');
expect(descriptor.headers?.Accept).toContain(
'application/vnd.sap.adt.rap.behavdeft',
);
});

it('should define POST contract for creating BDEF', () => {
const contract = adtContract.rap.behavdeft;

const descriptor = contract.post();

expect(descriptor.method).toBe('POST');
expect(descriptor.path).toBe('/sap/bc/adt/rap/behavdeft');
expect(descriptor.headers?.['Content-Type']).toContain(
'application/vnd.sap.adt.rap.behavdeft',
);
});

it('should define PUT contract for updating BDEF', () => {
const contract = adtContract.rap.behavdeft;

const descriptor = contract.put('zcl_test_behav', {
corrNr: 'DEVK900001',
lockHandle: 'abc123',
});

expect(descriptor.method).toBe('PUT');
expect(descriptor.path).toContain('zcl_test_behav');
expect(descriptor.query?.corrNr).toBe('DEVK900001');
expect(descriptor.query?.lockHandle).toBe('abc123');
});

it('should define DELETE contract for BDEF', () => {
const contract = adtContract.rap.behavdeft;

const descriptor = contract.delete('zcl_test_behav');

expect(descriptor.method).toBe('DELETE');
expect(descriptor.path).toContain('zcl_test_behav');
});

it('should define lock contract for BDEF', () => {
const contract = adtContract.rap.behavdeft;

const descriptor = contract.lock('zcl_test_behav');

expect(descriptor.method).toBe('POST');
expect(descriptor.path).toContain('zcl_test_behav');
expect(descriptor.query?._action).toBe('LOCK');
});

it('should define unlock contract for BDEF', () => {
const contract = adtContract.rap.behavdeft;

const descriptor = contract.unlock('zcl_test_behav', {
lockHandle: 'abc123',
});

expect(descriptor.method).toBe('POST');
expect(descriptor.path).toContain('zcl_test_behav');
expect(descriptor.query?._action).toBe('UNLOCK');
expect(descriptor.query?.lockHandle).toBe('abc123');
});

it('should define source access contract', () => {
const contract = adtContract.rap.behavdeft;

const sourceDescriptor = contract.source.main.get('zcl_test_behav');

expect(sourceDescriptor.method).toBe('GET');
expect(sourceDescriptor.path).toContain('/sap/bc/adt/rap/behavdeft/');
expect(sourceDescriptor.path).toContain('/source/main');
});

it('should define objectstructure contract for BDEF', () => {
const contract = adtContract.rap.behavdeft;

const structureDescriptor = contract.objectstructure('zcl_test_behav');

expect(structureDescriptor.method).toBe('GET');
expect(structureDescriptor.path).toContain('zcl_test_behav');
expect(structureDescriptor.path).toContain('/objectstructure');
});
});

describe('CDS View/Entity (DDLS) Contract', () => {
it('should define GET contract for DDLS', () => {
const contract = adtContract.rap.ddls;

const descriptor = contract.get('zcds_view');

expect(descriptor.method).toBe('GET');
expect(descriptor.path).toContain('/sap/bc/adt/ddl/ddls/');
expect(descriptor.path).toContain('zcds_view');
expect(descriptor.headers?.Accept).toContain(
'application/vnd.sap.adt.ddl.ddlsource',
);
});

it('should define POST contract for DDLS', () => {
const contract = adtContract.rap.ddls;

const createDescriptor = contract.post();

expect(createDescriptor.method).toBe('POST');
expect(createDescriptor.path).toBe('/sap/bc/adt/ddl/ddls');
expect(createDescriptor.headers?.['Content-Type']).toContain(
'application/vnd.sap.adt.ddl.ddlsource',
);
});

it('should define PUT contract for DDLS', () => {
const contract = adtContract.rap.ddls;

const descriptor = contract.put('zcds_view', {
corrNr: 'DEVK900001',
lockHandle: 'abc123',
});

expect(descriptor.method).toBe('PUT');
expect(descriptor.path).toContain('zcds_view');
expect(descriptor.query?.corrNr).toBe('DEVK900001');
expect(descriptor.query?.lockHandle).toBe('abc123');
});

it('should define DELETE contract for DDLS', () => {
const contract = adtContract.rap.ddls;

const descriptor = contract.delete('zcds_view');

expect(descriptor.method).toBe('DELETE');
expect(descriptor.path).toContain('zcds_view');
});

it('should define lock contract for DDLS', () => {
const contract = adtContract.rap.ddls;

const descriptor = contract.lock('zcds_view', {
corrNr: 'DEVK900001',
});

expect(descriptor.method).toBe('POST');
expect(descriptor.path).toContain('zcds_view');
expect(descriptor.query?._action).toBe('LOCK');
});

it('should define source access for DDLS', () => {
const contract = adtContract.rap.ddls;

const sourceDescriptor = contract.source.main.get('zcds_view');

expect(sourceDescriptor.method).toBe('GET');
expect(sourceDescriptor.path).toContain('/sap/bc/adt/ddl/ddls/');
expect(sourceDescriptor.path).toContain('/source/main');
});
});

describe('RAP Generator Workspace Contract', () => {
it('should define list contract', () => {
const contract = adtContract.rap.generator;

const descriptor = contract.list();

expect(descriptor.method).toBe('GET');
expect(descriptor.path).toBe('/sap/bc/adt/rap/generator');
expect(descriptor.headers?.Accept).toContain(
'application/vnd.sap.adt.rap.generator',
);
});

it('should define get contract', () => {
const contract = adtContract.rap.generator;

const descriptor = contract.get('zrap_workspace');

expect(descriptor.method).toBe('GET');
expect(descriptor.path).toContain('/sap/bc/adt/rap/generator/');
expect(descriptor.path).toContain('zrap_workspace');
});

it('should define create contract', () => {
const contract = adtContract.rap.generator;

const descriptor = contract.create({ corrNr: 'DEVK900001' });

expect(descriptor.method).toBe('POST');
expect(descriptor.path).toBe('/sap/bc/adt/rap/generator');
expect(descriptor.query?.corrNr).toBe('DEVK900001');
});

it('should define update contract', () => {
const contract = adtContract.rap.generator;

const descriptor = contract.update('zrap_workspace', {
corrNr: 'DEVK900001',
lockHandle: 'abc123',
});

expect(descriptor.method).toBe('PUT');
expect(descriptor.path).toContain('zrap_workspace');
expect(descriptor.query?.corrNr).toBe('DEVK900001');
expect(descriptor.query?.lockHandle).toBe('abc123');
});

it('should define delete contract', () => {
const contract = adtContract.rap.generator;

const descriptor = contract.delete('zrap_workspace');

expect(descriptor.method).toBe('DELETE');
expect(descriptor.path).toContain('zrap_workspace');
});

it('should define lock contract', () => {
const contract = adtContract.rap.generator;

const descriptor = contract.lock('zrap_workspace', {
corrNr: 'DEVK900001',
});

expect(descriptor.method).toBe('POST');
expect(descriptor.path).toContain('zrap_workspace');
expect(descriptor.query?._action).toBe('LOCK');
expect(descriptor.query?.accessMode).toBe('MODIFY');
});

it('should define unlock contract', () => {
const contract = adtContract.rap.generator;

const descriptor = contract.unlock('zrap_workspace', 'lock-handle-123');

expect(descriptor.method).toBe('POST');
expect(descriptor.path).toContain('zrap_workspace');
expect(descriptor.query?._action).toBe('UNLOCK');
expect(descriptor.query?.lockHandle).toBe('lock-handle-123');
});

it('should define getSource contract', () => {
const contract = adtContract.rap.generator;

const descriptor = contract.getSource('zrap_workspace');

expect(descriptor.method).toBe('GET');
expect(descriptor.path).toContain('/source/main');
expect(descriptor.headers?.Accept).toContain('text/plain');
});

it('should define putSource contract', () => {
const contract = adtContract.rap.generator;

const descriptor = contract.putSource('zrap_workspace', {
lockHandle: 'abc123',
});

expect(descriptor.method).toBe('PUT');
expect(descriptor.path).toContain('/source/main');
expect(descriptor.headers?.['Content-Type']).toContain('text/plain');
expect(descriptor.query?.lockHandle).toBe('abc123');
});
});

describe('RAP Contract Types', () => {
it('should export BehavdeftContract type', () => {
const contract = adtContract.rap.behavdeft;
expect(contract).toBeDefined();
expect(typeof contract.get).toBe('function');
expect(typeof contract.post).toBe('function');
expect(typeof contract.put).toBe('function');
expect(typeof contract.delete).toBe('function');
});

it('should export DdlsContract type', () => {
const contract = adtContract.rap.ddls;
expect(contract).toBeDefined();
expect(typeof contract.get).toBe('function');
expect(typeof contract.post).toBe('function');
expect(typeof contract.put).toBe('function');
expect(typeof contract.delete).toBe('function');
});

it('should export GeneratorContract type', () => {
const contract = adtContract.rap.generator;
expect(contract).toBeDefined();
expect(typeof contract.list).toBe('function');
expect(typeof contract.get).toBe('function');
expect(typeof contract.create).toBe('function');
});
});
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Test file violates AGENTS.md convention: wrong location and missing ContractScenario/runScenario pattern

The packages/adt-contracts/AGENTS.md explicitly requires new contract tests to follow a specific structure:

  1. Create scenario in tests/contracts/{area}.ts
  2. Register in tests/contracts/index.ts

The RAP tests are placed in tests/adt/rap/rap.test.ts instead of tests/contracts/rap.test.ts, and use ad-hoc describe/it blocks instead of the established ContractScenario/runScenario pattern used by every other contract test file (packages/adt-contracts/tests/contracts/oo.test.ts, packages/adt-contracts/tests/contracts/cts.test.ts, packages/adt-contracts/tests/contracts/system.test.ts, etc.). The ContractScenario base class at packages/adt-contracts/tests/contracts/base/index.ts provides standardized validation of method, path, headers, query, body schema, response schema, and fixture round-trips — none of which is leveraged by the new tests.

Prompt for agents
The test file at packages/adt-contracts/tests/adt/rap/rap.test.ts violates the contract testing convention documented in packages/adt-contracts/AGENTS.md. All contract tests must:

1. Be placed in tests/contracts/{area}.test.ts (e.g., tests/contracts/rap.test.ts)
2. Use the ContractScenario class and runScenario() function from tests/contracts/base/
3. Define operations as ContractOperation[] arrays with method, path, headers, query, body, and response fields

See tests/contracts/oo.test.ts or tests/contracts/system.test.ts for examples. The test should define scenario classes like BehavdeftScenario, DdlsScenario, and GeneratorScenario, each extending ContractScenario with the appropriate ContractOperation[] definitions, and then call runScenario() for each. Delete the tests/adt/rap/ directory entirely.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@kilo-code-bot
Copy link
Copy Markdown
Author

kilo-code-bot bot commented Apr 4, 2026

Duplicate of PR #93. Closing in favor of the other implementation.

@kilo-code-bot kilo-code-bot bot closed this Apr 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants