Compare commits
22 Commits
refactor/s
...
v7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea79264e9d | ||
|
|
c2d1217e4a | ||
|
|
d739680180 | ||
|
|
326729e03d | ||
|
|
6e56eb9c01 | ||
|
|
1a0d3e60cf | ||
|
|
402a5816e3 | ||
|
|
cdb9ae6436 | ||
|
|
4ba262f02a | ||
|
|
187014d98b | ||
|
|
85f24970de | ||
|
|
a191c4fd50 | ||
|
|
ac3cfa81c7 | ||
|
|
710dd7ac32 | ||
|
|
bbe2bae087 | ||
|
|
ec8608faab | ||
|
|
4c46f115f5 | ||
|
|
c6b88f6b66 | ||
|
|
aaa94e2d5f | ||
|
|
0f6809a45b | ||
|
|
6249fa2270 | ||
|
|
9e02e2c796 |
3
.github/dependabot.yml
vendored
3
.github/dependabot.yml
vendored
@@ -15,3 +15,6 @@ updates:
|
|||||||
- dependency-name: "chai"
|
- dependency-name: "chai"
|
||||||
# chai 5 doesn't work atm w/ cds.test, TODO fix that in cds.test
|
# chai 5 doesn't work atm w/ cds.test, TODO fix that in cds.test
|
||||||
versions: ["5.x"]
|
versions: ["5.x"]
|
||||||
|
- dependency-name: "chai-as-promised"
|
||||||
|
# chai-as-promised 8 doesn't work atm w/ cds.test, TODO fix that in cds.test
|
||||||
|
versions: ["8.x"]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const cds = require('@sap/cds/lib')
|
const cds = require('@sap/cds')
|
||||||
|
|
||||||
module.exports = class AdminService extends cds.ApplicationService { init(){
|
module.exports = class AdminService extends cds.ApplicationService { init(){
|
||||||
this.before ('NEW','Authors', genid)
|
this.before ('NEW','Authors', genid)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
const cds = require('@sap/cds')
|
||||||
module.exports = class CatalogService extends cds.ApplicationService { init() {
|
module.exports = class CatalogService extends cds.ApplicationService { init() {
|
||||||
|
|
||||||
const { Books } = cds.entities('sap.capire.bookshop')
|
const { Books } = cds.entities('sap.capire.bookshop')
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
|
||||||
|
|
||||||
|
<head>
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
@@ -10,21 +10,22 @@
|
|||||||
<script>
|
<script>
|
||||||
window["sap-ushell-config"] = {
|
window["sap-ushell-config"] = {
|
||||||
defaultRenderer: "fiori2",
|
defaultRenderer: "fiori2",
|
||||||
applications: {}
|
applications: {},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script id="sap-ushell-bootstrap" src="https://sapui5.hana.ondemand.com/test-resources/sap/ushell/bootstrap/sandbox.js"></script>
|
<script id="sap-ushell-bootstrap" src="https://ui5.sap.com/test-resources/sap/ushell/bootstrap/sandbox.js"></script>
|
||||||
<script id="sap-ui-bootstrap" src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
|
<script id="sap-ui-bootstrap" src="https://ui5.sap.com/resources/sap-ui-core.js"
|
||||||
data-sap-ui-libs="sap.m, sap.ushell, sap.collaboration, sap.ui.layout"
|
data-sap-ui-libs="sap.m, sap.ushell, sap.collaboration, sap.ui.layout" data-sap-ui-compatVersion="edge"
|
||||||
data-sap-ui-compatVersion="edge"
|
data-sap-ui-theme="sap_horizon"></script>
|
||||||
data-sap-ui-theme="sap_horizon"
|
|
||||||
data-sap-ui-frameOptions="allow"
|
|
||||||
></script>
|
|
||||||
<script>
|
<script>
|
||||||
sap.ui.getCore().attachInit(()=> sap.ushell.Container.createRenderer().placeAt("content"))
|
sap.ui.getCore().attachInit(() =>
|
||||||
|
sap.ushell.Container.createRenderer().placeAt("content")
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="sapUiBody" id="content"></body>
|
|
||||||
|
<body class="sapUiBody" id="content">
|
||||||
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
// install OData v2 adapter
|
|
||||||
const cds = require("@sap/cds")
|
|
||||||
const proxy = require('@cap-js-community/odata-v2-adapter')
|
|
||||||
const opts = global.it ? { target:'auto' } : {} // for tests, set 'auto' to detect port dynamically
|
|
||||||
cds.on('bootstrap', app => app.use(proxy(opts))) // install proxy
|
|
||||||
// cds.log('cov2ap','silent') // suppress anoying log outpout, e.g. for `npm run mocha -- --reporter nyan`
|
|
||||||
|
|
||||||
module.exports = require('@capire/bookstore/server.js')
|
|
||||||
@@ -1,13 +1,10 @@
|
|||||||
const cds = require ('@sap/cds')
|
const cds = require ('@sap/cds')
|
||||||
describe('Hello world!', () => {
|
describe('Hello world!', () => {
|
||||||
|
|
||||||
beforeAll (()=> process.env.CDS_TYPESCRIPT = true)
|
|
||||||
afterAll (()=> delete process.env.CDS_TYPESCRIPT)
|
|
||||||
const {GET} = cds.test.in(__dirname,'../srv').run('serve', 'world.cds')
|
const {GET} = cds.test.in(__dirname,'../srv').run('serve', 'world.cds')
|
||||||
|
|
||||||
it('should say hello with class impl', async () => {
|
it('should say hello with class impl', async () => {
|
||||||
const {data} = await GET`/say/hello(to='world')`
|
const {data} = await GET`/say/hello(to='world')`
|
||||||
expect(data.value).toMatch(/Hello world.*typescript.*/i)
|
expect(data.value).to.match(/Hello world.*typescript.*/i)
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const cds = require ('@sap/cds/lib')
|
const cds = require ('@sap/cds')
|
||||||
const LOG = cds.log('cds.log')
|
const LOG = cds.log('cds.log')
|
||||||
|
|
||||||
module.exports = class LogService extends cds.Service {
|
module.exports = class LogService extends cds.Service {
|
||||||
|
|||||||
6753
package-lock.json
generated
6753
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,8 @@
|
|||||||
|
const cds = require('@sap/cds')
|
||||||
|
const { expect } = cds.test
|
||||||
|
|
||||||
describe('cds.ql → cqn', () => {
|
describe('cds.ql → cqn', () => {
|
||||||
|
|
||||||
const cds = require('@sap/cds/lib')
|
|
||||||
const { expect } = cds.test
|
|
||||||
const Foo = { name: 'Foo' }
|
const Foo = { name: 'Foo' }
|
||||||
const Books = { name: 'capire.bookshop.Books' }
|
const Books = { name: 'capire.bookshop.Books' }
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const cds = require('@sap/cds/lib')
|
const cds = require('@sap/cds')
|
||||||
|
|
||||||
describe('cap/samples - Consuming Services locally', () => {
|
describe('cap/samples - Consuming Services locally', () => {
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const cds = require('@sap/cds/lib')
|
const cds = require('@sap/cds')
|
||||||
|
|
||||||
describe('cap/samples - Custom Handlers', () => {
|
describe('cap/samples - Custom Handlers', () => {
|
||||||
|
|
||||||
@@ -8,9 +8,10 @@ describe('cap/samples - Custom Handlers', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should reject out-of-stock orders', async () => {
|
it('should reject out-of-stock orders', async () => {
|
||||||
await POST `/browse/submitOrder ${{ book: 201, quantity: 5 }}`
|
await expect(POST `/browse/submitOrder ${{ book: 201, quantity: 5 }}`).to.be.fulfilled
|
||||||
await POST `/browse/submitOrder ${{ book: 201, quantity: 5 }}`
|
await expect(POST `/browse/submitOrder ${{ book: 201, quantity: 5 }}`).to.be.fulfilled
|
||||||
await expect(POST `/browse/submitOrder ${{ book: 201, quantity: 5 }}`).to.be.rejectedWith(/409 - 5 exceeds stock for book #201/)
|
await expect(POST `/browse/submitOrder ${{ book: 201, quantity: 5 }}`).to.be.rejectedWith(
|
||||||
|
/409 - 5 exceeds stock for book #201/)
|
||||||
const { data } = await GET`/admin/Books/201/stock/$value`
|
const { data } = await GET`/admin/Books/201/stock/$value`
|
||||||
expect(data).to.equal(2)
|
expect(data).to.equal(2)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
const cds = require('@sap/cds/lib')
|
// Quick hack: suppress deprecation warnings w/ Node22 caused by http-proxy (used by OData v2 proxy)
|
||||||
|
// See also: https://github.com/http-party/node-http-proxy/pull/1666
|
||||||
|
require('util')._extend = Object.assign
|
||||||
|
|
||||||
|
const cds = require('@sap/cds')
|
||||||
|
|
||||||
describe('cap/samples - Fiori APIs - v2', function() {
|
describe('cap/samples - Fiori APIs - v2', function() {
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const cds = require('@sap/cds/lib')
|
const cds = require('@sap/cds')
|
||||||
|
|
||||||
describe('cap/samples - Hello world!', () => {
|
describe('cap/samples - Hello world!', () => {
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const cds = require('@sap/cds/lib')
|
const cds = require('@sap/cds')
|
||||||
const { expect } = cds.test.in(__dirname,'..')
|
const { expect } = cds.test.in(__dirname,'..')
|
||||||
|
|
||||||
describe('cap/samples - Hierarchical Data', ()=>{
|
describe('cap/samples - Hierarchical Data', ()=>{
|
||||||
@@ -77,49 +77,45 @@ describe('cap/samples - Hierarchical Data', ()=>{
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it ('supports nested reads', async()=>{
|
it ('supports nested reads', ()=> expect (
|
||||||
expect (await
|
SELECT.one.from (Cats, c=>{
|
||||||
SELECT.one.from (Cats, c=>{
|
c.ID, c.name.as('parent'), c.children (c=>{
|
||||||
c.ID, c.name.as('parent'), c.children (c=>{
|
c.name.as('child')
|
||||||
c.name.as('child')
|
})
|
||||||
})
|
}) .where ({name:'Cat'})
|
||||||
}) .where ({name:'Cat'})
|
) .to.eventually.eql (
|
||||||
) .to.eql (
|
{ ID:101, parent:'Cat', children:[
|
||||||
{ ID:101, parent:'Cat', children:[
|
{ child:'Kitty' },
|
||||||
{ child:'Kitty' },
|
{ child:'Catwoman' },
|
||||||
{ child:'Catwoman' },
|
]}
|
||||||
]}
|
))
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it ('supports deeply nested reads', async()=>{
|
it ('supports deeply nested reads', ()=> expect (
|
||||||
expect (await SELECT.one.from (Cats, c=>{
|
SELECT.one.from (Cats, c=>{
|
||||||
c.ID, c.name, c.children (
|
c.ID, c.name, c.children (
|
||||||
c => { c.name },
|
c => { c.name },
|
||||||
{levels:3}
|
{levels:3}
|
||||||
)
|
)
|
||||||
}) .where ({name:'Cat'})
|
}) .where ({name:'Cat'})
|
||||||
) .to.eql (
|
) .to.eventually.eql (
|
||||||
{ ID:101, name:'Cat', children:[
|
{ ID:101, name:'Cat', children:[
|
||||||
{ name:'Kitty', children:[
|
{ name:'Kitty', children:[
|
||||||
{ name:'Kitty Cat', children:[
|
{ name:'Kitty Cat', children:[
|
||||||
{ name:'Aristocat' }, ]}, // level 3
|
{ name:'Aristocat' }, ]}, // level 3
|
||||||
{ name:'Kitty Bat', children:[] }, ]},
|
{ name:'Kitty Bat', children:[] }, ]},
|
||||||
{ name:'Catwoman', children:[
|
{ name:'Catwoman', children:[
|
||||||
{ name:'Catalina', children:[] } ]},
|
{ name:'Catalina', children:[] } ]},
|
||||||
]}
|
]}
|
||||||
)
|
))
|
||||||
})
|
|
||||||
|
|
||||||
it ('supports cascaded deletes', async()=>{
|
it ('supports cascaded deletes', async()=>{
|
||||||
const affectedRows = await DELETE.from (Cats) .where ({ID:[102,106]})
|
const affectedRows = await DELETE.from (Cats) .where ({ID:[102,106]})
|
||||||
expect (affectedRows) .to.be.greaterThan (0)
|
expect (affectedRows) .to.be.greaterThan (0)
|
||||||
const expected = [
|
await expect (SELECT`ID,name`.from(Cats) ).to.eventually.eql ([
|
||||||
{ ID:100, name:'Some Cats...' },
|
{ ID:100, name:'Some Cats...' },
|
||||||
{ ID:101, name:'Cat' },
|
{ ID:101, name:'Cat' },
|
||||||
{ ID:108, name:'Catweazle' }
|
{ ID:108, name:'Catweazle' }
|
||||||
]
|
])
|
||||||
expect ( await SELECT`ID,name`.from(Cats) ).to.eql (expected)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const cds = require('@sap/cds/lib')
|
const cds = require('@sap/cds')
|
||||||
|
|
||||||
describe('cap/samples - Localized Data', () => {
|
describe('cap/samples - Localized Data', () => {
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const cds = require('@sap/cds/lib')
|
const cds = require('@sap/cds')
|
||||||
|
|
||||||
describe('cap/samples - Messaging', ()=>{
|
describe('cap/samples - Messaging', ()=>{
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const cds = require('@sap/cds/lib')
|
const cds = require('@sap/cds')
|
||||||
|
|
||||||
describe('cap/samples - Bookshop APIs', () => {
|
describe('cap/samples - Bookshop APIs', () => {
|
||||||
const { GET, expect, axios } = cds.test ('@capire/bookshop')
|
const { GET, expect, axios } = cds.test ('@capire/bookshop')
|
||||||
@@ -8,9 +8,10 @@ describe('cap/samples - Bookshop APIs', () => {
|
|||||||
const { headers, status, data } = await GET `/browse/$metadata`
|
const { headers, status, data } = await GET `/browse/$metadata`
|
||||||
expect(status).to.equal(200)
|
expect(status).to.equal(200)
|
||||||
expect(headers).to.contain({
|
expect(headers).to.contain({
|
||||||
'content-type': 'application/xml',
|
// 'content-type': 'application/xml', //> fails with 'application/xml;charset=utf-8', which is set by express
|
||||||
'odata-version': '4.0',
|
'odata-version': '4.0',
|
||||||
})
|
})
|
||||||
|
expect(headers['content-type']).to.match(/application\/xml/)
|
||||||
expect(data).to.contain('<EntitySet Name="Books" EntityType="CatalogService.Books">')
|
expect(data).to.contain('<EntitySet Name="Books" EntityType="CatalogService.Books">')
|
||||||
expect(data).to.contain('<Annotation Term="Common.Label" String="Currency"/>')
|
expect(data).to.contain('<Annotation Term="Common.Label" String="Currency"/>')
|
||||||
})
|
})
|
||||||
@@ -28,63 +29,66 @@ describe('cap/samples - Bookshop APIs', () => {
|
|||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('supports $search in multiple fields', async () => {
|
describe('query options...', () => {
|
||||||
const { data } = await GET `/browse/Books ${{
|
|
||||||
params: { $search: 'Po', $select: `title,author` },
|
|
||||||
}}`
|
|
||||||
expect(data.value).to.containSubset([
|
|
||||||
{ ID: 201, title: 'Wuthering Heights', author: 'Emily Brontë' },
|
|
||||||
{ ID: 207, title: 'Jane Eyre', author: 'Charlotte Brontë' },
|
|
||||||
{ ID: 251, title: 'The Raven', author: 'Edgar Allen Poe' },
|
|
||||||
{ ID: 252, title: 'Eleonora', author: 'Edgar Allen Poe' },
|
|
||||||
])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('supports $select', async () => {
|
it('supports $search in multiple fields', async () => {
|
||||||
const { data } = await GET(`/browse/Books`, {
|
const { data } = await GET `/browse/Books ${{
|
||||||
params: { $select: `ID,title` },
|
params: { $search: 'Po', $select: `title,author` },
|
||||||
|
}}`
|
||||||
|
expect(data.value).to.containSubset([
|
||||||
|
{ ID: 201, title: 'Wuthering Heights', author: 'Emily Brontë' },
|
||||||
|
{ ID: 207, title: 'Jane Eyre', author: 'Charlotte Brontë' },
|
||||||
|
{ ID: 251, title: 'The Raven', author: 'Edgar Allen Poe' },
|
||||||
|
{ ID: 252, title: 'Eleonora', author: 'Edgar Allen Poe' },
|
||||||
|
])
|
||||||
})
|
})
|
||||||
expect(data.value).to.containSubset([
|
|
||||||
{ ID: 201, title: 'Wuthering Heights' },
|
|
||||||
{ ID: 207, title: 'Jane Eyre' },
|
|
||||||
{ ID: 251, title: 'The Raven' },
|
|
||||||
{ ID: 252, title: 'Eleonora' },
|
|
||||||
{ ID: 271, title: 'Catweazle' },
|
|
||||||
])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('supports $expand', async () => {
|
it('supports $select', async () => {
|
||||||
const { data } = await GET(`/admin/Authors`, {
|
const { data } = await GET(`/browse/Books`, {
|
||||||
params: {
|
params: { $select: `ID,title` },
|
||||||
$select: `name`,
|
})
|
||||||
$expand: `books($select=title)`,
|
expect(data.value).to.containSubset([
|
||||||
},
|
{ ID: 201, title: 'Wuthering Heights' },
|
||||||
|
{ ID: 207, title: 'Jane Eyre' },
|
||||||
|
{ ID: 251, title: 'The Raven' },
|
||||||
|
{ ID: 252, title: 'Eleonora' },
|
||||||
|
{ ID: 271, title: 'Catweazle' },
|
||||||
|
])
|
||||||
})
|
})
|
||||||
expect(data.value).to.containSubset([
|
|
||||||
{ name: 'Emily Brontë', books: [{ title: 'Wuthering Heights' }] },
|
|
||||||
{ name: 'Charlotte Brontë', books: [{ title: 'Jane Eyre' }] },
|
|
||||||
{ name: 'Edgar Allen Poe', books: [{ title: 'The Raven' }, { title: 'Eleonora' }] },
|
|
||||||
{ name: 'Richard Carpenter', books: [{ title: 'Catweazle' }] },
|
|
||||||
])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('supports $value requests', async () => {
|
it('supports $expand', async () => {
|
||||||
const { data } = await GET`/admin/Books/201/stock/$value`
|
const { data } = await GET(`/admin/Authors`, {
|
||||||
expect(data).to.equal(12)
|
params: {
|
||||||
})
|
$select: `name`,
|
||||||
|
$expand: `books($select=title)`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
expect(data.value).to.containSubset([
|
||||||
|
{ name: 'Emily Brontë', books: [{ title: 'Wuthering Heights' }] },
|
||||||
|
{ name: 'Charlotte Brontë', books: [{ title: 'Jane Eyre' }] },
|
||||||
|
{ name: 'Edgar Allen Poe', books: [{ title: 'The Raven' }, { title: 'Eleonora' }] },
|
||||||
|
{ name: 'Richard Carpenter', books: [{ title: 'Catweazle' }] },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
it('supports $top/$skip paging', async () => {
|
it('supports $value requests', async () => {
|
||||||
const { data: p1 } = await GET`/browse/Books?$select=title&$top=3`
|
const { data } = await GET`/admin/Books/201/stock/$value`
|
||||||
expect(p1.value).to.containSubset([
|
expect(data).to.equal(12)
|
||||||
{ ID: 201, title: 'Wuthering Heights' },
|
})
|
||||||
{ ID: 207, title: 'Jane Eyre' },
|
|
||||||
{ ID: 251, title: 'The Raven' },
|
it('supports $top/$skip paging', async () => {
|
||||||
])
|
const { data: p1 } = await GET`/browse/Books?$select=title&$top=3`
|
||||||
const { data: p2 } = await GET`/browse/Books?$select=title&$skip=3`
|
expect(p1.value).to.containSubset([
|
||||||
expect(p2.value).to.containSubset([
|
{ ID: 201, title: 'Wuthering Heights' },
|
||||||
{ ID: 252, title: 'Eleonora' },
|
{ ID: 207, title: 'Jane Eyre' },
|
||||||
{ ID: 271, title: 'Catweazle' },
|
{ ID: 251, title: 'The Raven' },
|
||||||
])
|
])
|
||||||
|
const { data: p2 } = await GET`/browse/Books?$select=title&$skip=3`
|
||||||
|
expect(p2.value).to.containSubset([
|
||||||
|
{ ID: 252, title: 'Eleonora' },
|
||||||
|
{ ID: 271, title: 'Catweazle' },
|
||||||
|
])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('serves user info', async () => {
|
it('serves user info', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user