Merge pull request #127 from SAP-samples/cds.test
Prepare moving test kit over to @sap/cds
This commit is contained in:
@@ -9,8 +9,7 @@
|
||||
"@capire/common": "file:common",
|
||||
"@capire/fiori": "file:fiori",
|
||||
"@capire/orders": "file:orders",
|
||||
"@capire/reviews": "file:reviews",
|
||||
"@capire/tests": "file:test"
|
||||
"@capire/reviews": "file:reviews"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^4.2.0",
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This is included with cds in newer versions
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const { resolve, dirname } = require('path')
|
||||
const cwd = process.cwd()
|
||||
|
||||
// harmonizing jest and mocha
|
||||
const is_mocha = !global.test
|
||||
const is_jest = !!global.test
|
||||
if (is_jest) { // it's jest
|
||||
global.before = (msg,fn) => global.beforeAll(fn||msg)
|
||||
global.after = (msg,fn) => global.afterAll(fn||msg)
|
||||
} else { // it's mocha
|
||||
global.beforeAll = global.before
|
||||
global.afterAll = global.after
|
||||
global.test = global.it
|
||||
}
|
||||
|
||||
/**
|
||||
* Test kit for jest or mocha testing, which can be used statically
|
||||
* via the getters for chai, expect and assert or through a server
|
||||
* started with .launch(...).
|
||||
*/
|
||||
class CDSTestKit {
|
||||
|
||||
/**
|
||||
* Creates a new instance serving projects from subfolders under the root
|
||||
* specified by a sequence of path components which are concatenated with
|
||||
* path.resolve().
|
||||
*/
|
||||
for (...paths) {
|
||||
const tk = new CDSTestKit
|
||||
tk.root = resolve (...paths)
|
||||
return tk
|
||||
}
|
||||
|
||||
/** Lazily loads and returns an instance of chai */
|
||||
get chai() {
|
||||
const chai = require('chai')
|
||||
chai.use (require('chai-as-promised'))
|
||||
chai.use (require('chai-subset'))
|
||||
Object.defineProperty (CDSTestKit.prototype, 'chai', {value:chai})
|
||||
return chai
|
||||
}
|
||||
get expect(){ return this.chai.expect }
|
||||
get assert(){ return this.chai.assert }
|
||||
|
||||
/**
|
||||
* Launches a cds server with arbitrary port and returns a subclass which
|
||||
* also acts as an axios lookalike, providing methods to send requests.
|
||||
*/
|
||||
launch (project, ...args) {
|
||||
|
||||
// Setting up test server
|
||||
const console = global.console, logs=[]
|
||||
const axios = require('axios').default
|
||||
const lazy = this, test = {
|
||||
|
||||
GET: (path,...etc) => axios.get (test.url+path,...etc) .catch(_error),
|
||||
PUT: (path,...etc) => axios.put (test.url+path,...etc) .catch(_error),
|
||||
POST: (path,...etc) => axios.post (test.url+path,...etc) .catch(_error),
|
||||
PATCH: (path,...etc) => axios.patch (test.url+path,...etc) .catch(_error),
|
||||
DELETE: (path,...etc) => axios.delete (test.url+path,...etc) .catch(_error),
|
||||
|
||||
get: (path,...etc) => axios.get (test.url+path,...etc) .catch(_error),
|
||||
put: (path,...etc) => axios.put (test.url+path,...etc) .catch(_error),
|
||||
post: (path,...etc) => axios.post (test.url+path,...etc) .catch(_error),
|
||||
patch: (path,...etc) => axios.patch (test.url+path,...etc) .catch(_error),
|
||||
delete: (path,...etc) => axios.delete (test.url+path,...etc) .catch(_error),
|
||||
|
||||
/** Lazily loads and returns an instance of chai */
|
||||
get chai(){ return lazy.chai },
|
||||
get expect(){ return lazy.expect },
|
||||
get assert(){ return lazy.assert },
|
||||
}
|
||||
|
||||
// launch cds server...
|
||||
before (`launching cds server for ${project}...`, done => {
|
||||
|
||||
const cds = require('@sap/cds'), { isdir } = cds.utils
|
||||
|
||||
let cmd = 'run'
|
||||
if (project.startsWith('cds ')) [ cmd, project ] = [ project.slice(4), args.shift() ]
|
||||
if (!args.length) args = ['--in-memory?']
|
||||
|
||||
// Supporting .launch (<package name>)
|
||||
if (cmd === 'run') {
|
||||
if (isdir(project)) ; //> all fine
|
||||
else if (isdir(resolve(this.root,project))) project = resolve(this.root,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,
|
||||
time: ()=>{}, timeEnd: (...args)=> logs.push(args),
|
||||
debug: (...args)=> logs.push(args),
|
||||
log: (...args)=> logs.push(args),
|
||||
warn: (...args)=> logs.push(args),
|
||||
error: (...args)=> logs.push(args),
|
||||
dump(){ for (let each of logs) console.log (...each) },
|
||||
}
|
||||
|
||||
// return done (new Error(11))
|
||||
process.env.PORT = '0'
|
||||
const p = cds.exec (cmd, project, ...args) // TODO w/ @sap/cds@3.33.3: , '--port', '0')
|
||||
if (p && 'catch' in p) p.catch (e => {
|
||||
if (is_mocha) console.error(e)
|
||||
done(e)
|
||||
})
|
||||
|
||||
cds.once('listening', ({ server, url }) => {
|
||||
Object.assign (test,{server,url})
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
// shutdown cds server...
|
||||
after (done => {
|
||||
if (global.console !== console) global.console = console
|
||||
if (cwd !== process.cwd()) process.chdir(cwd)
|
||||
test.server ? test.server.close (done) : done()
|
||||
process.emit('shutdown')
|
||||
})
|
||||
|
||||
function _error (e) {
|
||||
if (!e.response) throw e
|
||||
if (!e.response.data) throw e
|
||||
if (!e.response.data.error) throw e
|
||||
const { code, message } = e.response.data.error
|
||||
throw new Error (code && code !== 'null' ? `${code} - ${message}` : message)
|
||||
}
|
||||
|
||||
return test
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-global-assign
|
||||
require = (mod) => {
|
||||
try { return module.require(mod) }
|
||||
catch(e) { if (e.code === 'MODULE_NOT_FOUND') throw new Error (`
|
||||
Failed to load required package '${mod}'. Please add it thru:
|
||||
npm add -D ${mod === 'chai' ? 'chai chai-as-promised chai-subset' : mod}
|
||||
`) }
|
||||
}
|
||||
|
||||
module.exports = new CDSTestKit
|
||||
exports.root = __dirname
|
||||
@@ -1 +0,0 @@
|
||||
module.exports = require('./_cds_tests').for(__dirname,'..')
|
||||
158
test/cds.js
Normal file
158
test/cds.js
Normal file
@@ -0,0 +1,158 @@
|
||||
const cds = module.exports = require('@sap/cds/lib')
|
||||
if (!cds.test) { // monkey patching cds
|
||||
|
||||
const { resolve, dirname } = require('path')
|
||||
const cwd = process.cwd()
|
||||
|
||||
// harmonizing jest and mocha
|
||||
const is_mocha = !global.test
|
||||
const is_jest = !!global.test
|
||||
if (is_jest) { // it's jest
|
||||
global.before = (msg,fn) => global.beforeAll(fn||msg)
|
||||
global.after = (msg,fn) => global.afterAll(fn||msg)
|
||||
} else { // it's mocha
|
||||
global.beforeAll = global.before
|
||||
global.afterAll = global.after
|
||||
global.test = global.it
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-global-assign
|
||||
require = (mod) => {
|
||||
try { return module.require(mod) }
|
||||
catch(e) { if (e.code === 'MODULE_NOT_FOUND') throw new Error (`
|
||||
Failed to load required package '${mod}'. Please add it thru:
|
||||
npm add -D ${mod === 'chai' ? 'chai chai-as-promised chai-subset' : mod}
|
||||
`) }
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Test {
|
||||
|
||||
/**
|
||||
* Launches a cds server with arbitrary port and returns a subclass which
|
||||
* also acts as an axios lookalike, providing methods to send requests.
|
||||
* @returns {Test}
|
||||
*/
|
||||
static run (cmd, ...args) {
|
||||
|
||||
// Setting up test server
|
||||
const console = global.console, logs=[]
|
||||
const axios = require('axios').default
|
||||
const test = {__proto__:Test.run,
|
||||
|
||||
GET: (path,...etc) => axios.get (test.url+path,...etc) .catch(_error),
|
||||
PUT: (path,...etc) => axios.put (test.url+path,...etc) .catch(_error),
|
||||
POST: (path,...etc) => axios.post (test.url+path,...etc) .catch(_error),
|
||||
PATCH: (path,...etc) => axios.patch (test.url+path,...etc) .catch(_error),
|
||||
DEL: (path,...etc) => axios.delete (test.url+path,...etc) .catch(_error),
|
||||
|
||||
get: (path,...etc) => axios.get (test.url+path,...etc) .catch(_error),
|
||||
put: (path,...etc) => axios.put (test.url+path,...etc) .catch(_error),
|
||||
post: (path,...etc) => axios.post (test.url+path,...etc) .catch(_error),
|
||||
patch: (path,...etc) => axios.patch (test.url+path,...etc) .catch(_error),
|
||||
delete: (path,...etc) => axios.delete (test.url+path,...etc) .catch(_error),
|
||||
|
||||
}
|
||||
|
||||
// launch cds server...
|
||||
before (`launching ${cmd} ${args.join(' ')}...`, done => {
|
||||
|
||||
// const cds = require('../index'),
|
||||
const { isdir } = cds.utils
|
||||
if (!args.length) {
|
||||
let project = cmd; cmd = 'run'
|
||||
if (isdir(project)) ; //> all fine
|
||||
// Supporting .launch (<package name>)
|
||||
else if (isdir(resolve(project))) project = resolve(project)
|
||||
else try { project = dirname (require.resolve(project+'/package.json')) }
|
||||
catch(e) { throw cds.error (`Cannot resolve project folder for '${project}' in '${process.cwd()}'`) }
|
||||
args.push (project, '--in-memory?')
|
||||
}
|
||||
|
||||
if (!process.env.CDS_TEST_VERBOSE) global.console = { __proto__: global.console, logs,
|
||||
time: ()=>{}, timeEnd: (...args)=> logs.push(args),
|
||||
debug: (...args)=> logs.push(args),
|
||||
log: (...args)=> logs.push(args),
|
||||
warn: (...args)=> logs.push(args),
|
||||
error: (...args)=> logs.push(args),
|
||||
dump(){ for (let each of logs) console.log (...each) },
|
||||
}
|
||||
|
||||
// return done (new Error(11))
|
||||
process.env.PORT = '0'
|
||||
const p = cds.exec (cmd, ...args) // TODO w/ @sap/cds@3.33.3: , '--port', '0')
|
||||
if (p && 'catch' in p) p.catch (e => {
|
||||
if (is_mocha) console.error(e)
|
||||
done(e)
|
||||
})
|
||||
|
||||
cds.once('listening', ({ server, url }) => {
|
||||
Object.assign (test,{server,url})
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
// shutdown cds server...
|
||||
after (done => {
|
||||
if (global.console !== console) global.console = console
|
||||
if (cwd !== process.cwd()) process.chdir(cwd)
|
||||
test.server ? test.server.close (done) : done()
|
||||
process.emit('shutdown')
|
||||
})
|
||||
|
||||
function _error (e) {
|
||||
if (!e.response) throw e
|
||||
if (!e.response.data) throw e
|
||||
if (!e.response.data.error) throw e
|
||||
const { code, message } = e.response.data.error
|
||||
throw new Error (code && code !== 'null' ? `${code} - ${message}` : message)
|
||||
}
|
||||
|
||||
return test
|
||||
}
|
||||
|
||||
/**
|
||||
* Serving projects from subfolders under the root specified by a sequence
|
||||
* of path components which are concatenated with path.resolve().
|
||||
*/
|
||||
in (...paths) {
|
||||
process.chdir (resolve (...paths))
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch on/off console log output.
|
||||
*/
|
||||
verbose(v) {
|
||||
process.env.CDS_TEST_VERBOSE = v
|
||||
return this
|
||||
}
|
||||
|
||||
/** Lazily loads and returns an instance of chai */
|
||||
get chai() {
|
||||
const chai = require('chai')
|
||||
chai.use (require('chai-subset'))
|
||||
chai.use (require('chai-as-promised'))
|
||||
Object.defineProperty (this, 'chai', {value:chai})
|
||||
return chai
|
||||
}
|
||||
get expect(){ return this.chai.expect }
|
||||
get assert(){ return this.chai.assert }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test kit for jest or mocha testing, which can be used statically
|
||||
* via the getters for chai, expect and assert or through a server
|
||||
* started with cds.test(...).
|
||||
* @type Test.run & Test
|
||||
*/
|
||||
Object.defineProperties (Test.run, Object.getOwnPropertyDescriptors (Test.prototype))
|
||||
Object.defineProperty (cds, 'test', {value:Test.run})
|
||||
const cds_load = cds.load; cds.load = (models,o)=>{
|
||||
if (typeof models === 'string') models = models.split(',')
|
||||
return cds_load.call(cds,models,o)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
const { expect } = require('./capire')
|
||||
const cds = require('@sap/cds')
|
||||
const cds = require('./cds'),{ expect } = cds.test
|
||||
const CQL = ([cql]) => cds.parse.cql(cql)
|
||||
const Foo = { name: 'Foo' }
|
||||
const Books = { name: 'capire.bookshop.Books' }
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
const { expect } = require('./capire')
|
||||
const cds = require('@sap/cds')
|
||||
|
||||
const cwd = process.cwd()
|
||||
before (()=> process.chdir(__dirname))
|
||||
after(()=> process.chdir(cwd))
|
||||
const cds = require('./cds')
|
||||
const { expect } = cds.test (
|
||||
'serve', 'AdminService', '--from', '@capire/bookshop,@capire/common', '--in-memory'
|
||||
).in(__dirname)
|
||||
|
||||
describe('Consuming Services locally', () => {
|
||||
//
|
||||
before('bootstrap db and services', async () => {
|
||||
const model = await cds.load(['@capire/bookshop', '@capire/common'])
|
||||
await cds.deploy(model).to('sqlite::memory:')
|
||||
const { AdminService } = await cds.serve('AdminService').from(model)
|
||||
it('bootrapped the database successfully', ()=>{
|
||||
const { AdminService } = cds.services
|
||||
const { Authors } = AdminService.entities
|
||||
expect(AdminService).not.to.be.undefined
|
||||
expect(Authors).not.to.be.undefined
|
||||
})
|
||||
|
||||
it('bootrapped the database successfully', ()=>{})
|
||||
|
||||
it('supports targets as strings or reflected defs', async () => {
|
||||
const AdminService = await cds.connect.to('AdminService')
|
||||
const { Authors } = AdminService.entities
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
const cwd = process.cwd()
|
||||
const { GET, POST, expect } = require('./cds').test('bookshop').in(__dirname,'..')
|
||||
const is_jest = !!global.test
|
||||
if (is_jest) { // it's jest
|
||||
global.before = (msg,fn) => global.beforeAll(fn||msg)
|
||||
global.after = (msg,fn) => global.afterAll(fn||msg)
|
||||
}
|
||||
before (()=> process.chdir(__dirname))
|
||||
after (()=> process.chdir(cwd))
|
||||
|
||||
describe('Custom Handlers', () => {
|
||||
const { GET, POST, expect } = require('./capire').launch('bookshop')
|
||||
|
||||
it('should reject out-of-stock orders', async () => {
|
||||
await expect(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const cds = require ('./cds')
|
||||
const { GET, expect } = cds.test('serve','hello/world.cds').in(__dirname,'..')
|
||||
|
||||
describe('Hello world!', () => {
|
||||
const { GET, expect } = require('./capire').launch('cds serve', __dirname+'/../hello/world.cds', '')
|
||||
|
||||
it('should say hello with class impl', async () => {
|
||||
const {data} = await GET `/say/hello(to='world')`
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const cwd = process.cwd(); process.chdir (__dirname) //> only for internal CI/CD@SAP
|
||||
const {expect} = require('./capire')
|
||||
const cds = require ('@sap/cds')
|
||||
const cds = require ('./cds'), {expect} = cds.test
|
||||
|
||||
// monkey patching older releases:
|
||||
if (!cds.compile.cdl) cds.compile.cdl = cds.parse
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
const cds = require ('./cds')
|
||||
const { GET, expect } = cds.test ('serve', __dirname+'/localized-data.cds', '--in-memory')
|
||||
|
||||
describe('Localized Data', () => {
|
||||
const { GET, expect } = require('./capire').launch('cds serve',__dirname+'/localized-data.cds')
|
||||
|
||||
it('serves localized $metadata documents', async () => {
|
||||
const { data } = await GET`/browse/$metadata?sap-language=de`
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const cwd = process.cwd(); process.chdir (__dirname) //> only for internal CI/CD@SAP
|
||||
const {expect} = require('./capire')
|
||||
const cds = require ('@sap/cds')
|
||||
const cds = require ('./cds'), {expect} = cds.test
|
||||
const _model = '@capire/reviews'
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const { GET, expect } = require('./cds').test('bookshop').in(__dirname,'..')
|
||||
|
||||
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`
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "@capire/tests",
|
||||
"version": "1.0.0",
|
||||
"main": "capire.js"
|
||||
}
|
||||
Reference in New Issue
Block a user