diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..538caf1 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,16 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/setup-node@v4 + - uses: actions/checkout@v4 + - run: npm i + - run: npm run test diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..5fde7ae --- /dev/null +++ b/jest.config.js @@ -0,0 +1,6 @@ +const config = { + testTimeout: 42222, + testMatch: ['**/*.test.js'] + } + +module.exports = config diff --git a/package.json b/package.json index 2860664..f16206d 100644 --- a/package.json +++ b/package.json @@ -13,15 +13,17 @@ "LICENSES" ], "scripts": { - "lint": "npx eslint ." + "lint": "npx eslint .", + "test": "npx jest" }, "devDependencies": { - "eslint": "^8" + "eslint": "^8", + "jest": "^29.7.0" }, "peerDependencies": { - "@sap/cds": "7.9.4", - "@sap/cds-compiler" : "5.0.6", "@cap-js/asyncapi": "^1.0.0", - "@cap-js/openapi": "^1.0.2" + "@cap-js/openapi": "^1.0.2", + "@sap/cds": "7.9.4", + "@sap/cds-compiler": "5.0.6" } } diff --git a/tests/bookshop/.gitignore b/tests/bookshop/.gitignore new file mode 100644 index 0000000..eb69605 --- /dev/null +++ b/tests/bookshop/.gitignore @@ -0,0 +1,34 @@ +# CAP bookshop +_out +*.db +*.sqlite +connection.properties +default-*.json +.cdsrc-private.json +gen/ +node_modules/ +target/ + +# Web IDE, App Studio +.che/ +.gen/ + +# MTA +*_mta_build_tmp +*.mtar +mta_archives/ + +# Other +.DS_Store +*.orig +*.log + +*.iml +*.flattened-pom.xml + +# IDEs +# .vscode +# .idea + +# @cap-js/cds-typer +@cds-models diff --git a/tests/bookshop/.vscode/extensions.json b/tests/bookshop/.vscode/extensions.json new file mode 100644 index 0000000..d558687 --- /dev/null +++ b/tests/bookshop/.vscode/extensions.json @@ -0,0 +1,18 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "SAPSE.vscode-cds", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "mechatroner.rainbow-csv", + "qwtel.sqlite-viewer", + "humao.rest-client" + ], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [ + + ] +} diff --git a/tests/bookshop/.vscode/launch.json b/tests/bookshop/.vscode/launch.json new file mode 100644 index 0000000..188a19c --- /dev/null +++ b/tests/bookshop/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "cds serve", + "request": "launch", + "type": "node", + "cwd": "${workspaceFolder}", + "runtimeExecutable": "cds", + "args": [ + "serve", + "--with-mocks", + "--in-memory?" + ], + "skipFiles": [ + "/**" + ] + } + ] +} diff --git a/tests/bookshop/.vscode/settings.json b/tests/bookshop/.vscode/settings.json new file mode 100644 index 0000000..aa9de54 --- /dev/null +++ b/tests/bookshop/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + // uncomment entries once all libraries have been installed via 'npm install' + "eslint.validate": [ + // "cds", + // "csn", + // "csv", + // "csv (semicolon)", + // "tab", + // "tsv" + ] +} \ No newline at end of file diff --git a/tests/bookshop/.vscode/tasks.json b/tests/bookshop/.vscode/tasks.json new file mode 100644 index 0000000..68697ef --- /dev/null +++ b/tests/bookshop/.vscode/tasks.json @@ -0,0 +1,25 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "type": "shell", + "label": "cds watch", + "command": "cds", + "args": ["watch"], + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": [] + }, + { + "type": "shell", + "label": "cds serve", + "command": "cds", + "args": ["serve", "--with-mocks", "--in-memory?"], + "problemMatcher": [] + } + ] +} diff --git a/tests/bookshop/README.md b/tests/bookshop/README.md new file mode 100644 index 0000000..dbac29e --- /dev/null +++ b/tests/bookshop/README.md @@ -0,0 +1,25 @@ +# Getting Started + +Welcome to your new project. + +It contains these folders and files, following our recommended project layout: + +File or Folder | Purpose +---------|---------- +`app/` | content for UI frontends goes here +`db/` | your domain models and data go here +`srv/` | your service models and code go here +`package.json` | project metadata and configuration +`readme.md` | this getting started guide + + +## Next Steps + +- Open a new terminal and run `cds watch` +- (in VS Code simply choose _**Terminal** > Run Task > cds watch_) +- Start adding content, for example, a [db/schema.cds](db/schema.cds). + + +## Learn More + +Learn more at https://cap.cloud.sap/docs/get-started/. diff --git a/tests/bookshop/db/schema.cds b/tests/bookshop/db/schema.cds new file mode 100644 index 0000000..938fe44 --- /dev/null +++ b/tests/bookshop/db/schema.cds @@ -0,0 +1,26 @@ +using { Currency, managed, sap } from '@sap/cds/common'; +namespace sap.capire.bookshop; + +entity Books : managed { + key ID : Integer; + title : localized String(111); + descr : localized String(1111); + author : Association to Authors; + genre : Association to Genres; + stock : Integer; + price : Decimal(9,2); + currency : Currency; +} + +entity Authors : managed { + key ID : Integer; + name : String(111); + books : Association to many Books on books.author = $self; +} + +/** Hierarchically organized Code List for Genres */ +entity Genres : sap.common.CodeList { + key ID : Integer; + parent : Association to Genres; + children : Composition of many Genres on children.parent = $self; +} diff --git a/tests/bookshop/eslint.config.mjs b/tests/bookshop/eslint.config.mjs new file mode 100644 index 0000000..2fdb432 --- /dev/null +++ b/tests/bookshop/eslint.config.mjs @@ -0,0 +1,2 @@ +import cds from '@sap/cds/eslint.config.mjs' +export default [ ...cds.recommended ] diff --git a/tests/bookshop/package.json b/tests/bookshop/package.json new file mode 100644 index 0000000..e25a558 --- /dev/null +++ b/tests/bookshop/package.json @@ -0,0 +1,19 @@ +{ + "name": "bookshop", + "version": "1.0.0", + "description": "A simple CAP project.", + "repository": "", + "license": "UNLICENSED", + "private": true, + "dependencies": { + "@sap/cds": "^8", + "express": "^4" + }, + "devDependencies": { + "@cap-js/sqlite": "^1", + "@cap-js/cds-types": "^0.6" + }, + "scripts": { + "start": "cds-serve" + } +} diff --git a/tests/bookshop/srv/admin-service.cds b/tests/bookshop/srv/admin-service.cds new file mode 100644 index 0000000..b787951 --- /dev/null +++ b/tests/bookshop/srv/admin-service.cds @@ -0,0 +1,5 @@ +using { sap.capire.bookshop as my } from '../db/schema'; +service AdminService @(requires:'authenticated-user') { + entity Books as projection on my.Books; + entity Authors as projection on my.Authors; +} diff --git a/tests/bookshop/srv/cat-service.cds b/tests/bookshop/srv/cat-service.cds new file mode 100644 index 0000000..342b330 --- /dev/null +++ b/tests/bookshop/srv/cat-service.cds @@ -0,0 +1,10 @@ +using { sap.capire.bookshop as my } from '../db/schema'; +service CatalogService @(path:'/browse') { + + @readonly entity Books as select from my.Books {*, + author.name as author + } excluding { createdBy, modifiedBy }; + + @requires: 'authenticated-user' + action submitOrder (book: Books:ID, quantity: Integer); +} diff --git a/tests/ord.test.js b/tests/ord.test.js new file mode 100644 index 0000000..de70cee --- /dev/null +++ b/tests/ord.test.js @@ -0,0 +1,137 @@ +const cds = require("@sap/cds"); +const ord = require("../lib/ord"); +const path = require("path"); + +describe("Tests for default ORD document", () => { + let csn; + + beforeAll(async () => { + csn = await cds.load(path.join(__dirname, "bookshop", "srv")); + }); + + test("Successfully create ORD Documents with defaults", () => { + const document = ord(csn); + expect(document).toStrictEqual({ + "$schema": "https://sap.github.io/open-resource-discovery/spec-v1/interfaces/Document.schema.json", + "openResourceDiscovery": "1.9", + "policyLevel": "none", + "description": "this is an application description", + "products": [ + { + "ordId": "customer:product:cap.js.ord:", + "title": "cap js ord", + "shortDescription": "Description for cap js ord", + "vendor": "customer:vendor:customer:" + } + ], + "groups": [ + { + "groupId": "sap.cds:service:capjs.ord:undefined.AdminService", + "groupTypeId": "sap.cds:service", + "title": "Admin Service Title" + }, + { + "groupId": "sap.cds:service:capjs.ord:undefined.CatalogService", + "groupTypeId": "sap.cds:service", + "title": "Catalog Service Title" + } + ], + "apiResources": [ + { + "ordId": "capjs.ord:apiResource:undefined.AdminService:v1", + "title": "The service is for AdminService", + "shortDescription": "Here we have the shortDescription for AdminService", + "description": "Here we have the description for AdminService", + "version": "1.0.0", + "visibility": "public", + "partOfGroups": [ + "sap.cds:service:capjs.ord:undefined.AdminService" + ], + "partOfPackage": undefined, + "releaseStatus": "active", + "apiProtocol": "odata-v4", + "resourceDefinitions": [ + { + "type": "openapi-v3", + "mediaType": "application/json", + "url": "/.well-known/open-resource-discovery/v1/api-metadata/AdminService.oas3.json", + "accessStrategies": [ + { + "type": "open" + } + ] + }, + { + "type": "edmx", + "mediaType": "application/xml", + "url": "/.well-known/open-resource-discovery/v1/api-metadata/AdminService.edmx", + "accessStrategies": [ + { + "type": "open" + } + ] + } + ], + "entryPoints": [ + "/odata/v4/admin" + ], + "extensible": { + "supported": "no" + }, + "entityTypeMappings": [ + { + "entityTypeTargets": [] + } + ] + }, + { + "ordId": "capjs.ord:apiResource:undefined.CatalogService:v1", + "title": "The service is for CatalogService", + "shortDescription": "Here we have the shortDescription for CatalogService", + "description": "Here we have the description for CatalogService", + "version": "1.0.0", + "visibility": "public", + "partOfGroups": [ + "sap.cds:service:capjs.ord:undefined.CatalogService" + ], + "partOfPackage": undefined, + "releaseStatus": "active", + "apiProtocol": "odata-v4", + "resourceDefinitions": [ + { + "type": "openapi-v3", + "mediaType": "application/json", + "url": "/.well-known/open-resource-discovery/v1/api-metadata/CatalogService.oas3.json", + "accessStrategies": [ + { + "type": "open" + } + ] + }, + { + "type": "edmx", + "mediaType": "application/xml", + "url": "/.well-known/open-resource-discovery/v1/api-metadata/CatalogService.edmx", + "accessStrategies": [ + { + "type": "open" + } + ] + } + ], + "entryPoints": [ + "/browse" + ], + "extensible": { + "supported": "no" + }, + "entityTypeMappings": [ + { + "entityTypeTargets": [] + } + ] + } + ] + }); + }); +});