Compare commits

..

2 Commits

Author SHA1 Message Date
Daniel
adaeb6ab05 cosmetics 2021-03-23 20:48:17 +01:00
Daniel
6e88453dea cds.deploy++ 2021-03-23 20:00:37 +01:00
35 changed files with 156 additions and 189 deletions

View File

@@ -5,7 +5,7 @@ const app = express()
const { PORT=4444 } = process.env
const [,,port=PORT] = process.argv
const cwd = __dirname
process.chdir(__dirname)
app.use('/-/:tarball', (req,res,next) => {
console.debug ('GET', req.params)
@@ -13,7 +13,7 @@ app.use('/-/:tarball', (req,res,next) => {
const { tarball } = req.params
const [, pkg ] = /^capire-(\w+)/.exec(tarball)
fs.lstat(tarball,(err => {
if (err) exec(`npm pack ../${pkg}`,{cwd},next)
if (err) exec(`npm pack ../${pkg}`,next)
else next()
}))
} catch (e) {

37
.vscode/launch.json vendored
View File

@@ -4,31 +4,28 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Attach by Process ID",
"processId": "${command:PickProcess}",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "pwa-node"
},
{
"name": "bookshop",
"command": "npx cds watch bookshop",
"type": "node-terminal",
"command": "cds watch bookshop",
"request": "launch",
"skipFiles": [
"<node_internals>/**",
"**/node_modules/**",
"**/cds/lib/lazy.js",
"**/cds/lib/req/cls.js",
"**/odata-v4/okra/**"
]
"type": "node-terminal",
"skipFiles": ["<node_internals>/**"]
},
{
"name": "Fiori App",
"command": "npx cds watch fiori",
"type": "node-terminal",
"name": "Fiori app",
"command": "cds watch fiori",
"request": "launch",
"skipFiles": [
"<node_internals>/**",
"**/node_modules/**",
"**/cds/lib/lazy.js",
"**/cds/lib/req/cls.js",
"**/odata-v4/okra/**"
]
"type": "node-terminal",
"skipFiles": ["<node_internals>/**"]
}
],
"inputs": [
@@ -36,7 +33,7 @@
"type": "pickString",
"id": "sample",
"description": "Which sample do you want to start?",
"options": [ "bookshop", "fiori", "reviews", "reviews" ],
"options": ["bookshop", "fiori", "reviews", "reviews/test/bookshop"],
"default": "bookshop"
}
]

View File

@@ -4,14 +4,5 @@
"**/.gitignore": true,
"**/.vscode": true,
"LICENSES/**": true
},
"debug.javascript.terminalOptions": {
"skipFiles": [
"<node_internals>/**",
"**/node_modules/**",
"**/cds/lib/lazy.js",
"**/cds/lib/req/cls.js",
"**/odata-v4/okra/**"
]
}
}

View File

@@ -83,4 +83,4 @@ In case you've a question, find a bug, or otherwise need support, use our [commu
## License
Copyright (c) 2021 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, version 2.0 except as noted otherwise in the [LICENSE](LICENSE.txt) file.
Copyright (c) 2021 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, version 2.0 except as noted otherwise in the [LICENSE](LICENSES/Apache-2.0.txt) file.

View File

