Compare commits
29 Commits
using-upse
...
addCustomR
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b22915b6e7 | ||
|
|
6fb46a0ad7 | ||
|
|
d15d0535d9 | ||
|
|
6ee42326a7 | ||
|
|
430d3a46c4 | ||
|
|
308e6b932a | ||
|
|
703d45fab0 | ||
|
|
63c21c5a96 | ||
|
|
e0c6b16b15 | ||
|
|
0771fc06e6 | ||
|
|
dc90cad8f4 | ||
|
|
f731a95bd1 | ||
|
|
2cd092be10 | ||
|
|
a1c2f32408 | ||
|
|
8a6a42f109 | ||
|
|
e790d89065 | ||
|
|
94dd9620e4 | ||
|
|
1672c8d914 | ||
|
|
0132241c43 | ||
|
|
d1619cfa4d | ||
|
|
f844a39069 | ||
|
|
b60e02bb22 | ||
|
|
07ffdedace | ||
|
|
3554674d8e | ||
|
|
45e9c132a9 | ||
|
|
e9a81ad2a8 | ||
|
|
2389924403 | ||
|
|
b733f8333c | ||
|
|
4fa96203cb |
15
.eslint/index.js
Normal file
15
.eslint/index.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const cds = require("@sap/eslint-plugin-cds");
|
||||
|
||||
module.exports = {
|
||||
configs: {
|
||||
recommended: {
|
||||
plugins: ["cloud-cap-samples"],
|
||||
rules: {
|
||||
"cloud-cap-samples/no-open-services": ["error", "show"]
|
||||
}
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
"no-open-services": cds.createRule(require("./rules/no-open-services")),
|
||||
}
|
||||
};
|
||||
5
.eslint/package.json
Normal file
5
.eslint/package.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "eslint-plugin-cloud-cap-samples",
|
||||
"description": "Contains shareable custom lint rules for this repository",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
29
.eslint/rules/no-open-services.js
Normal file
29
.eslint/rules/no-open-services.js
Normal file
@@ -0,0 +1,29 @@
|
||||
module.exports = {
|
||||
meta: {
|
||||
docs: {
|
||||
description: "Service without `@requires/restrict` should not expose fields with personal data.",
|
||||
version: "1.0.0"
|
||||
},
|
||||
fixable: "code",
|
||||
model: "inferred"
|
||||
},
|
||||
create: function (context) {
|
||||
const services = context.getModel() ? context.getModel().services : [];
|
||||
const unprotectedServices = services.filter(s => !s["@requires"] && !s["@restrict"]).map(s => s.name)
|
||||
return { entity: checkForExposedFields };
|
||||
|
||||
function checkForExposedFields(entity) {
|
||||
const entityInUnprotectedService = unprotectedServices.some(service => entity.name.includes(service))
|
||||
if (entityInUnprotectedService) {
|
||||
const elements = Object.keys(entity.elements).filter((name) => ["createdBy", "modifiedBy"].includes(name))
|
||||
for (let element of elements) {
|
||||
context.report({
|
||||
message: `Field '${element}' in '${entity.name}' exposes personal data. Remove field or add \`@restrict/requires\`.`,
|
||||
node: context.getNode(entity),
|
||||
file: entity.$location.file
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
{
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@sap/cds/recommended"
|
||||
"plugin:@sap/cds/recommended",
|
||||
"plugin:cloud-cap-samples/recommended"
|
||||
],
|
||||
"plugins": [
|
||||
"cloud-cap-samples"
|
||||
],
|
||||
"env": {
|
||||
"browser": true,
|
||||
@@ -23,7 +27,7 @@
|
||||
"rules": {
|
||||
"no-console": "off",
|
||||
"require-atomic-updates": "off",
|
||||
"require-await":"warn",
|
||||
"require-await": "warn",
|
||||
"no-unused-vars": ["warn", { "argsIgnorePattern": "_" }]
|
||||
}
|
||||
}
|
||||
|
||||
1
.registry/.gitignore
vendored
1
.registry/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
*.tgz
|
||||
@@ -1,81 +0,0 @@
|
||||
const { exec } = require ('child_process')
|
||||
const isWin = process.platform === 'win32'
|
||||
const express = require ('express')
|
||||
const fs = require ('fs')
|
||||
const app = express()
|
||||
|
||||
const { PORT=4444 } = process.env
|
||||
const [,,port=PORT,scope='@capire'] = process.argv
|
||||
const cwd = __dirname
|
||||
|
||||
// clean up on start (exit handler might not complete on Windows)
|
||||
exec(isWin ? 'del *.tgz' : 'rm *.tgz', {cwd})
|
||||
|
||||
|
||||
app.use('/-/:tarball', (req,res,next) => {
|
||||
console.debug ('GET', req.params)
|
||||
try {
|
||||
const { tarball } = req.params
|
||||
const pkgFull = tarball.substring(0, tarball.lastIndexOf('-'))
|
||||
const [, pkg ] = /^\w+-(.+)/.exec(pkgFull)
|
||||
fs.lstat(tarball,(err => {
|
||||
if (err) console.debug (`npm pack ../${pkg}`)
|
||||
if (err) exec(`npm pack ../${pkg}`,{cwd},next)
|
||||
else next()
|
||||
}))
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
res.sendStatus(500)
|
||||
}
|
||||
})
|
||||
|
||||
app.use('/-', express.static(__dirname))
|
||||
|
||||
app.get('/*', (req,res)=>{
|
||||
const urlRegex = /^\/(@[\w-]+)\/(.+)/
|
||||
const url = decodeURIComponent(req.url)
|
||||
console.debug ('GET',url)
|
||||
try {
|
||||
if (!urlRegex.test(url)) return res.sendStatus(404)
|
||||
const [, scpe, pkg ] = urlRegex.exec(url)
|
||||
const package = require (`${scpe}/${pkg}/package.json`)
|
||||
const tarball = `${scpe.slice(1)}-${pkg}-${package.version}.tgz`
|
||||
// https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md
|
||||
res.json({
|
||||
"name": package.name,
|
||||
"dist-tags": {
|
||||
"latest": package.version
|
||||
},
|
||||
"versions": {
|
||||
[package.version]: {
|
||||
"name": package.name,
|
||||
"version": package.version,
|
||||
"dist": {
|
||||
"tarball": `${server.url}/-/${tarball}`
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
} catch (e) {
|
||||
if (e.code === 'MODULE_NOT_FOUND') return res.sendStatus(404)
|
||||
console.error(e); throw e
|
||||
}
|
||||
})
|
||||
|
||||
const server = app.listen(port, ()=>{
|
||||
const url = server.url = `http://localhost:${server.address().port}`
|
||||
console.log (`npm set ${scope}:registry=${url}`)
|
||||
exec(`npm set ${scope}:registry=${url}`)
|
||||
console.log (`${scope} registry listening on ${url}`)
|
||||
})
|
||||
|
||||
|
||||
const _exit = ()=>{
|
||||
server.close()
|
||||
exec(`npm conf rm "${scope}:registry"`, ()=> { process.exit() })
|
||||
}
|
||||
|
||||
process.on ('SIGTERM',_exit)
|
||||
process.on ('SIGHUP',_exit)
|
||||
process.on ('SIGINT',_exit)
|
||||
process.on ('SIGUSR2',_exit)
|
||||
20
.vscode/launch.json
vendored
20
.vscode/launch.json
vendored
@@ -13,7 +13,7 @@
|
||||
"<node_internals>/**",
|
||||
"**/node_modules/**",
|
||||
"**/cds/lib/lazy.js",
|
||||
"**/cds/lib/req/cls.js",
|
||||
"**/cds/lib/req/cds-context.js",
|
||||
"**/odata-v4/okra/**"
|
||||
]
|
||||
},
|
||||
@@ -26,10 +26,24 @@
|
||||
"<node_internals>/**",
|
||||
"**/node_modules/**",
|
||||
"**/cds/lib/lazy.js",
|
||||
"**/cds/lib/req/cls.js",
|
||||
"**/cds/lib/req/cds-context.js",
|
||||
"**/odata-v4/okra/**"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Debug Mocha Tests",
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"port": 9229,
|
||||
"continueOnAttach": true,
|
||||
"skipFiles": [
|
||||
"<node_internals>/**",
|
||||
"**/node_modules/**",
|
||||
"**/cds/lib/lazy.js",
|
||||
"**/cds/lib/req/cds-context.js",
|
||||
"**/odata-v4/okra/**",
|
||||
]
|
||||
},
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
|
||||
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@@ -10,10 +10,11 @@
|
||||
"<node_internals>/**",
|
||||
"**/node_modules/**",
|
||||
"**/cds/lib/lazy.js",
|
||||
"**/cds/lib/req/cls.js",
|
||||
"**/cds/lib/req/cds-context.js",
|
||||
"**/odata-v4/okra/**"
|
||||
]
|
||||
},
|
||||
"mochaExplorer.debuggerConfig": "Debug Mocha Tests",
|
||||
"mochaExplorer.parallel": true,
|
||||
"eslint.validate": [
|
||||
"cds",
|
||||
@@ -22,5 +23,5 @@
|
||||
"csv (semicolon)",
|
||||
"tsv",
|
||||
"tab"
|
||||
]
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
@@ -4,21 +4,21 @@
|
||||
* currencies, if not obtained through @capire/common.
|
||||
*/
|
||||
|
||||
module.exports = async (db)=>{
|
||||
module.exports = async (tx)=>{
|
||||
|
||||
const has_common = db.model.definitions['sap.common.Currencies'].elements.numcode
|
||||
const has_common = tx.model.definitions['sap.common.Currencies']?.elements.numcode
|
||||
if (has_common) return
|
||||
|
||||
const already_filled = await db.exists('sap.common.Currencies',{code:'EUR'})
|
||||
const already_filled = await tx.exists('sap.common.Currencies',{code:'EUR'})
|
||||
if (already_filled) return
|
||||
|
||||
await INSERT.into ('sap.common.Currencies') .columns (
|
||||
'code','symbol','name'
|
||||
await tx.run (INSERT.into ('sap.common.Currencies') .columns (
|
||||
[ 'code', 'symbol', 'name' ]
|
||||
) .rows (
|
||||
[ 'EUR','€','Euro' ],
|
||||
[ 'USD','$','US Dollar' ],
|
||||
[ 'GBP','£','British Pound' ],
|
||||
[ 'ILS','₪','Shekel' ],
|
||||
[ 'JPY','¥','Yen' ],
|
||||
)
|
||||
[ 'EUR', '€', 'Euro' ],
|
||||
[ 'USD', '$', 'US Dollar' ],
|
||||
[ 'GBP', '£', 'British Pound' ],
|
||||
[ 'ILS', '₪', 'Shekel' ],
|
||||
[ 'JPY', '¥', 'Yen' ],
|
||||
))
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const cds = require("@sap/cds")
|
||||
|
||||
// install OData v2 adapter
|
||||
const cds = require("@sap/cds")
|
||||
const proxy = require('@sap/cds-odata-v2-adapter-proxy')
|
||||
const proxyOpts = global.it ? { target:'auto' } : {} // for tests, set 'auto' to detect port dynamically
|
||||
cds.on('bootstrap', app => app.use(proxy(proxyOpts)))
|
||||
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')
|
||||
module.exports = require('@capire/bookstore/server.js')
|
||||
|
||||
3403
package-lock.json
generated
3403
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@@ -24,18 +24,20 @@
|
||||
"chai": "^4.3.4",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"chai-subset": "^1.6.0",
|
||||
"eslint": "^8.9",
|
||||
"semver": "^7",
|
||||
"sqlite3": "^5"
|
||||
"sqlite3": "^5",
|
||||
"@sap/eslint-plugin-cds": "^2.6.0",
|
||||
"eslint-plugin-cloud-cap-samples": "file:.eslint"
|
||||
},
|
||||
"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",
|
||||
"hello": "cds watch hello",
|
||||
"media": "cds watch media",
|
||||
"mocha": "npx mocha || echo",
|
||||
"jest": "npx jest",
|
||||
"mocha": "CDS_TEST_SILENT=y npx mocha",
|
||||
"jest": "npx jest --silent",
|
||||
"start": "cds watch fiori",
|
||||
"test": "npm run jest -- --silent",
|
||||
"test:hello": "cd hello && npm test"
|
||||
@@ -48,7 +50,8 @@
|
||||
},
|
||||
"mocha": {
|
||||
"recursive": true,
|
||||
"parallel": true
|
||||
"parallel": true,
|
||||
"timeout": 6666
|
||||
},
|
||||
"license": "SAP SAMPLE CODE LICENSE",
|
||||
"private": true
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Overview of Samples
|
||||
|
||||
The following list gives an overview of the samples provided in subdirectories.
|
||||
Each sub directory essentially is an individual npm package arranged in an [all-in-one monorepo](all-in-one-monorepo) umbrella setup.
|
||||
Each sub directory essentially is an individual npm package arranged in an [all-in-one monorepo](#all-in-one-monorepo) umbrella setup.
|
||||
|
||||
|
||||
## [@capire/hello-world](hello)
|
||||
|
||||
@@ -3,8 +3,9 @@ const cds = require('@sap/cds/lib')
|
||||
describe('cap/samples - Custom Handlers', () => {
|
||||
|
||||
const { GET, POST, expect } = cds.test(__dirname+'/../bookshop')
|
||||
if (cds.User.default) cds.User.default = cds.User.Privileged // hard core monkey patch
|
||||
else cds.User = cds.User.Privileged // hard core monkey patch for older cds releases
|
||||
beforeAll(()=>{
|
||||
cds.User.default = cds.User.Privileged // hard core monkey patch
|
||||
})
|
||||
|
||||
it('should reject out-of-stock orders', async () => {
|
||||
await POST `/browse/submitOrder ${{ book: 201, quantity: 5 }}`
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
const cds = require('@sap/cds/lib')
|
||||
|
||||
describe('cap/samples - Fiori APIs - v2', () => {
|
||||
describe('cap/samples - Fiori APIs - v2', function() {
|
||||
|
||||
const { GET, expect, axios } = cds.test ('@capire/fiori', '--with-mocks')
|
||||
axios.defaults.auth = { username: 'alice', password: 'admin' }
|
||||
|
||||
// if (this.timeout) this.timeout(1e6)
|
||||
|
||||
it('serves $metadata documents in v2', async () => {
|
||||
const { headers, data } = await GET `/v2/browse/$metadata`
|
||||
expect(headers).to.contain({
|
||||
|
||||
@@ -16,21 +16,21 @@ describe('cap/samples - 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
|
||||
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' }
|
||||
]}
|
||||
))
|
||||
{ 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()=>{
|
||||
if (require('semver').gte(cds.version, '5.9.0')) {
|
||||
@@ -101,12 +101,12 @@ describe('cap/samples - Hierarchical Data', ()=>{
|
||||
})
|
||||
|
||||
it ('supports cascaded deletes', async()=>{
|
||||
const affectedRows = await DELETE.from (Cats) .where ({ID:[102,106]})
|
||||
expect (affectedRows) .to.be.greaterThan (0)
|
||||
const affectedRows = await DELETE.from (Cats) .where ({ID:[102,106]})
|
||||
expect (affectedRows) .to.be.greaterThan (0)
|
||||
const expected = [
|
||||
{ ID:100, name:'Some Cats...' },
|
||||
{ ID:101, name:'Cat' },
|
||||
{ ID:108, name:'Catweazle' }
|
||||
{ ID:100, name:'Some Cats...' },
|
||||
{ ID:101, name:'Cat' },
|
||||
{ ID:108, name:'Catweazle' }
|
||||
]
|
||||
expect ( await SELECT`ID,name`.from(Cats) ).to.eql (expected)
|
||||
})
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
const cds = require('@sap/cds/lib')
|
||||
|
||||
describe('cap/samples - Localized Data', () => {
|
||||
|
||||
const { GET, expect, cds } = require('@sap/cds/lib').test (__dirname)
|
||||
if (cds.User.default) cds.User.default = cds.User.Privileged // hard core monkey patch
|
||||
else cds.User = cds.User.Privileged // hard core monkey patch for older cds releases
|
||||
const { GET, expect } = cds.test (__dirname)
|
||||
beforeAll(()=>{
|
||||
cds.User.default = cds.User.Privileged // hard core monkey patch
|
||||
})
|
||||
|
||||
|
||||
it('serves localized $metadata documents', async () => {
|
||||
const { data } = await GET(`/browse/$metadata?sap-language=de`, { headers: { 'accept-language': 'de' }})
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
const cds = require('@sap/cds/lib')
|
||||
const {resolve} = require('path')
|
||||
|
||||
describe('cap/samples - Messaging', ()=>{
|
||||
|
||||
const { expect } = cds.test
|
||||
const { expect } = cds.test.in(__dirname,'..')
|
||||
const _model = '@capire/reviews'
|
||||
const Reviews = 'sap.capire.reviews.Reviews'
|
||||
if (cds.User.default) cds.User.default = cds.User.Privileged // hard core monkey patch
|
||||
else cds.User = cds.User.Privileged // hard core monkey patch for older cds releases
|
||||
|
||||
beforeAll(() => { cds.root = resolve(__dirname, '..') })
|
||||
afterAll(() => { cds.root = process.cwd() })
|
||||
beforeAll(()=>{
|
||||
cds.User.default = cds.User.Privileged // hard core monkey patch
|
||||
})
|
||||
|
||||
it ('should bootstrap sqlite in-memory db', async()=>{
|
||||
const db = await cds.deploy (_model) .to ('sqlite::memory:')
|
||||
@@ -35,6 +32,7 @@ describe('cap/samples - Messaging', ()=>{
|
||||
|
||||
it ('should add review', async ()=>{
|
||||
const review = { subject: "201", title: "Captivating", rating: ++N }
|
||||
cds._debug = 1
|
||||
const response = await srv.create ('Reviews') .entries (review)
|
||||
expect (response) .to.containSubset (review)
|
||||
})
|
||||
|
||||
@@ -4,47 +4,6 @@ describe('cap/samples - Bookshop APIs', () => {
|
||||
const { GET, expect, axios } = cds.test ('@capire/bookshop')
|
||||
axios.defaults.auth = { username: 'alice', password: 'admin' }
|
||||
|
||||
// Genres
|
||||
const Drama = {
|
||||
"name": "Drama",
|
||||
"descr": null,
|
||||
"ID": 11,
|
||||
"parent_ID": 10
|
||||
}
|
||||
const Mystery = {
|
||||
"name": "Mystery",
|
||||
"descr": null,
|
||||
"ID": 16,
|
||||
"parent_ID": 10
|
||||
}
|
||||
const Romance = {
|
||||
"name": "Romance",
|
||||
"descr": null,
|
||||
"ID": 15,
|
||||
"parent_ID": 10
|
||||
}
|
||||
|
||||
// Currencies
|
||||
const GBP = {
|
||||
"name": "British Pound",
|
||||
"descr": null,
|
||||
"code": "GBP",
|
||||
"symbol": "£"
|
||||
}
|
||||
const USD = {
|
||||
"name": "US Dollar",
|
||||
"descr": null,
|
||||
"code": "USD",
|
||||
"symbol": "$"
|
||||
}
|
||||
const JPY = {
|
||||
"name": "Yen",
|
||||
"descr": null,
|
||||
"code": "JPY",
|
||||
"symbol": "¥"
|
||||
}
|
||||
|
||||
|
||||
it('serves $metadata documents in v4', async () => {
|
||||
const { headers, status, data } = await GET `/browse/$metadata`
|
||||
expect(status).to.equal(200)
|
||||
@@ -57,6 +16,9 @@ describe('cap/samples - Bookshop APIs', () => {
|
||||
})
|
||||
|
||||
it('serves ListOfBooks?$expand=genre,currency', async () => {
|
||||
const Mystery = { ID: 16, name: 'Mystery', descr: null, parent_ID: 10 }
|
||||
const Romance = { ID: 15, name: 'Romance', descr: null, parent_ID: 10 }
|
||||
const USD = { code: 'USD', name: 'US Dollar', descr: null, symbol: '$' }
|
||||
const { data } = await GET `/browse/ListOfBooks ${{
|
||||
params: { $search: 'Po', $select: `title,author`, $expand:`genre,currency` },
|
||||
}}`
|
||||
@@ -126,14 +88,10 @@ describe('cap/samples - Bookshop APIs', () => {
|
||||
})
|
||||
|
||||
it('serves user info', async () => {
|
||||
{
|
||||
const { data } = await GET (`/user/me`)
|
||||
expect(data).to.containSubset({ id: 'alice', locale:'en' })
|
||||
}
|
||||
{
|
||||
const { data } = await GET (`/user/me`, {auth: { username: 'joe' }})
|
||||
expect(data).to.containSubset({ id: 'joe', locale:'en' })
|
||||
}
|
||||
const { data: alice } = await GET `/user/me`
|
||||
expect(alice).to.containSubset({ id: 'alice', locale:'en' })
|
||||
const { data: joe } = await GET (`/user/me`, {auth: { username: 'joe' }})
|
||||
expect(joe).to.containSubset({ id: 'joe', locale:'en' })
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
|
||||
const cds = require('@sap/cds/lib')
|
||||
const { fork } = require('child_process')
|
||||
const { resolve } = require('path')
|
||||
const verbose = process.env.CDS_TEST_VERBOSE
|
||||
|
||||
describe('cap/samples - Local NPM registry', () => {
|
||||
|
||||
const { expect } = cds.test
|
||||
// ||true
|
||||
|
||||
let registry
|
||||
let axios
|
||||
const cwd = resolve(__dirname, '..')
|
||||
|
||||
before(async ()=> {
|
||||
const env = Object.assign(process.env, {PORT:'0'})
|
||||
const res = await exec (resolve(cwd, '.registry/server.js'), {cwd, stdio: 'pipe', env})
|
||||
registry = res.cp
|
||||
axios = require('axios').create ({ baseURL: res.url, validateStatus: (status)=>status<500 })
|
||||
})
|
||||
|
||||
after(done => { registry.once('exit',done); registry.kill() })
|
||||
|
||||
for (const mod of ['bookshop', 'data-viewer', 'fiori','orders','reviews']) {
|
||||
it(`should serve ${mod}`, async () => {
|
||||
const resp = await axios.get(`/@capire/${mod}`)
|
||||
expect(resp.data).to.containSubset({name: `@capire/${mod}`, versions:{}})
|
||||
const versions = Object.values(resp.data.versions)
|
||||
await axios.get(versions[0].dist.tarball)
|
||||
})
|
||||
}
|
||||
it(`should return 404 for unknown packages`, async () => {
|
||||
let resp = await axios.get(`/@capire/foo`)
|
||||
expect(resp.status).to.equal(404)
|
||||
resp = await axios.get(`/foo`)
|
||||
expect(resp.status).to.equal(404)
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
function exec (script, opts) {
|
||||
return new Promise((resolve, reject)=> {
|
||||
const cp = fork (script, [], opts)
|
||||
.on('error', err => reject(new Error(err)))
|
||||
cp.stdout.on('data', chunk => {
|
||||
if (verbose) console.log(chunk.toString())
|
||||
if (chunk.toString().match(/listening.*(http:.*:\d+)/i)) {
|
||||
resolve({cp, url:RegExp.$1})
|
||||
}
|
||||
})
|
||||
cp.stderr.on('data', chunk => {
|
||||
if (verbose) console.error(chunk.toString())
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user