1
0
Fork 0
arangodb/js/client/tests/shell/shell-foxx-api-spec.js

1375 lines
47 KiB
JavaScript

/* global arango, describe, beforeEach, afterEach, it*/
'use strict';
const expect = require('chai').expect;
const FoxxManager = require('@arangodb/foxx/manager');
const request = require('@arangodb/request');
const util = require('@arangodb/util');
const fs = require('fs');
const internal = require('internal');
const path = require('path');
const basePath = path.resolve(internal.startupPath, 'common', 'test-data', 'apps', 'headers');
const arangodb = require('@arangodb');
const db = arangodb.db;
const aql = arangodb.aql;
var origin = arango.getEndpoint().replace(/\+vpp/, '').replace(/^tcp:/, 'http:').replace(/^ssl:/, 'https:');
describe('FoxxApi commit', function () {
const mount = '/test';
beforeEach(function () {
try {
FoxxManager.uninstall(mount, {force: true});
} catch (e) {}
FoxxManager.install(basePath, mount);
});
afterEach(function () {
try {
FoxxManager.uninstall(mount, {force: true});
} catch (e) {}
});
it('should fix missing service definition', function () {
db._query(aql`
FOR service IN _apps
FILTER service.mount == ${mount}
REMOVE service IN _apps
`);
let result = request.get('/test/header-echo', { headers: { origin } });
expect(result.statusCode).to.equal(404);
result = request.post('/_api/foxx/commit');
expect(result.statusCode).to.equal(204);
result = request.get('/test/header-echo', { headers: { origin } });
expect(result.statusCode).to.equal(200);
expect(result.headers['access-control-allow-origin']).to.equal(origin);
});
it('should fix missing checksum', function () {
db._query(aql`
FOR service IN _apps
FILTER service.mount == ${mount}
UPDATE service WITH { checksum: null } IN _apps
`);
let checksum = db._query(aql`
FOR service IN _apps
FILTER service.mount == ${mount}
RETURN service.checksum
`).next();
expect(checksum).to.equal(null);
const result = request.post('/_api/foxx/commit');
expect(result.statusCode).to.equal(204);
checksum = db._query(aql`
FOR service IN _apps
FILTER service.mount == ${mount}
RETURN service.checksum
`).next();
expect(checksum).to.not.equal(null);
});
it('without param replace should not fix wrong checksum', function () {
db._query(aql`
FOR service IN _apps
FILTER service.mount == ${mount}
UPDATE service WITH { checksum: '1234' } IN _apps
`);
let checksum = db._query(aql`
FOR service IN _apps
FILTER service.mount == ${mount}
RETURN service.checksum
`).next();
expect(checksum).to.equal('1234');
const result = request.post('/_api/foxx/commit');
expect(result.statusCode).to.equal(204);
checksum = db._query(aql`
FOR service IN _apps
FILTER service.mount == ${mount}
RETURN service.checksum
`).next();
expect(checksum).to.equal('1234');
});
it('with param replace should fix wrong checksum', function () {
db._query(aql`
FOR service IN _apps
FILTER service.mount == ${mount}
UPDATE service WITH { checksum: '1234' } IN _apps
`);
let checksum = db._query(aql`
FOR service IN _apps
FILTER service.mount == ${mount}
RETURN service.checksum
`).next();
expect(checksum).to.equal('1234');
const result = request.post('/_api/foxx/commit', { qs: { replace: true } });
expect(result.statusCode).to.equal(204);
checksum = db._query(aql`
FOR service IN _apps
FILTER service.mount == ${mount}
RETURN service.checksum
`).next();
expect(checksum).to.not.equal('1234');
});
it('should fix missing bundle', function () {
db._query(aql`
FOR bundle IN _appbundles
REMOVE bundle IN _appbundles
`);
let bundles = db._query(aql`
FOR bundle IN _appbundles
RETURN 1
`).toArray().length;
expect(bundles).to.equal(0);
const result = request.post('/_api/foxx/commit', { qs: { replace: true } });
expect(result.statusCode).to.equal(204);
bundles = db._query(aql`
FOR bundle IN _appbundles
RETURN 1
`).toArray().length;
expect(bundles).to.equal(1);
});
});
describe('Foxx service', () => {
const mount = '/foxx-crud-test';
const basePath = path.resolve(internal.startupPath, 'common', 'test-data', 'apps', 'minimal-working-service');
const itzPath = path.resolve(internal.startupPath, 'common', 'test-data', 'apps', 'itzpapalotl');
var utils = require('@arangodb/foxx/manager-utils');
const servicePath = utils.zipDirectory(basePath);
const serviceServiceMount = '/foxx-crud-test-download';
const serviceServicePath = path.resolve(internal.startupPath, 'common', 'test-data', 'apps', 'service-service', 'index.js');
beforeEach(() => {
FoxxManager.install(serviceServicePath, serviceServiceMount);
});
afterEach(() => {
try {
FoxxManager.uninstall(serviceServiceMount, {force: true});
} catch (e) {}
});
afterEach(() => {
try {
FoxxManager.uninstall(mount, {force: true});
} catch (e) {}
});
const cases = [
{
name: 'localJsFile',
request: {
qs: {
mount
},
body: {
source: path.resolve(basePath, 'index.js')
},
json: true
}
},
{
name: 'localZipFile',
request: {
qs: {
mount
},
body: {
source: servicePath
},
json: true
}
},
{
name: 'localDir',
request: {
qs: {
mount
},
body: {
source: basePath
},
json: true
}
},
{
name: 'jsBuffer',
request: {
qs: {
mount
},
body: fs.readFileSync(path.resolve(basePath, 'index.js')),
contentType: 'application/javascript'
}
},
{
name: 'zipBuffer',
request: {
qs: {
mount
},
body: fs.readFileSync(servicePath),
contentType: 'application/zip'
}
},
{
name: 'remoteJsFile',
request: {
qs: {
mount
},
body: {
source: `${origin}/_db/${db._name()}${serviceServiceMount}/js`
},
json: true
}
},
{
name: 'remoteZipFile',
request: {
qs: {
mount
},
body: {
source: `${origin}/_db/${db._name()}${serviceServiceMount}/zip`
},
json: true
}
}
];
for (const c of cases) {
it(`installed via ${c.name} should be available`, () => {
const installResp = request.post('/_api/foxx', c.request);
expect(installResp.status).to.equal(201);
const resp = request.get(c.request.qs.mount);
expect(resp.json).to.eql({hello: 'world'});
});
it(`replaced via ${c.name} should be available`, () => {
FoxxManager.install(itzPath, c.request.qs.mount);
const replaceResp = request.put('/_api/foxx/service', c.request);
expect(replaceResp.status).to.equal(200);
const resp = request.get(c.request.qs.mount);
expect(resp.json).to.eql({hello: 'world'});
});
it(`upgrade via ${c.name} should be available`, () => {
FoxxManager.install(itzPath, c.request.qs.mount);
const upgradeResp = request.patch('/_api/foxx/service', c.request);
expect(upgradeResp.status).to.equal(200);
const resp = request.get(c.request.qs.mount);
expect(resp.json).to.eql({hello: 'world'});
});
}
it('uninstalled should not be available', () => {
FoxxManager.install(basePath, mount);
const delResp = request.delete('/_api/foxx/service', {qs: {mount}});
expect(delResp.status).to.equal(204);
expect(delResp.body).to.equal('');
const resp = request.get(mount);
expect(resp.status).to.equal(404);
});
const confPath = path.resolve(internal.startupPath, 'common', 'test-data', 'apps', 'with-configuration');
it('empty configuration should be available', () => {
FoxxManager.install(basePath, mount);
const resp = request.get('/_api/foxx/configuration', {qs: {mount}});
expect(resp.status).to.equal(200);
expect(resp.json).to.eql({});
});
it('empty non-minimal configuration should be available', () => {
FoxxManager.install(basePath, mount);
const resp = request.get('/_api/foxx/configuration', {qs: {mount, minimal: false}});
expect(resp.status).to.equal(200);
expect(resp.json).to.eql({});
});
it('empty minimal configuration should be available', () => {
FoxxManager.install(basePath, mount);
const resp = request.get('/_api/foxx/configuration', {qs: {mount, minimal: true}});
expect(resp.status).to.equal(200);
expect(resp.json).to.eql({});
});
it('configuration should be available', () => {
FoxxManager.install(confPath, mount);
const resp = request.get('/_api/foxx/configuration', {qs: {mount}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.not.have.property('current');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('non-minimal configuration should be available', () => {
FoxxManager.install(confPath, mount);
const resp = request.get('/_api/foxx/configuration', {qs: {mount, minimal: false}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.not.have.property('current');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('minimal configuration should be available', () => {
FoxxManager.install(confPath, mount);
const resp = request.get('/_api/foxx/configuration', {qs: {mount, minimal: true}});
expect(resp.status).to.equal(200);
expect(resp.json).to.eql({});
});
it('configuration should be available after update', () => {
FoxxManager.install(confPath, mount);
const updateResp = request.patch('/_api/foxx/configuration', {
qs: {
mount
},
body: {
test1: 'test'
},
json: true
});
expect(updateResp.status).to.equal(200);
expect(updateResp.json).to.have.property('values');
expect(updateResp.json.values).to.have.property('test1', 'test');
expect(updateResp.json.values).to.not.have.property('test2');
expect(updateResp.json).to.not.have.property('warnings');
const resp = request.get('/_api/foxx/configuration', {qs: {mount}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', 'test');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('non-minimal configuration should be available after update', () => {
FoxxManager.install(confPath, mount);
const updateResp = request.patch('/_api/foxx/configuration', {
qs: {
mount,
minimal: false
},
body: {
test1: 'test'
},
json: true
});
expect(updateResp.status).to.equal(200);
expect(updateResp.json).to.have.property('test1');
expect(updateResp.json.test1).to.have.property('current', 'test');
expect(updateResp.json.test1).to.not.have.property('warning');
expect(updateResp.json).to.have.property('test2');
expect(updateResp.json.test2).to.not.have.property('current');
expect(updateResp.json.test2).to.not.have.property('warning');
const resp = request.get('/_api/foxx/configuration', {qs: {mount, minimal: false}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', 'test');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('minimal configuration should be available after update', () => {
FoxxManager.install(confPath, mount);
const updateResp = request.patch('/_api/foxx/configuration', {
qs: {
mount,
minimal: true
},
body: {
test1: 'test'
},
json: true
});
expect(updateResp.status).to.equal(200);
expect(updateResp.json).to.have.property('values');
expect(updateResp.json.values).to.have.property('test1', 'test');
expect(updateResp.json.values).to.not.have.property('test2');
expect(updateResp.json).to.not.have.property('warnings');
const resp = request.get('/_api/foxx/configuration', {qs: {mount, minimal: true}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1', 'test');
expect(resp.json).to.not.have.property('test2');
});
it('configuration should be available after replace', () => {
FoxxManager.install(confPath, mount);
const replaceResp = request.put('/_api/foxx/configuration', {
qs: {
mount
},
body: {
test1: 'test'
},
json: true
});
expect(replaceResp.status).to.equal(200);
expect(replaceResp.json).to.have.property('values');
expect(replaceResp.json.values).to.have.property('test1', 'test');
expect(replaceResp.json.values).to.not.have.property('test2');
expect(replaceResp.json).to.have.property('warnings');
expect(replaceResp.json.warnings).to.have.property('test2', 'is required');
const resp = request.get('/_api/foxx/configuration', {qs: {mount}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', 'test');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('non-minimal configuration should be available after replace', () => {
FoxxManager.install(confPath, mount);
const replaceResp = request.put('/_api/foxx/configuration', {
qs: {
mount,
minimal: false
},
body: {
test1: 'test'
},
json: true
});
expect(replaceResp.status).to.equal(200);
expect(replaceResp.json).to.have.property('test1');
expect(replaceResp.json.test1).to.have.property('current', 'test');
expect(replaceResp.json.test1).to.not.have.property('warning');
expect(replaceResp.json).to.have.property('test2');
expect(replaceResp.json.test2).to.not.have.property('current');
expect(replaceResp.json.test2).to.have.property('warning', 'is required');
const resp = request.get('/_api/foxx/configuration', {qs: {mount, minimal: false}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', 'test');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('minimal configuration should be available after replace', () => {
FoxxManager.install(confPath, mount);
const replaceResp = request.put('/_api/foxx/configuration', {
qs: {
mount,
minimal: true
},
body: {
test1: 'test'
},
json: true
});
expect(replaceResp.status).to.equal(200);
expect(replaceResp.json).to.have.property('values');
expect(replaceResp.json.values).to.have.property('test1', 'test');
expect(replaceResp.json.values).to.not.have.property('test2');
expect(replaceResp.json).to.have.property('warnings');
expect(replaceResp.json.warnings).to.have.property('test2', 'is required');
const resp = request.get('/_api/foxx/configuration', {qs: {mount, minimal: true}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1', 'test');
expect(resp.json).to.not.have.property('test2');
});
it('configuration should be merged after update', () => {
FoxxManager.install(confPath, mount);
const replaceResp = request.put('/_api/foxx/configuration', {
qs: {
mount
},
body: {
test2: 'test2'
},
json: true
});
expect(replaceResp.status).to.equal(200);
const updateResp = request.patch('/_api/foxx/configuration', {
qs: {
mount
},
body: {
test1: 'test1'
},
json: true
});
expect(updateResp.status).to.equal(200);
const resp = request.get('/_api/foxx/configuration', {qs: {mount}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', 'test1');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.have.property('current', 'test2');
});
it('non-minimal configuration should be merged after update', () => {
FoxxManager.install(confPath, mount);
const replaceResp = request.put('/_api/foxx/configuration', {
qs: {
mount,
minimal: false
},
body: {
test2: 'test2'
},
json: true
});
expect(replaceResp.status).to.equal(200);
const updateResp = request.patch('/_api/foxx/configuration', {
qs: {
mount,
minimal: false
},
body: {
test1: 'test1'
},
json: true
});
expect(updateResp.status).to.equal(200);
const resp = request.get('/_api/foxx/configuration', {qs: {mount, minimal: false}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', 'test1');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.have.property('current', 'test2');
});
it('minimal configuration should be merged after update', () => {
FoxxManager.install(confPath, mount);
const replaceResp = request.put('/_api/foxx/configuration', {
qs: {
mount,
minimal: true
},
body: {
test2: 'test2'
},
json: true
});
expect(replaceResp.status).to.equal(200);
const updateResp = request.patch('/_api/foxx/configuration', {
qs: {
mount,
minimal: true
},
body: {
test1: 'test1'
},
json: true
});
expect(updateResp.status).to.equal(200);
const resp = request.get('/_api/foxx/configuration', {qs: {mount, minimal: true}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1', 'test1');
expect(resp.json).to.have.property('test2', 'test2');
});
it('configuration should be overwritten after replace', () => {
FoxxManager.install(confPath, mount);
const updateResp = request.patch('/_api/foxx/configuration', {
qs: {
mount
},
body: {
test2: 'test2'
},
json: true
});
expect(updateResp.status).to.equal(200);
const replaceResp = request.put('/_api/foxx/configuration', {
qs: {
mount
},
body: {
test1: 'test'
},
json: true
});
expect(replaceResp.status).to.equal(200);
const resp = request.get('/_api/foxx/configuration', {qs: {mount}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', 'test');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('non-minimal configuration should be overwritten after replace', () => {
FoxxManager.install(confPath, mount);
const updateResp = request.patch('/_api/foxx/configuration', {
qs: {
mount,
minimal: false
},
body: {
test2: 'test2'
},
json: true
});
expect(updateResp.status).to.equal(200);
const replaceResp = request.put('/_api/foxx/configuration', {
qs: {
mount,
minimal: false
},
body: {
test1: 'test'
},
json: true
});
expect(replaceResp.status).to.equal(200);
const resp = request.get('/_api/foxx/configuration', {qs: {mount, minimal: false}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', 'test');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('minimal configuration should be overwritten after replace', () => {
FoxxManager.install(confPath, mount);
const updateResp = request.patch('/_api/foxx/configuration', {
qs: {
mount,
minimal: true
},
body: {
test2: 'test2'
},
json: true
});
expect(updateResp.status).to.equal(200);
const replaceResp = request.put('/_api/foxx/configuration', {
qs: {
mount,
minimal: true
},
body: {
test1: 'test'
},
json: true
});
expect(replaceResp.status).to.equal(200);
const resp = request.get('/_api/foxx/configuration', {qs: {mount, minimal: true}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1', 'test');
expect(resp.json).not.to.have.property('test2');
});
const depPath = path.resolve(internal.startupPath, 'common', 'test-data', 'apps', 'with-dependencies');
it('empty configuration should be available', () => {
FoxxManager.install(basePath, mount);
const resp = request.get('/_api/foxx/dependencies', {qs: {mount}});
expect(resp.status).to.equal(200);
expect(resp.json).to.eql({});
});
it('empty non-minimal configuration should be available', () => {
FoxxManager.install(basePath, mount);
const resp = request.get('/_api/foxx/dependencies', {qs: {mount, minimal: false}});
expect(resp.status).to.equal(200);
expect(resp.json).to.eql({});
});
it('empty minimal configuration should be available', () => {
FoxxManager.install(basePath, mount);
const resp = request.get('/_api/foxx/dependencies', {qs: {mount, minimal: true}});
expect(resp.status).to.equal(200);
expect(resp.json).to.eql({});
});
it('dependencies should be available', () => {
FoxxManager.install(depPath, mount);
const resp = request.get('/_api/foxx/dependencies', {qs: {mount}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.not.have.property('current');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('non-minimal dependencies should be available', () => {
FoxxManager.install(depPath, mount);
const resp = request.get('/_api/foxx/dependencies', {qs: {mount, minimal: false}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.not.have.property('current');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('minimal dependencies should be available', () => {
FoxxManager.install(depPath, mount);
const resp = request.get('/_api/foxx/dependencies', {qs: {mount, minimal: true}});
expect(resp.status).to.equal(200);
expect(resp.json).to.eql({});
});
it('dependencies should be available after update', () => {
FoxxManager.install(depPath, mount);
const updateResp = request.patch('/_api/foxx/dependencies', {
qs: {
mount
},
body: {
test1: '/test'
},
json: true
});
expect(updateResp.status).to.equal(200);
expect(updateResp.json).to.have.property('values');
expect(updateResp.json.values).to.have.property('test1', '/test');
expect(updateResp.json.values).not.to.have.property('test2');
expect(updateResp.json).to.not.have.property('warnings');
const resp = request.get('/_api/foxx/dependencies', {qs: {mount}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', '/test');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('non-minimal dependencies should be available after update', () => {
FoxxManager.install(depPath, mount);
const updateResp = request.patch('/_api/foxx/dependencies', {
qs: {
mount,
minimal: false
},
body: {
test1: '/test'
},
json: true
});
expect(updateResp.status).to.equal(200);
expect(updateResp.json).to.have.property('test1');
expect(updateResp.json.test1).to.have.property('current', '/test');
expect(updateResp.json.test1).to.not.have.property('warning');
expect(updateResp.json).to.have.property('test2');
expect(updateResp.json.test2).to.not.have.property('current');
expect(updateResp.json.test2).to.not.have.property('warning');
const resp = request.get('/_api/foxx/dependencies', {qs: {mount, minimal: false}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', '/test');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('minimal dependencies should be available after update', () => {
FoxxManager.install(depPath, mount);
const updateResp = request.patch('/_api/foxx/dependencies', {
qs: {
mount,
minimal: true
},
body: {
test1: '/test'
},
json: true
});
expect(updateResp.status).to.equal(200);
expect(updateResp.json).to.have.property('values');
expect(updateResp.json.values).to.have.property('test1', '/test');
expect(updateResp.json.values).not.to.have.property('test2');
expect(updateResp.json).to.not.have.property('warnings');
const resp = request.get('/_api/foxx/dependencies', {qs: {mount, minimal: true}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1', '/test');
expect(resp.json).to.not.have.property('test2');
});
it('dependencies should be available after replace', () => {
FoxxManager.install(depPath, mount);
const replaceResp = request.put('/_api/foxx/dependencies', {
qs: {
mount
},
body: {
test1: '/test'
},
json: true
});
expect(replaceResp.status).to.equal(200);
expect(replaceResp.json).to.have.property('values');
expect(replaceResp.json.values).to.have.property('test1', '/test');
expect(replaceResp.json.values).to.not.have.property('test2');
expect(replaceResp.json).to.have.property('warnings');
expect(replaceResp.json.warnings).to.have.property('test2', 'is required');
const resp = request.get('/_api/foxx/dependencies', {qs: {mount}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', '/test');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('non-minimal dependencies should be available after replace', () => {
FoxxManager.install(depPath, mount);
const replaceResp = request.put('/_api/foxx/dependencies', {
qs: {
mount,
minimal: false
},
body: {
test1: '/test'
},
json: true
});
expect(replaceResp.status).to.equal(200);
expect(replaceResp.json).to.have.property('test1');
expect(replaceResp.json.test1).to.have.property('current', '/test');
expect(replaceResp.json.test1).to.not.have.property('warning');
expect(replaceResp.json).to.have.property('test2');
expect(replaceResp.json.test2).to.not.have.property('current');
expect(replaceResp.json.test2).to.have.property('warning', 'is required');
const resp = request.get('/_api/foxx/dependencies', {qs: {mount, minimal: false}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', '/test');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('minimal dependencies should be available after replace', () => {
FoxxManager.install(depPath, mount);
const replaceResp = request.put('/_api/foxx/dependencies', {
qs: {
mount,
minimal: true
},
body: {
test1: '/test'
},
json: true
});
expect(replaceResp.status).to.equal(200);
expect(replaceResp.json).to.have.property('values');
expect(replaceResp.json.values).to.have.property('test1', '/test');
expect(replaceResp.json.values).to.not.have.property('test2');
expect(replaceResp.json).to.have.property('warnings');
expect(replaceResp.json.warnings).to.have.property('test2', 'is required');
const resp = request.get('/_api/foxx/dependencies', {qs: {mount, minimal: true}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1', '/test');
expect(resp.json).to.not.have.property('test2');
});
it('dependencies should be merged after update', () => {
FoxxManager.install(depPath, mount);
const replaceResp = request.put('/_api/foxx/dependencies', {
qs: {
mount
},
body: {
test2: '/test2'
},
json: true
});
expect(replaceResp.status).to.equal(200);
expect(replaceResp.json).to.have.property('values');
expect(replaceResp.json.values).to.not.have.property('test1');
expect(replaceResp.json.values).to.have.property('test2', '/test2');
expect(replaceResp.json).to.have.property('warnings');
expect(replaceResp.json.warnings).to.have.property('test1', 'is required');
const updateResp = request.patch('/_api/foxx/dependencies', {
qs: {
mount
},
body: {
test1: '/test1'
},
json: true
});
expect(updateResp.status).to.equal(200);
expect(updateResp.json).to.have.property('values');
expect(updateResp.json.values).to.have.property('test1', '/test1');
expect(updateResp.json.values).to.have.property('test2', '/test2');
const resp = request.get('/_api/foxx/dependencies', {qs: {mount}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', '/test1');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.have.property('current', '/test2');
});
it('non-minimal dependencies should be merged after update', () => {
FoxxManager.install(depPath, mount);
const replaceResp = request.put('/_api/foxx/dependencies', {
qs: {
mount,
minimal: false
},
body: {
test2: '/test2'
},
json: true
});
expect(replaceResp.status).to.equal(200);
expect(replaceResp.json).to.have.property('test1');
expect(replaceResp.json.test1).to.have.property('warning', 'is required');
expect(replaceResp.json).to.have.property('test2');
expect(replaceResp.json.test2).to.have.property('current', '/test2');
const updateResp = request.patch('/_api/foxx/dependencies', {
qs: {
mount,
minimal: false
},
body: {
test1: '/test1'
},
json: true
});
expect(updateResp.status).to.equal(200);
expect(updateResp.json).to.have.property('test1');
expect(updateResp.json.test1).to.have.property('current', '/test1');
expect(updateResp.json.test1).to.not.have.property('warning');
expect(updateResp.json).to.have.property('test2');
expect(updateResp.json.test2).to.have.property('current', '/test2');
expect(updateResp.json.test2).to.not.have.property('warning');
const resp = request.get('/_api/foxx/dependencies', {qs: {mount, minimal: false}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', '/test1');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.have.property('current', '/test2');
});
it('minimal dependencies should be merged after update', () => {
FoxxManager.install(depPath, mount);
const replaceResp = request.put('/_api/foxx/dependencies', {
qs: {
mount,
minimal: true
},
body: {
test2: '/test2'
},
json: true
});
expect(replaceResp.status).to.equal(200);
expect(replaceResp.json).to.have.property('values');
expect(replaceResp.json.values).to.have.property('test2', '/test2');
expect(replaceResp.json.values).to.not.have.property('test1');
expect(replaceResp.json).to.have.property('warnings');
expect(replaceResp.json.warnings).to.have.property('test1', 'is required');
const updateResp = request.patch('/_api/foxx/dependencies', {
qs: {
mount,
minimal: true
},
body: {
test1: '/test1'
},
json: true
});
expect(updateResp.status).to.equal(200);
expect(updateResp.json).to.have.property('values');
expect(updateResp.json.values).to.have.property('test1', '/test1');
expect(updateResp.json.values).to.have.property('test2', '/test2');
const resp = request.get('/_api/foxx/dependencies', {qs: {mount, minimal: true}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1', '/test1');
expect(resp.json).to.have.property('test2', '/test2');
});
it('dependencies should be overwritten after replace', () => {
FoxxManager.install(depPath, mount);
const updateResp = request.patch('/_api/foxx/dependencies', {
qs: {
mount
},
body: {
test2: '/test2'
},
json: true
});
expect(updateResp.status).to.equal(200);
expect(updateResp.json).to.have.property('values');
expect(updateResp.json).to.not.have.property('warnings');
expect(updateResp.json.values).to.have.property('test2', '/test2');
expect(updateResp.json.values).to.not.have.property('test1');
const replaceResp = request.put('/_api/foxx/dependencies', {
qs: {
mount
},
body: {
test1: '/test'
},
json: true
});
expect(replaceResp.status).to.equal(200);
expect(replaceResp.json).to.have.property('values');
expect(replaceResp.json.values).to.have.property('test1', '/test');
expect(replaceResp.json.values).to.not.have.property('test2');
expect(replaceResp.json).to.have.property('warnings');
expect(replaceResp.json.warnings).to.have.property('test2', 'is required');
const resp = request.get('/_api/foxx/dependencies', {qs: {mount}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', '/test');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('non-minimal dependencies should be overwritten after replace', () => {
FoxxManager.install(depPath, mount);
const updateResp = request.patch('/_api/foxx/dependencies', {
qs: {
mount,
minimal: false
},
body: {
test2: '/test2'
},
json: true
});
expect(updateResp.status).to.equal(200);
expect(updateResp.json).to.have.property('test1');
expect(updateResp.json.test1).to.not.have.property('current');
expect(updateResp.json.test1).to.not.have.property('warning');
expect(updateResp.json).to.have.property('test2');
expect(updateResp.json.test2).to.have.property('current', '/test2');
expect(updateResp.json.test2).to.not.have.property('warning');
const replaceResp = request.put('/_api/foxx/dependencies', {
qs: {
mount,
minimal: false
},
body: {
test1: '/test'
},
json: true
});
expect(replaceResp.status).to.equal(200);
expect(replaceResp.json).to.have.property('test1');
expect(replaceResp.json.test1).to.have.property('current', '/test');
expect(replaceResp.json.test1).to.not.have.property('warning');
expect(replaceResp.json.test2).to.not.have.property('current');
expect(replaceResp.json.test2).to.have.property('warning', 'is required');
const resp = request.get('/_api/foxx/dependencies', {qs: {mount, minimal: false}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1');
expect(resp.json.test1).to.have.property('current', '/test');
expect(resp.json).to.have.property('test2');
expect(resp.json.test2).to.not.have.property('current');
});
it('minimal dependencies should be overwritten after replace', () => {
FoxxManager.install(depPath, mount);
const updateResp = request.patch('/_api/foxx/dependencies', {
qs: {
mount,
minimal: true
},
body: {
test2: '/test2'
},
json: true
});
expect(updateResp.status).to.equal(200);
expect(updateResp.json).to.have.property('values');
expect(updateResp.json).to.not.have.property('warnings');
expect(updateResp.json.values).to.have.property('test2', '/test2');
expect(updateResp.json.values).to.not.have.property('test1');
const replaceResp = request.put('/_api/foxx/dependencies', {
qs: {
mount,
minimal: true
},
body: {
test1: '/test'
},
json: true
});
expect(replaceResp.status).to.equal(200);
expect(replaceResp.json).to.have.property('values');
expect(replaceResp.json.values).to.have.property('test1', '/test');
expect(replaceResp.json.values).to.not.have.property('test2');
expect(replaceResp.json).to.have.property('warnings');
expect(replaceResp.json.warnings).to.have.property('test2', 'is required');
const resp = request.get('/_api/foxx/dependencies', {qs: {mount, minimal: true}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('test1', '/test');
expect(resp.json).to.not.have.property('test2');
});
it('should be downloadable', () => {
FoxxManager.install(basePath, mount);
const resp = request.post('/_api/foxx/download', {
qs: {mount},
encoding: null
});
expect(resp.status).to.equal(200);
expect(resp.headers['content-type']).to.equal('application/zip');
expect(util.isZipBuffer(resp.body)).to.equal(true);
});
const readmePath = path.resolve(internal.startupPath, 'common', 'test-data', 'apps', 'with-readme');
it('should deliver the readme', () => {
FoxxManager.install(readmePath, mount);
const resp = request.get('/_api/foxx/readme', {qs: {mount}});
expect(resp.status).to.equal(200);
expect(resp.headers['content-type']).to.equal('text/plain; charset=utf-8');
expect(resp.body).to.equal('Please read this.');
});
it('should indicate a missing readme', () => {
FoxxManager.install(basePath, mount);
const resp = request.get('/_api/foxx/readme', {qs: {mount}});
expect(resp.status).to.equal(204);
expect(resp.body).to.equal('');
});
it('should provide a swagger description', () => {
FoxxManager.install(basePath, mount);
const resp = request.get('/_api/foxx/swagger', {qs: {mount}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('swagger', '2.0');
expect(resp.json).to.have.property('basePath', `/_db/${db._name()}${mount}`);
expect(resp.json).to.have.property('info');
expect(resp.json.info).to.have.property('title', 'minimal-working-manifest');
expect(resp.json.info).to.have.property('description', '');
expect(resp.json.info).to.have.property('version', '0.0.0');
expect(resp.json.info).to.have.property('license');
expect(resp.json).to.have.property('paths');
expect(resp.json.paths).to.have.property('/');
expect(resp.json.paths['/']).to.have.property('get');
});
it('list should allow excluding system services', () => {
FoxxManager.install(basePath, mount);
const withSystem = request.get('/_api/foxx');
const withoutSystem = request.get('/_api/foxx', {qs: {excludeSystem: true}});
const numSystemWithSystem = withSystem.json.map(service => service.mount).filter(mount => mount.startsWith('/_')).length;
const numSystemWithoutSystem = withoutSystem.json.map(service => service.mount).filter(mount => mount.startsWith('/_')).length;
expect(numSystemWithSystem).to.above(0);
expect(numSystemWithSystem).to.equal(withSystem.json.length - withoutSystem.json.length);
expect(numSystemWithoutSystem).to.equal(0);
});
it('should be contained in service list', () => {
FoxxManager.install(basePath, mount);
const resp = request.get('/_api/foxx');
const service = resp.json.find(service => service.mount === mount);
expect(service).to.have.property('name', 'minimal-working-manifest');
expect(service).to.have.property('version', '0.0.0');
expect(service).to.have.property('provides');
expect(service.provides).to.eql({});
expect(service).to.have.property('development', false);
expect(service).to.have.property('legacy', false);
});
it('informations should be returned', () => {
FoxxManager.install(basePath, mount);
const resp = request.get('/_api/foxx/service', {qs: {mount}});
const service = resp.json;
expect(service).to.have.property('mount', mount);
expect(service).to.have.property('name', 'minimal-working-manifest');
expect(service).to.have.property('version', '0.0.0');
expect(service).to.have.property('development', false);
expect(service).to.have.property('legacy', false);
expect(service).to.have.property('manifest');
expect(service.manifest).to.be.an('object');
expect(service).to.have.property('options');
expect(service.options).to.be.an('object');
expect(service).to.have.property('checksum');
expect(service.checksum).to.be.a('string');
});
const scriptPath = path.resolve(internal.startupPath, 'common', 'test-data', 'apps', 'minimal-working-setup-teardown');
it('list of scripts should be available', () => {
FoxxManager.install(scriptPath, mount);
const resp = request.get('/_api/foxx/scripts', {qs: {mount}});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('setup', 'Setup');
expect(resp.json).to.have.property('teardown', 'Teardown');
});
it('script should be available', () => {
FoxxManager.install(scriptPath, mount);
const col = `${mount}_setup_teardown`.replace(/\//, '').replace(/-/g, '_');
expect(db._collection(col)).to.be.an('object');
const resp = request.post('/_api/foxx/scripts/teardown', {
qs: {mount},
body: {},
json: true
});
expect(resp.status).to.equal(200);
db._flushCache();
expect(db._collection(col)).to.equal(null);
});
it('non-existing script should not be available', () => {
FoxxManager.install(scriptPath, mount);
const resp = request.post('/_api/foxx/scripts/no', {
qs: {mount},
body: {},
json: true
});
expect(resp.status).to.equal(400);
});
const echoPath = path.resolve(internal.startupPath, 'common', 'test-data', 'apps', 'echo-script');
it('should pass argv to script and return exports', () => {
FoxxManager.install(echoPath, mount);
const argv = {hello: 'world'};
const resp = request.post('/_api/foxx/scripts/echo', {
qs: {mount},
body: argv,
json: true
});
expect(resp.json).to.eql([argv]);
});
it('should treat array script argv like any other script argv', () => {
FoxxManager.install(echoPath, mount);
const argv = ['yes', 'please'];
const resp = request.post('/_api/foxx/scripts/echo', {
qs: {mount},
body: argv,
json: true
});
expect(resp.json).to.eql([argv]);
});
it('set devmode should enable devmode', () => {
FoxxManager.install(basePath, mount);
const resp = request.get('/_api/foxx/service', {
qs: {mount},
json: true
});
expect(resp.json.development).to.equal(false);
const devResp = request.post('/_api/foxx/development', {
qs: {mount},
json: true
});
expect(devResp.json.development).to.equal(true);
const respAfter = request.get('/_api/foxx/service', {
qs: {mount},
json: true
});
expect(respAfter.json.development).to.equal(true);
});
it('clear devmode should disable devmode', () => {
FoxxManager.install(basePath, mount, {development: true});
const resp = request.get('/_api/foxx/service', {
qs: {mount},
json: true
});
expect(resp.json.development).to.equal(true);
const devResp = request.delete('/_api/foxx/development', {
qs: {mount},
json: true
});
expect(devResp.json.development).to.equal(false);
const respAfter = request.get('/_api/foxx/service', {
qs: {mount},
json: true
});
expect(respAfter.json.development).to.equal(false);
});
const routes = [
['GET', '/_api/foxx/service'],
['PATCH', '/_api/foxx/service', { source: servicePath }],
['PUT', '/_api/foxx/service', { source: servicePath }],
['DELETE', '/_api/foxx/service'],
['GET', '/_api/foxx/configuration'],
['PATCH', '/_api/foxx/configuration'],
['PUT', '/_api/foxx/configuration'],
['GET', '/_api/foxx/dependencies'],
['PATCH', '/_api/foxx/dependencies'],
['PUT', '/_api/foxx/dependencies'],
['POST', '/_api/foxx/development'],
['DELETE', '/_api/foxx/development'],
['GET', '/_api/foxx/scripts'],
['POST', '/_api/foxx/scripts/xxx'],
['POST', '/_api/foxx/tests'],
['POST', '/_api/foxx/download'],
['GET', '/_api/foxx/readme'],
['GET', '/_api/foxx/swagger']
];
for (const [method, url, body] of routes) {
it(`should return 400 when mount is omitted for ${method} ${url}`, () => {
const resp = request({
method,
url,
body,
json: true
});
expect(resp.status).to.equal(400);
});
it(`should return 400 when mount is unknown for ${method} ${url}`, () => {
const resp = request({
method,
url,
qs: {mount: '/dev/null'},
body,
json: true
});
expect(resp.status).to.equal(400);
});
}
it('tests should run', () => {
const testPath = path.resolve(internal.startupPath, 'common', 'test-data', 'apps', 'with-tests');
FoxxManager.install(testPath, mount);
const resp = request.post('/_api/foxx/tests', {qs: { mount }});
expect(resp.status).to.equal(200);
expect(resp.json).to.have.property('stats');
expect(resp.json).to.have.property('tests');
expect(resp.json).to.have.property('pending');
expect(resp.json).to.have.property('failures');
expect(resp.json).to.have.property('passes');
});
it('replace on invalid mount should not be installed', () => {
const replaceResp = request.put('/_api/foxx/service', {
qs: {
mount
},
body: {
source: servicePath
},
json: true
});
expect(replaceResp.status).to.equal(400);
const resp = request.get(mount);
expect(resp.status).to.equal(404);
});
it('replace on invalid mount should be installed when forced', () => {
const replaceResp = request.put('/_api/foxx/service', {
qs: {
mount,
force: true
},
body: {
source: servicePath
},
json: true
});
expect(replaceResp.status).to.equal(200);
const resp = request.get(mount);
expect(resp.status).to.equal(200);
expect(resp.json).to.eql({hello: 'world'});
});
});