@@ -35,7 +35,7 @@ const books = new Vue ({
try {
const res = await POST(`/submitOrder`, { amount, book: book.ID })
book.stock = res.data.stock
books.order = { amount, succeeded: `Successfully ordered ${amount} item(s).` }
books.order = { amount, succeeded: `Successfully orderd ${amount} item(s).` }
} catch (e) {
books.order = { amount, failed: e.response.data.error.message }
}

View File

@@ -3,4 +3,4 @@ ID;title;descr;author_ID;stock;price;currency_code;genre_ID
207;Jane Eyre;"Jane Eyre /ɛər/ (originally published as Jane Eyre: An Autobiography) is a novel by English writer Charlotte Brontë, published under the pen name ""Currer Bell"", on 16 October 1847, by Smith, Elder & Co. of London. The first American edition was published the following year by Harper & Brothers of New York. Primarily a bildungsroman, Jane Eyre follows the experiences of its eponymous heroine, including her growth to adulthood and her love for Mr. Rochester, the brooding master of Thornfield Hall. The novel revolutionised prose fiction in that the focus on Jane's moral and spiritual development is told through an intimate, first-person narrative, where actions and events are coloured by a psychological intensity. The book contains elements of social criticism, with a strong sense of Christian morality at its core and is considered by many to be ahead of its time because of Jane's individualistic character and how the novel approaches the topics of class, sexuality, religion and feminism.";107;11;12.34;GBP;11
251;The Raven;"""The Raven"" is a narrative poem by American writer Edgar Allan Poe. First published in January 1845, the poem is often noted for its musicality, stylized language, and supernatural atmosphere. It tells of a talking raven's mysterious visit to a distraught lover, tracing the man's slow fall into madness. The lover, often identified as being a student, is lamenting the loss of his love, Lenore. Sitting on a bust of Pallas, the raven seems to further distress the protagonist with its constant repetition of the word ""Nevermore"". The poem makes use of folk, mythological, religious, and classical references.";150;333;13.13;USD;16
252;Eleonora;"""Eleonora"" is a short story by Edgar Allan Poe, first published in 1842 in Philadelphia in the literary annual The Gift. It is often regarded as somewhat autobiographical and has a relatively ""happy"" ending.";150;555;14;USD;16
271;Catweazle;Catweazle is a British fantasy television series, starring Geoffrey Bayldon in the title role, and created by Richard Carpenter for London Weekend Television. The first series, produced and directed by Quentin Lawrence, was screened in the UK on ITV in 1970. The second series, directed by David Reid and David Lane, was shown in 1971. Each series had thirteen episodes, most but not all written by Carpenter, who also published two books based on the scripts.;170;22;150;JPY;13
271;Catweazle;Catweazle is a British fantasy television series, starring Geoffrey Bayldon in the title role, and created by Richard Carpenter for London Weekend Television. The first series, produced and directed by Quentin Lawrence, was screened in the UK on ITV in 1970. The second series, directed by David Reid and David Lane, was shown in 1971. Each series had thirteen episodes, most but not all written by Carpenter, who also published two books based on the scripts.;170;22;15;EUR;13
1 ID title descr author_ID stock price currency_code genre_ID
3 207 Jane Eyre Jane Eyre /ɛər/ (originally published as Jane Eyre: An Autobiography) is a novel by English writer Charlotte Brontë, published under the pen name "Currer Bell", on 16 October 1847, by Smith, Elder & Co. of London. The first American edition was published the following year by Harper & Brothers of New York. Primarily a bildungsroman, Jane Eyre follows the experiences of its eponymous heroine, including her growth to adulthood and her love for Mr. Rochester, the brooding master of Thornfield Hall. The novel revolutionised prose fiction in that the focus on Jane's moral and spiritual development is told through an intimate, first-person narrative, where actions and events are coloured by a psychological intensity. The book contains elements of social criticism, with a strong sense of Christian morality at its core and is considered by many to be ahead of its time because of Jane's individualistic character and how the novel approaches the topics of class, sexuality, religion and feminism. 107 11 12.34 GBP 11
4 251 The Raven "The Raven" is a narrative poem by American writer Edgar Allan Poe. First published in January 1845, the poem is often noted for its musicality, stylized language, and supernatural atmosphere. It tells of a talking raven's mysterious visit to a distraught lover, tracing the man's slow fall into madness. The lover, often identified as being a student, is lamenting the loss of his love, Lenore. Sitting on a bust of Pallas, the raven seems to further distress the protagonist with its constant repetition of the word "Nevermore". The poem makes use of folk, mythological, religious, and classical references. 150 333 13.13 USD 16
5 252 Eleonora "Eleonora" is a short story by Edgar Allan Poe, first published in 1842 in Philadelphia in the literary annual The Gift. It is often regarded as somewhat autobiographical and has a relatively "happy" ending. 150 555 14 USD 16
6 271 Catweazle Catweazle is a British fantasy television series, starring Geoffrey Bayldon in the title role, and created by Richard Carpenter for London Weekend Television. The first series, produced and directed by Quentin Lawrence, was screened in the UK on ITV in 1970. The second series, directed by David Reid and David Lane, was shown in 1971. Each series had thirteen episodes, most but not all written by Carpenter, who also published two books based on the scripts. 170 22 150 15 JPY EUR 13

View File

@@ -4,7 +4,7 @@
"description": "A simple self-contained bookshop service.",
"dependencies": {
"@capire/common": "*",
"@sap/cds": "^5.0.4",
"@sap/cds": ">=4",
"express": "^4.17.1",
"passport": "0.4.1"
},
@@ -16,8 +16,9 @@
"cds": {
"requires": {
"db": {
"kind": "sql"
"kind": "sqlite",
"model": "*"
}
}
}
}
}

