diff --git a/.registry/.gitignore b/.registry/.gitignore deleted file mode 100644 index aa1ec1ea..00000000 --- a/.registry/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.tgz diff --git a/.registry/server.js b/.registry/server.js deleted file mode 100644 index d3489325..00000000 --- a/.registry/server.js +++ /dev/null @@ -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) diff --git a/.vscode/launch.json b/.vscode/launch.json index 40b41090..40d3ef3c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -13,7 +13,7 @@ "/**", "**/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_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_modules/**", + "**/cds/lib/lazy.js", + "**/cds/lib/req/cds-context.js", + "**/odata-v4/okra/**", + ] + }, ], "inputs": [ { diff --git a/.vscode/settings.json b/.vscode/settings.json index bf4970b0..42681ccc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,10 +10,11 @@ "/**", "**/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" - ] + ], } diff --git a/bookshop/db/init.js b/bookshop/db/init.js index 0db736ca..bfa0fc89 100644 --- a/bookshop/db/init.js +++ b/bookshop/db/init.js @@ -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' ], + )) } diff --git a/fiori/server.js b/fiori/server.js index 70cf701b..b3ab5dde 100644 --- a/fiori/server.js +++ b/fiori/server.js @@ -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') \ No newline at end of file +module.exports = require('@capire/bookstore/server.js') diff --git a/package-lock.json b/package-lock.json index 9a623859..6087b9e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -100,6 +100,7 @@ } }, "loggers": { + "name": "@capire/loggers", "version": "1.0.0", "dependencies": { "@sap/cds": ">=5.9", @@ -444,9 +445,9 @@ } }, "node_modules/@sap/cds": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@sap/cds/-/cds-6.3.1.tgz", - "integrity": "sha512-EywUoV16yfYMMEgpY5M4NdNrdjw7dPcIK5c+pAVjio+16PDa7l2x81AhO/JNWD7g7j/POsNUc2ry+LtRxUuceQ==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@sap/cds/-/cds-6.5.0.tgz", + "integrity": "sha512-xzlFEgm2On2/iztS5rj6200cN+6GrszlKGEOnFXDicJYk9SjDOjWgkWX+1j75c9t7qOSi7vidRSKAKjFyALRXg==", "dependencies": { "@sap/cds-compiler": "^3.2.0", "@sap/cds-foss": "^4" @@ -789,9 +790,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.1.3.tgz", - "integrity": "sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.2.tgz", + "integrity": "sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw==", "dev": true, "dependencies": { "follow-redirects": "^1.15.0", @@ -1984,9 +1985,9 @@ "dev": true }, "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true, "optional": true }, @@ -3476,9 +3477,9 @@ } }, "node_modules/sqlite3": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.2.tgz", - "integrity": "sha512-D0Reg6pRWAFXFUnZKsszCI67tthFD8fGPewRddDCX6w4cYwz3MbvuwRICbL+YQjBAh9zbw+lJ/V9oC8nG5j6eg==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.4.tgz", + "integrity": "sha512-i0UlWAzPlzX3B5XP2cYuhWQJsTtlMD6obOa1PgeEQ4DHEXUuyJkgv50I3isqZAP5oFc2T8OFvakmDh2W6I+YpA==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -4211,9 +4212,9 @@ } }, "@sap/cds": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@sap/cds/-/cds-6.3.1.tgz", - "integrity": "sha512-EywUoV16yfYMMEgpY5M4NdNrdjw7dPcIK5c+pAVjio+16PDa7l2x81AhO/JNWD7g7j/POsNUc2ry+LtRxUuceQ==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@sap/cds/-/cds-6.5.0.tgz", + "integrity": "sha512-xzlFEgm2On2/iztS5rj6200cN+6GrszlKGEOnFXDicJYk9SjDOjWgkWX+1j75c9t7qOSi7vidRSKAKjFyALRXg==", "requires": { "@sap/cds-compiler": "^3.2.0", "@sap/cds-foss": "^4" @@ -4482,9 +4483,9 @@ "dev": true }, "axios": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.1.3.tgz", - "integrity": "sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.2.tgz", + "integrity": "sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw==", "dev": true, "requires": { "follow-redirects": "^1.15.0", @@ -5403,9 +5404,9 @@ "dev": true }, "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true, "optional": true }, @@ -6503,9 +6504,9 @@ } }, "sqlite3": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.2.tgz", - "integrity": "sha512-D0Reg6pRWAFXFUnZKsszCI67tthFD8fGPewRddDCX6w4cYwz3MbvuwRICbL+YQjBAh9zbw+lJ/V9oC8nG5j6eg==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.4.tgz", + "integrity": "sha512-i0UlWAzPlzX3B5XP2cYuhWQJsTtlMD6obOa1PgeEQ4DHEXUuyJkgv50I3isqZAP5oFc2T8OFvakmDh2W6I+YpA==", "dev": true, "requires": { "@mapbox/node-pre-gyp": "^1.0.0", diff --git a/package.json b/package.json index 3780ed0a..4cbf9692 100644 --- a/package.json +++ b/package.json @@ -32,13 +32,12 @@ }, "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" @@ -51,7 +50,8 @@ }, "mocha": { "recursive": true, - "parallel": true + "parallel": true, + "timeout": 6666 }, "license": "SAP SAMPLE CODE LICENSE", "private": true diff --git a/samples.md b/samples.md index afaa083a..9caed0e8 100644 --- a/samples.md +++ b/samples.md @@ -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) diff --git a/test/custom-handlers.test.js b/test/custom-handlers.test.js index ae2184d3..5bd8acda 100644 --- a/test/custom-handlers.test.js +++ b/test/custom-handlers.test.js @@ -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 }}` diff --git a/test/fiori.test.js b/test/fiori.test.js index 9da8eb5e..a48abc3c 100644 --- a/test/fiori.test.js +++ b/test/fiori.test.js @@ -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({ diff --git a/test/hierarchical-data.test.js b/test/hierarchical-data.test.js index 3f12ff57..94741978 100644 --- a/test/hierarchical-data.test.js +++ b/test/hierarchical-data.test.js @@ -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) }) diff --git a/test/localized-data/services.test.js b/test/localized-data/services.test.js index a440e60e..8ec30485 100644 --- a/test/localized-data/services.test.js +++ b/test/localized-data/services.test.js @@ -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' }}) diff --git a/test/messaging.test.js b/test/messaging.test.js index f31f715a..9e9ab66c 100644 --- a/test/messaging.test.js +++ b/test/messaging.test.js @@ -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) }) diff --git a/test/odata.test.js b/test/odata.test.js index c0987828..73ac0ff4 100644 --- a/test/odata.test.js +++ b/test/odata.test.js @@ -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' }) }) }) diff --git a/test/registry.test.js b/test/registry.test.js deleted file mode 100644 index 5c64c31e..00000000 --- a/test/registry.test.js +++ /dev/null @@ -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(() => { 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()) - }) - }) - -}