Cleaned up tests
This commit is contained in:
@@ -1,167 +0,0 @@
|
|||||||
describe('@capire/bookshop', () => {
|
|
||||||
const { GET, POST, expect } = require('@capire/tests').launch('@capire/bookshop')
|
|
||||||
|
|
||||||
it('should serve $metadata documents in v4', async () => {
|
|
||||||
const { headers, status, data } = await GET`/browse/$metadata`
|
|
||||||
expect(headers).to.contain({
|
|
||||||
'content-type': 'application/xml',
|
|
||||||
'odata-version': '4.0',
|
|
||||||
})
|
|
||||||
expect(data).to.contain(
|
|
||||||
'<EntitySet Name="Books" EntityType="CatalogService.Books">'
|
|
||||||
)
|
|
||||||
expect(data).to.contain(
|
|
||||||
'<Annotation Term="Common.Label" String="Currency"/>'
|
|
||||||
)
|
|
||||||
expect(status).to.equal(200)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should serve localized $metadata documents', async () => {
|
|
||||||
const { data } = await GET`/browse/$metadata?sap-language=de`
|
|
||||||
expect(data).to.contain(
|
|
||||||
'<Annotation Term="Common.Label" String="Währung"/>'
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should serve localized Books with $expanded currency', async () => {
|
|
||||||
const {
|
|
||||||
data,
|
|
||||||
} = await GET`/browse/Books?&$select=title,author&$expand=currency&sap-language=de`
|
|
||||||
expect(data.value).to.containSubset([
|
|
||||||
{
|
|
||||||
ID: 201,
|
|
||||||
title: 'Sturmhöhe',
|
|
||||||
author: 'Emily Brontë',
|
|
||||||
currency: {
|
|
||||||
code: 'GBP',
|
|
||||||
descr: 'Britische Pfund',
|
|
||||||
name: 'Pfund',
|
|
||||||
symbol: '£',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: 207,
|
|
||||||
title: 'Jane Eyre',
|
|
||||||
author: 'Charlotte Brontë',
|
|
||||||
currency: {
|
|
||||||
descr: 'Britische Pfund',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: 251,
|
|
||||||
title: 'The Raven',
|
|
||||||
author: 'Edgar Allen Poe',
|
|
||||||
currency: {
|
|
||||||
code: 'USD',
|
|
||||||
name: 'US-Dollar',
|
|
||||||
symbol: '$',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: 252,
|
|
||||||
title: 'Eleonora',
|
|
||||||
author: 'Edgar Allen Poe',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: 271,
|
|
||||||
title: 'Catweazle',
|
|
||||||
author: 'Richard Carpenter',
|
|
||||||
currency: {
|
|
||||||
code: 'EUR',
|
|
||||||
name: 'Euro',
|
|
||||||
symbol: '€',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should serve localized Authors w/ $expanded book and currency', async () => {
|
|
||||||
const { data } = await GET(
|
|
||||||
`/admin/Authors/101?sap-language=de` +
|
|
||||||
`&$expand=books($select=title;$expand=currency($select=code,name,symbol))` +
|
|
||||||
`&$select=name`
|
|
||||||
)
|
|
||||||
expect(data).to.eql({
|
|
||||||
'@odata.context':
|
|
||||||
'$metadata#Authors(name,ID,books(title,ID,currency(code,name,symbol)))/$entity',
|
|
||||||
ID: 101,
|
|
||||||
name: 'Emily Brontë',
|
|
||||||
books: [
|
|
||||||
{
|
|
||||||
ID: 201,
|
|
||||||
title: 'Sturmhöhe',
|
|
||||||
currency: {
|
|
||||||
code: 'GBP',
|
|
||||||
name: 'Pfund',
|
|
||||||
symbol: '£',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should check on current stocks with $value', async () => {
|
|
||||||
const { data } = await GET`/admin/Books/201/stock/$value`
|
|
||||||
expect(data).to.equal(12)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should reject out-of-stock orders', () => {
|
|
||||||
return 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/)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should serve $select requests', async () => {
|
|
||||||
const { data } = await GET`/browse/Books?$select=ID,title`
|
|
||||||
expect(data.value).to.eql([
|
|
||||||
{ ID: 201, title: 'Wuthering Heights' },
|
|
||||||
{ ID: 207, title: 'Jane Eyre' },
|
|
||||||
{ ID: 251, title: 'The Raven' },
|
|
||||||
{ ID: 252, title: 'Eleonora' },
|
|
||||||
{ ID: 271, title: 'Catweazle' },
|
|
||||||
])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should serve $search requests', async () => {
|
|
||||||
const { data } = await GET`/admin/Authors?$search=Bro&$select=name`
|
|
||||||
expect(data.value).to.eql([
|
|
||||||
{ ID: 101, name: 'Emily Brontë' },
|
|
||||||
{ ID: 107, name: 'Charlotte Brontë' },
|
|
||||||
])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should serve $expand requests', async () => {
|
|
||||||
const {
|
|
||||||
data,
|
|
||||||
} = await GET`/admin/Authors?$select=name&$expand=books($select=ID,title)`
|
|
||||||
expect(data.value).to.eql([
|
|
||||||
{
|
|
||||||
ID: 101,
|
|
||||||
name: 'Emily Brontë',
|
|
||||||
books: [{ ID: 201, title: 'Wuthering Heights' }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: 107,
|
|
||||||
name: 'Charlotte Brontë',
|
|
||||||
books: [{ ID: 207, title: 'Jane Eyre' }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: 150,
|
|
||||||
name: 'Edgar Allen Poe',
|
|
||||||
books: [
|
|
||||||
{ ID: 251, title: 'The Raven' },
|
|
||||||
{ ID: 252, title: 'Eleonora' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: 170,
|
|
||||||
name: 'Richard Carpenter',
|
|
||||||
books: [{ ID: 271, title: 'Catweazle' }],
|
|
||||||
},
|
|
||||||
])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,31 +1,39 @@
|
|||||||
/** For static usage w/o launching a server */
|
/** For static usage w/o launching a server */
|
||||||
module.exports = exports = {
|
const { resolve, dirname } = require('path')
|
||||||
get chai() { return _chai() },
|
|
||||||
get expect(){ return this.chai.expect },
|
class CDSTestKit {
|
||||||
get assert(){ return this.chai.assert },
|
for (...paths) {
|
||||||
|
const tk = new CDSTestKit
|
||||||
|
tk.root = resolve (...paths)
|
||||||
|
return tk
|
||||||
|
}
|
||||||
|
get chai() {
|
||||||
|
const chai = require('chai')
|
||||||
|
chai.use (require('chai-as-promised'))
|
||||||
|
chai.use (require('chai-subset'))
|
||||||
|
chai.should()
|
||||||
|
Object.defineProperty (this, 'chai', {value:chai})
|
||||||
|
return chai
|
||||||
|
}
|
||||||
|
get expect(){ return this.chai.expect }
|
||||||
|
get assert(){ return this.chai.assert }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lazy = (new CDSTestKit) .for (__dirname,'../..')
|
||||||
|
module.exports = exports = lazy
|
||||||
|
|
||||||
// harmonizing jest and mocha
|
// harmonizing jest and mocha
|
||||||
const is_mocha = !global.test
|
const is_mocha = !global.test
|
||||||
const is_jest = !!global.test
|
const is_jest = !!global.test
|
||||||
if (is_jest) { // it's jest
|
if (is_jest) { // it's jest
|
||||||
global.before = global.beforeAll
|
global.before = (msg,fn) => global.beforeAll(fn||msg)
|
||||||
global.after = global.afterAll
|
global.after = (msg,fn) => global.afterAll(fn||msg)
|
||||||
} else { // it's mocha
|
} else { // it's mocha
|
||||||
global.beforeAll = global.before
|
global.beforeAll = global.before
|
||||||
global.afterAll = global.after
|
global.afterAll = global.after
|
||||||
global.test = global.it
|
global.test = global.it
|
||||||
}
|
}
|
||||||
|
|
||||||
// lazy-loading chai
|
|
||||||
function _chai(){
|
|
||||||
const chai = exports.chai = require('chai')
|
|
||||||
.use (require('chai-as-promised'))
|
|
||||||
.use (require('chai-subset'))
|
|
||||||
chai.should()
|
|
||||||
return chai
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Launching and testing a cds server */
|
/** Launching and testing a cds server */
|
||||||
exports.launch = (project, ...args) => {
|
exports.launch = (project, ...args) => {
|
||||||
@@ -35,37 +43,38 @@ exports.launch = (project, ...args) => {
|
|||||||
const axios = require('axios').default
|
const axios = require('axios').default
|
||||||
const test = {
|
const test = {
|
||||||
|
|
||||||
GET: (path) => axios.get (test.url+path) .catch(_error),
|
GET: (path,...etc) => axios.get (test.url+path,...etc) .catch(_error),
|
||||||
PUT: (path,data) => axios.put (test.url+path,data) .catch(_error),
|
PUT: (path,...etc) => axios.put (test.url+path,...etc) .catch(_error),
|
||||||
POST: (path,data) => axios.post (test.url+path,data) .catch(_error),
|
POST: (path,...etc) => axios.post (test.url+path,...etc) .catch(_error),
|
||||||
PATCH: (path,data) => axios.patch (test.url+path,data) .catch(_error),
|
PATCH: (path,...etc) => axios.patch (test.url+path,...etc) .catch(_error),
|
||||||
DELETE: (path) => axios.delete (test.url+path) .catch(_error),
|
DELETE: (path,...etc) => axios.delete (test.url+path,...etc) .catch(_error),
|
||||||
|
|
||||||
get: (path) => axios.get (test.url+path) .catch(_error),
|
get: (path,...etc) => axios.get (test.url+path,...etc) .catch(_error),
|
||||||
put: (path,data) => axios.put (test.url+path,data) .catch(_error),
|
put: (path,...etc) => axios.put (test.url+path,...etc) .catch(_error),
|
||||||
post: (path,data) => axios.post (test.url+path,data) .catch(_error),
|
post: (path,...etc) => axios.post (test.url+path,...etc) .catch(_error),
|
||||||
patch: (path,data) => axios.patch (test.url+path,data) .catch(_error),
|
patch: (path,...etc) => axios.patch (test.url+path,...etc) .catch(_error),
|
||||||
delete: (path) => axios.delete (test.url+path) .catch(_error),
|
delete: (path,...etc) => axios.delete (test.url+path,...etc) .catch(_error),
|
||||||
|
|
||||||
get chai(){ return _chai() },
|
get chai(){ return lazy.chai },
|
||||||
get expect(){ return this.chai.expect },
|
get expect(){ return lazy.expect },
|
||||||
get assert(){ return this.chai.assert },
|
get assert(){ return lazy.assert },
|
||||||
}
|
}
|
||||||
|
|
||||||
// launch cds server...
|
// launch cds server...
|
||||||
before (done => {
|
before (done => {
|
||||||
|
|
||||||
const cds = require('@sap/cds')
|
const cds = require('@sap/cds'), { isdir } = cds.utils
|
||||||
|
|
||||||
let cmd = 'run'
|
let cmd = 'run'
|
||||||
if (project.startsWith('cds ')) [ cmd, project ] = [ project.slice(4), args.shift() ]
|
if (project.startsWith('cds ')) [ cmd, project ] = [ project.slice(4), args.shift() ]
|
||||||
if (!args.length) args = ['--in-memory?']
|
if (!args.length) args = ['--in-memory?']
|
||||||
|
|
||||||
// Supporting .launch (<package name>)
|
// Supporting .launch (<package name>)
|
||||||
if (cmd === 'run' && !cds.utils.existsSync(project)) try {
|
if (cmd === 'run') {
|
||||||
project = require('path').dirname (require.resolve(project+'/package.json'))
|
if (isdir(project)) ; //> all fine
|
||||||
} catch(e) {
|
else if (isdir(resolve(this.root,project))) project = resolve(this.root,project)
|
||||||
throw cds.error (`Cannot resolve project folder for '${project}'`)
|
else try { project = dirname (require.resolve(project+'/package.json')) }
|
||||||
|
catch(e) { throw cds.error (`Cannot resolve project folder for '${project}'`) }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!process.env.CDS_TEST_VERBOSE) global.console = { __proto__: global.console, logs,
|
if (!process.env.CDS_TEST_VERBOSE) global.console = { __proto__: global.console, logs,
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
const { expect } = require('@capire/tests')
|
const { expect } = require('./capire')
|
||||||
const cds = require('@sap/cds')
|
const cds = require('@sap/cds')
|
||||||
const CQL = ([cql]) => cds.parse.cql(cql)
|
const CQL = ([cql]) => cds.parse.cql(cql)
|
||||||
const Foo = { name: 'Foo' }
|
const Foo = { name: 'Foo' }
|
||||||
|
|||||||
15
test/custom-handlers.test.js
Normal file
15
test/custom-handlers.test.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
describe('Custom Handlers', () => {
|
||||||
|
const { GET, POST, expect } = require('./capire').launch('bookshop')
|
||||||
|
|
||||||
|
it('should reject out-of-stock orders', async () => {
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
const {expect} = require('@capire/tests')
|
|
||||||
const cds = require ('@sap/cds')
|
|
||||||
|
|
||||||
describe('Hierarchical CodeLists', ()=>{
|
|
||||||
|
|
||||||
it ('should bootstrap sqlite in-memory db...', async()=>{
|
|
||||||
await cds.deploy ('@capire/bookshop') .to ('sqlite::memory:')
|
|
||||||
expect (cds.db) .to.exist
|
|
||||||
expect (cds.db.model) .to.exist
|
|
||||||
})
|
|
||||||
|
|
||||||
it ('should insert hierarchy of genres', ()=>{
|
|
||||||
const { Genres } = cds.entities
|
|
||||||
return INSERT.into (Genres) .entries (
|
|
||||||
{ ID:100, name:'Some Sample Genres...', children:[
|
|
||||||
{ ID:101, name:'Cat', children:[
|
|
||||||
{ ID:102, name:'Kitty', children:[
|
|
||||||
{ ID:103, name:'Kitty Cat', children:[
|
|
||||||
{ ID:104, name:'Aristocat' } ]},
|
|
||||||
{ ID:105, name:'Kitty Bat' } ]},
|
|
||||||
{ ID:106, name:'Catwoman', children:[
|
|
||||||
{ ID:107, name:'Catalina' } ]} ]},
|
|
||||||
{ ID:108, name:'Ca<tweazle' }
|
|
||||||
]}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it ('should read genres with children', async()=>{
|
|
||||||
const { Genres } = cds.entities
|
|
||||||
expect (await
|
|
||||||
|
|
||||||
SELECT.one.from (Genres, c=>{
|
|
||||||
c.ID, c.name.as('parent'), c.children (c=>{
|
|
||||||
c.name.as('child')
|
|
||||||
})
|
|
||||||
}) .where ({name:'Cat'})
|
|
||||||
|
|
||||||
) .to.containSubset (
|
|
||||||
|
|
||||||
{ ID:101, parent:'Cat', children:[
|
|
||||||
{ child:'Kitty' },
|
|
||||||
{ child:'Catwoman' },
|
|
||||||
]}
|
|
||||||
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it ('should read deep hierarchy of genres', async()=>{
|
|
||||||
const { Genres } = cds.entities
|
|
||||||
expect (await
|
|
||||||
|
|
||||||
SELECT.one.from (Genres, c=>{
|
|
||||||
c.ID, c.name, c.children (c=>{ c.name },{levels:3})
|
|
||||||
}) .where ({name:'Cat'})
|
|
||||||
|
|
||||||
) .to.containSubset (
|
|
||||||
|
|
||||||
{ ID:101, name:'Cat', children:[
|
|
||||||
{ name:'Kitty', children:[
|
|
||||||
{ name:'Kitty Cat', children:[
|
|
||||||
{ name:'Aristocat' }, ]},
|
|
||||||
{ name:'Kitty Bat' }, ]},
|
|
||||||
{ name:'Catwoman', children:[
|
|
||||||
{ name:'Catalina' } ]},
|
|
||||||
]}
|
|
||||||
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
describe('Hello world!', () => {
|
describe('Hello world!', () => {
|
||||||
const { GET, expect } = require('@capire/tests').launch('cds serve', __dirname+'/../hello/world.cds', '')
|
const { GET, expect } = require('./capire').launch('cds serve', __dirname+'/../hello/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')`
|
||||||
|
|||||||
81
test/hierarchical-data.test.js
Normal file
81
test/hierarchical-data.test.js
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
const {expect} = require('./capire')
|
||||||
|
const cds = require ('@sap/cds')
|
||||||
|
|
||||||
|
const model = cds.parse(`
|
||||||
|
entity Categories {
|
||||||
|
key ID : Integer;
|
||||||
|
name : String;
|
||||||
|
children : Composition of many Categories on children.parent = $self;
|
||||||
|
parent : Association to Categories;
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
const {Categories:Cats} = model.definitions
|
||||||
|
|
||||||
|
|
||||||
|
describe('Hierarchical Data', ()=>{
|
||||||
|
|
||||||
|
before ('bootstrap sqlite in-memory db...', async()=>{
|
||||||
|
await cds.deploy (model) .to ('sqlite::memory:')
|
||||||
|
expect (cds.db) .to.exist
|
||||||
|
expect (cds.db.model) .to.exist
|
||||||
|
})
|
||||||
|
|
||||||
|
it ('supports deeply nested inserts', ()=> INSERT.into (Cats,
|
||||||
|
{ ID:100, name:'Some Cats...', children:[
|
||||||
|
{ ID:101, name:'Cat', children:[
|
||||||
|
{ ID:102, name:'Kitty', children:[
|
||||||
|
{ ID:103, name:'Kitty Cat', children:[
|
||||||
|
{ ID:104, name:'Aristocat' } ]},
|
||||||
|
{ ID:105, name:'Kitty Bat' } ]},
|
||||||
|
{ ID:106, name:'Catwoman', children:[
|
||||||
|
{ ID:107, name:'Catalina' } ]} ]},
|
||||||
|
{ ID:108, name:'Catweazle' }
|
||||||
|
]}
|
||||||
|
))
|
||||||
|
|
||||||
|
it ('supports nested reads', async()=>{
|
||||||
|
expect (await
|
||||||
|
SELECT.one.from (Cats, c=>{
|
||||||
|
c.ID, c.name.as('parent'), c.children (c=>{
|
||||||
|
c.name.as('child')
|
||||||
|
})
|
||||||
|
}) .where ({name:'Cat'})
|
||||||
|
) .to.eql (
|
||||||
|
{ ID:101, parent:'Cat', children:[
|
||||||
|
{ ID:102, child:'Kitty' },
|
||||||
|
{ ID:106, child:'Catwoman' },
|
||||||
|
]}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it ('supports deeply nested reads', async()=>{
|
||||||
|
expect (await SELECT.one.from (Cats, c=>{
|
||||||
|
c.ID, c.name, c.children (
|
||||||
|
c => { c.name },
|
||||||
|
{levels:3}
|
||||||
|
)
|
||||||
|
}) .where ({name:'Cat'})
|
||||||
|
) .to.eql (
|
||||||
|
{ ID:101, name:'Cat', children:[
|
||||||
|
{ ID:102, name:'Kitty', children:[
|
||||||
|
{ ID:103, name:'Kitty Cat', children:[
|
||||||
|
{ ID:104, name:'Aristocat' }, ]}, // level 3
|
||||||
|
{ ID:105, name:'Kitty Bat', children:[] }, ]},
|
||||||
|
{ ID:106, name:'Catwoman', children:[
|
||||||
|
{ ID:107, name:'Catalina', children:[] } ]},
|
||||||
|
]}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it ('supports cascaded deletes', async()=>{
|
||||||
|
const affectedRows = await DELETE.from (Cats) .where ({ID:[102,106]})
|
||||||
|
expect (affectedRows) .to.equal (5)
|
||||||
|
expect ( await SELECT.from(Cats) ).to.eql ([
|
||||||
|
{ ID:100, name:'Some Cats...' },
|
||||||
|
{ ID:101, name:'Cat' },
|
||||||
|
{ ID:104, name:'Aristocat' }, // REVISIT: Should be deleted as well?
|
||||||
|
{ ID:108, name:'Catweazle' }
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
74
test/localized-data.test.js
Normal file
74
test/localized-data.test.js
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
describe('Localized Data', () => {
|
||||||
|
const { GET, expect } = require('./capire').launch('bookshop')
|
||||||
|
|
||||||
|
it('serves localized $metadata documents', async () => {
|
||||||
|
const { data } = await GET`/browse/$metadata?sap-language=de`
|
||||||
|
expect(data).to.contain('<Annotation Term="Common.Label" String="Währung"/>')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('supports sap-language param', async () => {
|
||||||
|
const { data } = await GET(`/browse/Books?$select=title,author` + '&sap-language=de')
|
||||||
|
expect(data.value).to.containSubset([
|
||||||
|
{ title: 'Sturmhöhe', author: 'Emily Brontë' },
|
||||||
|
{ title: 'Jane Eyre', author: 'Charlotte Brontë' },
|
||||||
|
{ title: 'The Raven', author: 'Edgar Allen Poe' },
|
||||||
|
{ title: 'Eleonora', author: 'Edgar Allen Poe' },
|
||||||
|
{ title: 'Catweazle', author: 'Richard Carpenter' },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('supports accept-language header', async () => {
|
||||||
|
const { data } = await GET(`/browse/Books?$select=title,author`, {
|
||||||
|
headers: { 'Accept-Language': 'de' },
|
||||||
|
})
|
||||||
|
expect(data.value).to.containSubset([
|
||||||
|
{ title: 'Sturmhöhe', author: 'Emily Brontë' },
|
||||||
|
{ title: 'Jane Eyre', author: 'Charlotte Brontë' },
|
||||||
|
{ title: 'The Raven', author: 'Edgar Allen Poe' },
|
||||||
|
{ title: 'Eleonora', author: 'Edgar Allen Poe' },
|
||||||
|
{ title: 'Catweazle', author: 'Richard Carpenter' },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('supports queries with $expand', async () => {
|
||||||
|
const { data } = await GET(`/browse/Books?&$select=title,author&$expand=currency`, {
|
||||||
|
headers: { 'Accept-Language': 'de' },
|
||||||
|
})
|
||||||
|
expect(data.value).to.containSubset([
|
||||||
|
{ title: 'Sturmhöhe', author: 'Emily Brontë', currency: { name: 'Pfund' } },
|
||||||
|
{ 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: 'Euro' } },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('supports queries with nested $expand', async () => {
|
||||||
|
const { data } = await GET(`/admin/Authors`, {
|
||||||
|
params: {
|
||||||
|
$filter: `startswith(name,'E')`,
|
||||||
|
$expand: `books(
|
||||||
|
$select=title;
|
||||||
|
$expand=currency(
|
||||||
|
$select=name,symbol
|
||||||
|
)
|
||||||
|
)`.replace(/\s/g, ''),
|
||||||
|
$select: `name`,
|
||||||
|
},
|
||||||
|
headers: { 'Accept-Language': 'de' },
|
||||||
|
})
|
||||||
|
expect(data.value).to.containSubset([
|
||||||
|
{
|
||||||
|
name: 'Emily Brontë',
|
||||||
|
books: [{ title: 'Sturmhöhe', currency: { name: 'Pfund', symbol: '£' } }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Edgar Allen Poe',
|
||||||
|
books: [
|
||||||
|
{ title: 'The Raven', currency: { name: 'US-Dollar', symbol: '$' } },
|
||||||
|
{ title: 'Eleonora', currency: { name: 'US-Dollar', symbol: '$' } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
const {expect} = require('@capire/tests')
|
const {expect} = require('./capire')
|
||||||
const cds = require ('@sap/cds')
|
const cds = require ('@sap/cds')
|
||||||
const _model = '@capire/reviews'
|
const _model = '@capire/reviews'
|
||||||
|
|
||||||
|
|||||||
73
test/odata.test.js
Normal file
73
test/odata.test.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
describe('OData Protocol', () => {
|
||||||
|
const { GET, expect } = require('./capire').launch('bookshop')
|
||||||
|
|
||||||
|
it('serves $metadata documents in v4', async () => {
|
||||||
|
const { headers, status, data } = await GET`/browse/$metadata`
|
||||||
|
expect(status).to.equal(200)
|
||||||
|
expect(headers).to.contain({
|
||||||
|
'content-type': 'application/xml',
|
||||||
|
'odata-version': '4.0',
|
||||||
|
})
|
||||||
|
expect(data).to.contain('<EntitySet Name="Books" EntityType="CatalogService.Books">')
|
||||||
|
expect(data).to.contain('<Annotation Term="Common.Label" String="Currency"/>')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('supports $search in multiple fields', async () => {
|
||||||
|
const { data } = await GET(`/browse/Books`, {
|
||||||
|
params: { $search: 'Po', $select: `title,author` },
|
||||||
|
})
|
||||||
|
expect(data.value).to.eql([
|
||||||
|
{ 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 () => {
|
||||||
|
const { data } = await GET(`/browse/Books`, {
|
||||||
|
params: { $select: `ID,title` },
|
||||||
|
})
|
||||||
|
expect(data.value).to.eql([
|
||||||
|
{ 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 () => {
|
||||||
|
const { data } = await GET(`/admin/Authors`, {
|
||||||
|
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 $value requests', async () => {
|
||||||
|
const { data } = await GET`/admin/Books/201/stock/$value`
|
||||||
|
expect(data).to.equal(12)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('supports $top/$skip paging', async () => {
|
||||||
|
const { data: p1 } = await GET`/browse/Books?$select=title&$top=3`
|
||||||
|
expect(p1.value).to.eql([
|
||||||
|
{ ID: 201, title: 'Wuthering Heights' },
|
||||||
|
{ ID: 207, title: 'Jane Eyre' },
|
||||||
|
{ ID: 251, title: 'The Raven' },
|
||||||
|
])
|
||||||
|
const { data: p2 } = await GET`/browse/Books?$select=title&$skip=3`
|
||||||
|
expect(p2.value).to.eql([
|
||||||
|
{ ID: 252, title: 'Eleonora' },
|
||||||
|
{ ID: 271, title: 'Catweazle' },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@capire/tests",
|
"name": "@capire/tests",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"main": "lib/helpers.js"
|
"main": "capire.js"
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user