BIN
bookshop/sqlite.db Normal file

Binary file not shown.

View File

@@ -1,15 +1,13 @@
using { sap.capire.bookshop as my } from '../db/schema';
service CatalogService @(path:'/browse') {
/** For displaying lists of Books */
@readonly entity ListOfBooks as projection on Books
excluding { descr };
/** For display in details pages */
@readonly entity Books as projection on my.Books { *,
@readonly entity Books as SELECT from my.Books { *,
author.name as author
} excluding { createdBy, modifiedBy };
@readonly entity ListOfBooks as SELECT from Books
excluding { descr };
@requires: 'authenticated-user'
action submitOrder ( book: Books:ID, amount: Integer ) returns { stock: Integer };
event OrderedBook : { book: Books:ID; amount: Integer; buyer: String };

View File

@@ -5,10 +5,10 @@ class CatalogService extends cds.ApplicationService { init(){
// Reduce stock of ordered books if available stock suffices
this.on ('submitOrder', async req => {
const {book,amount} = req.data
let {stock} = await SELECT `stock` .from (Books,book)
const {book,amount} = req.data, tx = cds.tx(req)
let {stock} = await tx.read('stock').from(Books,book)
if (stock >= amount) {
await UPDATE (Books,book) .with (`stock -=`, amount)
await tx.update (Books,book).with ({ stock: stock -= amount })
await this.emit ('OrderedBook', { book, amount, buyer:req.user.id })
return { stock }
}
@@ -16,8 +16,10 @@ class CatalogService extends cds.ApplicationService { init(){
})
// Add some discount for overstocked books
this.after ('READ','ListOfBooks', each => {
if (each.stock > 111) each.title += ` -- 11% discount!`
this.after ('READ','Books', each => {
if (each.stock > 111) {
each.title += ` -- 11% discount!`
}
})
return super.init()

19
bookshop/srv/server.js Normal file
View File

@@ -0,0 +1,19 @@
const cds = require ('@sap/cds')
cds.on('listening', async ()=>{ try { //> just to see the output at the end; will later on be in db service impl
console.log ('\nFilling database with initial data...')
const m = cds.model.minified() //> we likely should do that by default
const tx = cds.tx()
tx.run ([ //> this will be replaced by
DELETE.from ('sap.capire.bookshop.Authors'),
DELETE.from ('sap.capire.bookshop.Books'),
DELETE.from ('sap.capire.bookshop.Books.texts'),
DELETE.from ('sap.capire.bookshop.Genres'),
DELETE.from ('sap.common.Currencies'),
DELETE.from ('sap.common.Currencies.texts'),
])
await cds.deploy(m).to(tx,{ddl:false})
await tx.commit()
} catch(e) { console.error(e) }})
module.exports = cds.server

View File

@@ -5,11 +5,9 @@ CAD;de;Kanadischer Dollar;Kanadischer Dollar
AUD;de;Australischer Dollar;Australischer Dollar
GBP;de;Pfund;Britische Pfund
ILS;de;Schekel;Israelische Schekel
JPY;de;Yen;Japanische Yen
EUR;fr;euro;de la Zone euro
USD;fr;dollar;dollar des États-Unis
CAD;fr;dollar canadien;dollar canadien
AUD;fr;dollar australien;dollar australien
GBP;fr;livre sterling;pound sterling
ILS;fr;Shekel;shekel israelien
JPY;fr;Yen;Yen japonais
ILS;fr;Shekel;shekel israelien
1 code locale name descr
5 AUD de Australischer Dollar Australischer Dollar
6 GBP de Pfund Britische Pfund
7 ILS de Schekel Israelische Schekel
JPY de Yen Japanische Yen
8 EUR fr euro de la Zone euro
9 USD fr dollar dollar des États-Unis
10 CAD fr dollar canadien dollar canadien
11 AUD fr dollar australien dollar australien
12 GBP fr livre sterling pound sterling
13 ILS fr Shekel shekel israelien
JPY fr Yen Yen japonais

View File

@@ -70,7 +70,7 @@ annotate AdminService.Authors with @(
annotate sap.capire.bookshop.Books with @fiori.draft.enabled;
annotate AdminService.Books with @odata.draft.enabled;
annotate AdminService.Books.texts with @(
annotate AdminService.Books_texts with @(
UI: {
Identification: [{Value:title}],
SelectionFields: [ locale, title ],
@@ -83,7 +83,7 @@ annotate AdminService.Books.texts with @(
);
// Add Value Help for Locales
annotate AdminService.Books.texts {
annotate AdminService.Books_texts {
locale @ValueList:{entity:'Languages',type:#fixed}
}
// In addition we need to expose Languages through AdminService

View File

@@ -54,7 +54,7 @@ annotate my.Books with {
title @title:'{i18n>Title}';
genre @title:'{i18n>Genre}' @Common: { Text: genre.name, TextArrangement: #TextOnly };
author @title:'{i18n>Author}' @Common: { Text: author.name, TextArrangement: #TextOnly };
price @title:'{i18n>Price}' @Measures.ISOCurrency: currency_code;
price @title:'{i18n>Price}';
stock @title:'{i18n>Stock}';
descr @UI.MultiLineText;
}

View File

@@ -6,7 +6,7 @@
"@capire/reviews": "*",
"@capire/orders": "*",
"@capire/common": "*",
"@sap/cds": "^5",
"@sap/cds": ">=4",
"express": "^4.17.1",
"passport": "^0.4.1"
},

View File

@@ -19,7 +19,7 @@ extend Books with {
// Extend Orders with Books as Products
//
using { sap.capire.orders.Orders } from '@capire/orders';
extend Orders.Items with {
using { sap.capire.orders.Orders_Items } from '@capire/orders';
extend Orders_Items with {
book : Association to Books on product.ID = book.ID
}

View File

@@ -38,11 +38,7 @@ GET {{bookshop}}/browse/Books(201)?
&$select=ID,title,rating
&$expand=reviews
###
GET {{bookshop}}/browse/Books?
&$select=title,author&$expand=currency
Accept-Language: de
#################################################
#

View File

@@ -1,3 +1,2 @@
cds.requires.messaging.kind = file-based-messaging
PORT = 4006
# cds.odata.flavor = x4
PORT = 4006

View File

@@ -11,7 +11,6 @@
using { OrdersService } from '../../srv/orders-service';
using { sap.common } from '@capire/common';
@odata.draft.enabled
@@ -69,7 +68,7 @@ annotate OrdersService.Orders with @(
annotate OrdersService.Orders.Items with @(
annotate OrdersService.Orders_Items with @(
UI: {
LineItem: [
{Value: product_ID, Label:'Product ID'},
@@ -78,22 +77,13 @@ annotate OrdersService.Orders.Items with @(
{Value: amount, Label:'Quantity'},
],
Identification: [ //Is the main field group
{Value: product_ID, Label:'Product ID'},
{Value: title, Label:'Product Title'},
{Value: amount, Label:'Amount'},
{Value: title, Label:'Product'},
{Value: price, Label:'Unit Price'},
],
Facets: [
{$Type: 'UI.ReferenceFacet', Label: '{i18n>OrderItems}', Target: '@UI.Identification'},
],
HeaderInfo: {
TypeName: 'Order Item', TypeNamePlural: 'Order Items',
Title: {
Label: 'Product ID ', //A label is possible but it is not considered on the ObjectPage yet
Value: product_ID
},
Description: {Value: createdBy}
},
},
) {
amount @(

View File

@@ -3,17 +3,17 @@ namespace sap.capire.orders;
entity Orders : cuid, managed {
OrderNo : String @title:'Order Number'; //> readable key
Items : Composition of many Orders.Items on Items.up_ = $self;
Items : Composition of many Orders_Items on Items.up_ = $self;
buyer : User;
currency : Currency;
}
entity Orders.Items {
/*key*/ up_ : Association to Orders; // REVISIT: 'key' doesn't work due to bug in runtime
entity Orders_Items {
key ID : UUID;
product : Association to Products;
up_ : Association to Orders;
product : Association to Products @assert.integrity:false; // REVISIT: this is a temporary workaround for a glitch in cds-runtime
amount : Integer;
title : String; //> intentionally replicated as snapshot from product.title or alike
title : String;
price : Double;
}

View File

@@ -2,7 +2,6 @@
"name": "@capire/orders",
"version": "1.0.0",
"dependencies": {
"@capire/common": "*",
"@sap/cds": "^5"
"@sap/cds": ">=4.3.0"
}
}

View File

@@ -1,31 +0,0 @@
@Orders = http://localhost:4006/orders/Orders
### Read Orders
GET {{Orders}}?
###
GET {{Orders}}?$expand=Items
###
GET {{Orders}}(ID={{Order1}},IsActiveEntity=true)/Items
@Order1 = 64e718c9-ff99-47f1-8ca3-950c850777d4
@Order3 = e939604c-ab83-4d4f-bdb6-95fe30b3773e
### Create order, still inactive
POST {{Orders}}
Content-Type: application/json
{"ID": "{{Order3}}"}
### Get inactive order. We have to specify `IsActiveEntity`.
GET {{Orders}}(ID={{Order3}},IsActiveEntity=false)
### Activate order using `.../<servicename>.draftActivate`
POST {{Orders}}(ID={{Order3}},IsActiveEntity=false)/OrdersService.draftActivate
Content-Type: application/json
### Get active order
GET {{Orders}}(ID={{Order3}},IsActiveEntity=true)

View File

@@ -3,7 +3,7 @@ class OrdersService extends cds.ApplicationService {
/** register custom handlers */
init(){
const { 'Orders.Items':OrderItems } = this.entities
const { Orders_Items:OrderItems } = this.entities
this.before ('UPDATE', 'Orders', async function(req) {
const { ID, Items } = req.data

View File

@@ -20,13 +20,12 @@
"sqlite3": "^5.0.0"
},
"scripts": {
"cleanup": "rm -rf node_modules && rm -rf */node_modules && rm -rf */*/node_modules",
"registry": "node .registry/server.js",
"bookshop": "cds watch bookshop",
"fiori": "cds watch fiori",
"media": "cds watch media",
"mocha": "npx mocha || echo",
"jest": "npx jest@^26",
"jest": "npx jest",
"test": "npm run jest --silent"
},
"mocha": {

View File

@@ -7,7 +7,7 @@
"index.cds"
],
"dependencies": {
"@sap/cds": "^5",
"@sap/cds": ">=4",
"express": "^4.17.1"
},
"scripts": {

View File

@@ -2,10 +2,10 @@
## Run all-in-one
Open a terminal window and run the `fiori` app in it:
Open a terminal window and run the bookshop in it:
```sh
npm run fiori
npm run bookshop
```
@@ -17,8 +17,8 @@ Open two terminal windows. In the first one start the reviews service stand-alon
npm run reviews-service
```
In the second one start the `fiori` app:
In the second one start the bookshop:
```sh
npm run fiori
npm run bookshop
```

View File

@@ -152,69 +152,69 @@ describe('cds.ql → cqn', () => {
expect(CQL`SELECT *,a,b from Foo`).to.eql(CQL`SELECT from Foo{*,a,b}`)
//> .to.eql... FIXME: see skipped 'should handle * correctly' below
expect(SELECT.from(Foo, ['a', 'b', '*']))
.to.eql(SELECT.from(Foo).columns('a', 'b', '*'))
.to.eql(SELECT.from(Foo).columns(['a', 'b', '*']))
.to.eql(
SELECT.from(Foo, (foo) => {
foo.a, foo.b, foo('*')
.to.eql(SELECT.from(Foo).columns('a', 'b', '*'))
.to.eql(SELECT.from(Foo).columns(['a', 'b', '*']))
.to.eql(
SELECT.from(Foo, (foo) => {
foo.a, foo.b, foo('*')
})
)
.to.eql({
SELECT: {
from: { ref: ['Foo'] },
columns: [{ ref: ['a'] }, { ref: ['b'] }, cdr ? '*' : { ref: ['*'] }],
},
})
)
.to.eql({
SELECT: {
from: { ref: ['Foo'] },
columns: [{ ref: ['a'] }, { ref: ['b'] }, cdr ? '*' : { ref: ['*'] }],
},
})
})
test('from ( ..., => _.expand ( x=>{...}))', () => {
// SELECT from Foo { *, x, bar.*, car{*}, boo { *, moo.zoo } }
expect(
SELECT.from(Foo, (foo) => {
foo('*'),
foo.x,
foo.car('*'),
foo.boo((b) => {
b('*'), b.moo.zoo((x) => x.y.z)
})
test('from ( ..., => _.expand ( x=>{...}))', () => {
// SELECT from Foo { *, x, bar.*, car{*}, boo { *, moo.zoo } }
expect(
SELECT.from(Foo, (foo) => {
foo('*'),
foo.x,
foo.car('*'),
foo.boo((b) => {
b('*'), b.moo.zoo((x) => x.y.z)
})
})
).to.eql({
SELECT: {
from: { ref: ['Foo'] },
columns: [
cdr ? '*' : { ref: ['*'] },
{ ref: ['x'] },
{ ref: ['car'], expand: ['*'] },
{
ref: ['boo'],
expand: ['*', { ref: ['moo', 'zoo'], expand: [{ ref: ['y', 'z'] }] }],
},
],
},
})
).to.eql({
SELECT: {
from: { ref: ['Foo'] },
columns: [
cdr ? '*' : { ref: ['*'] },
{ ref: ['x'] },
{ ref: ['car'], expand: ['*'] },
{
ref: ['boo'],
expand: ['*', { ref: ['moo', 'zoo'], expand: [{ ref: ['y', 'z'] }] }],
},
],
},
})
})
test('from ( ..., => _.inline ( _=>{...}))', () => {
// SELECT from Foo { *, x, bar.*, car{*}, boo { *, moo.zoo } }
expect(
SELECT.from(Foo, (foo) => {
foo.bar('*'),
foo.bar('.*'), //> leading dot indicates inline
foo.boo((x) => x.moo.zoo),
foo.boo((_) => _.moo.zoo) //> underscore arg name indicates inline
test('from ( ..., => _.inline ( _=>{...}))', () => {
// SELECT from Foo { *, x, bar.*, car{*}, boo { *, moo.zoo } }
expect(
SELECT.from(Foo, (foo) => {
foo.bar('*'),
foo.bar('.*'), //> leading dot indicates inline
foo.boo((x) => x.moo.zoo),
foo.boo((_) => _.moo.zoo) //> underscore arg name indicates inline
})
).to.eql({
SELECT: {
from: { ref: ['Foo'] },
columns: [
{ ref: ['bar'], expand: ['*'] },
{ ref: ['bar'], inline: ['*'] },
{ ref: ['boo'], expand: [{ ref: ['moo', 'zoo'] }] },
{ ref: ['boo'], inline: [{ ref: ['moo', 'zoo'] }] },
],
},
})
).to.eql({
SELECT: {
from: { ref: ['Foo'] },
columns: [
{ ref: ['bar'], expand: ['*'] },
{ ref: ['bar'], inline: ['*'] },
{ ref: ['boo'], expand: [{ ref: ['moo', 'zoo'] }] },
{ ref: ['boo'], inline: [{ ref: ['moo', 'zoo'] }] },
],
},
})
})
test('one / distinct ...', () => {
expect(SELECT.distinct.from(Foo).SELECT)
@@ -280,7 +280,7 @@ describe('cds.ql → cqn', () => {
).to.eql({
SELECT: {
from: { ref: ['Foo'] },
where: cds.version >= '5.3.0'
where: cdr
? [
// '(', //> this one is not required
{ ref: ['ID'] },
@@ -289,7 +289,7 @@ describe('cds.ql → cqn', () => {
'and',
{ ref: ['args'] },
'in',
{ list: args.map(val => ({ val })) },
{ val: args },
'and',
'(', //> this one is missing, and that's changing the logic -> that's a BUG
{ ref: ['x'] },

View File

@@ -6,9 +6,13 @@ else cds.User = cds.User.Privileged // hard core monkey patch for older cds rele
describe('Custom Handlers', () => {
it('should reject out-of-stock orders', async () => {
await POST('/browse/submitOrder', { book: 201, amount: 5 })
await POST('/browse/submitOrder', { book: 201, amount: 5 })
await expect(POST('/browse/submitOrder', { book: 201, amount: 5 })).to.be.rejectedWith(/409 - 5 exceeds stock for book #201/)
await expect(
Promise.all([
POST('/browse/submitOrder', { book: 201, amount: 5 }),
POST('/browse/submitOrder', { book: 201, amount: 5 }),
POST('/browse/submitOrder', { book: 201, amount: 5 }),
])
).to.be.rejectedWith(/409 - 5 exceeds stock for book #201/)
const { data } = await GET`/admin/Books/201/stock/$value`
expect(data).to.equal(2)
})

View File

@@ -1,10 +1,11 @@
const {expect} = require('../test')
const cds = require('@sap/cds/lib')
// monkey patching older releases:
if (!cds.compile.cdl) cds.compile.cdl = cds.parse
const { parse:cdr } = cds.ql
// should become cds.compile(...) when cds5 is released
const model = cds.compile.to.csn (`
const model = cds.compile.cdl (`
entity Categories {
key ID : Integer;
name : String;

View File

@@ -1,2 +1,6 @@
const cds = require('@sap/cds')
module.exports = cds.test.in(__dirname,'..')
const test = require('@sap/cds/lib/utils/tests').in(__dirname,'..')
module.exports = Object.assign(test,{run:test})
// REVISIT: With upcoming release of @sap/cds this should become:
// module.exports = require('@sap/cds/tests').in(__dirname,'..')

View File

@@ -43,7 +43,7 @@ describe('Localized Data', () => {
{ title: 'Jane Eyre', author: 'Charlotte Brontë', currency: { name: 'Pfund' } },
{ title: 'The Raven', author: 'Edgar Allen Poe', currency: { name: 'US-Dollar' } },
{ title: 'Eleonora', author: 'Edgar Allen Poe', currency: { name: 'US-Dollar' } },
{ title: 'Catweazle', author: 'Richard Carpenter', currency: { name: 'Yen' } },
{ title: 'Catweazle', author: 'Richard Carpenter', currency: { name: 'Euro' } },
])
})
@@ -85,7 +85,7 @@ describe('Localized Data', () => {
{ title: 'Jane Eyre', currency: { name: 'British Pound' } },
{ title: 'The Raven', currency: { name: 'US Dollar' } },
{ title: 'Eleonora', currency: { name: 'US Dollar' } },
{ title: 'Catweazle', currency: { name: 'Yen' } },
{ title: 'Catweazle', currency: { name: 'Euro' } },
])
})
})

View File

@@ -20,11 +20,11 @@ describe('Messaging', ()=>{
let N=0, received=[], M=0
it ('should add messaging event handlers', ()=>{
srv.on('reviewed', (msg)=> received.push(msg))
srv.on('reviewed', (msg,next)=> { received.push(msg); return next() })
})
it ('should add more messaging event handlers', ()=>{
srv.on('reviewed', ()=> ++M)
srv.on('reviewed', (_,next)=> { ++M; return next() })
})
it ('should add review', async ()=>{