navy 6.0.0 → 7.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/__tests__/config-provider.js +75 -0
- package/lib/__tests__/config.js +130 -0
- package/lib/__tests__/driver-logging.js +148 -0
- package/lib/__tests__/driver.js +19 -0
- package/lib/__tests__/errors.js +49 -0
- package/lib/__tests__/http-proxy.js +214 -0
- package/lib/__tests__/index.js +25 -0
- package/lib/__tests__/service.js +16 -0
- package/lib/cli/__tests__/develop.js +239 -0
- package/lib/cli/__tests__/external-ip.js +68 -0
- package/lib/cli/__tests__/health.js +257 -0
- package/lib/cli/__tests__/https.js +210 -0
- package/lib/cli/__tests__/import.js +110 -0
- package/lib/cli/__tests__/index.js +118 -0
- package/lib/cli/__tests__/lan-ip.js +90 -0
- package/lib/cli/__tests__/launch.js +179 -0
- package/lib/cli/__tests__/live.js +155 -0
- package/lib/cli/__tests__/local-ip.js +72 -0
- package/lib/cli/__tests__/logs.js +52 -0
- package/lib/cli/__tests__/open.js +65 -0
- package/lib/cli/__tests__/program.js +472 -0
- package/lib/cli/__tests__/ps.js +345 -0
- package/lib/cli/__tests__/refresh-config.js +95 -0
- package/lib/cli/__tests__/run.js +54 -0
- package/lib/cli/__tests__/status.js +204 -0
- package/lib/cli/__tests__/updates.js +243 -0
- package/lib/cli/__tests__/wait-for-healthy.js +134 -0
- package/lib/cli/config/__tests__/index.js +275 -0
- package/lib/cli/config/__tests__/wrapper.js +53 -0
- package/lib/cli/config/index.js +19 -37
- package/lib/cli/config/wrapper.js +0 -6
- package/lib/cli/develop.js +7 -21
- package/lib/cli/doctor/__tests__/clean-compose-files.js +78 -0
- package/lib/cli/doctor/__tests__/index.js +67 -0
- package/lib/cli/doctor/__tests__/invalid-compose-config.js +103 -0
- package/lib/cli/doctor/__tests__/invalid-state.js +83 -0
- package/lib/cli/doctor/__tests__/util.js +91 -0
- package/lib/cli/doctor/clean-compose-files.js +5 -13
- package/lib/cli/doctor/index.js +0 -12
- package/lib/cli/doctor/invalid-compose-config.js +0 -4
- package/lib/cli/doctor/invalid-state.js +0 -6
- package/lib/cli/doctor/util.js +0 -10
- package/lib/cli/external-ip.js +0 -4
- package/lib/cli/health.js +0 -12
- package/lib/cli/https.js +9 -25
- package/lib/cli/import.js +0 -12
- package/lib/cli/index.js +0 -9
- package/lib/cli/lan-ip.js +2 -8
- package/lib/cli/launch.js +0 -9
- package/lib/cli/live.js +6 -16
- package/lib/cli/local-ip.js +2 -7
- package/lib/cli/logs.js +0 -3
- package/lib/cli/open.js +2 -7
- package/lib/cli/program.js +73 -101
- package/lib/cli/ps.js +1 -21
- package/lib/cli/refresh-config.js +0 -7
- package/lib/cli/run.js +0 -3
- package/lib/cli/status.js +0 -11
- package/lib/cli/updates.js +0 -22
- package/lib/cli/util/__tests__/get-or-initialise-navy.js +66 -0
- package/lib/cli/util/__tests__/import.js +123 -0
- package/lib/cli/util/__tests__/index.js +17 -0
- package/lib/cli/util/__tests__/merge-action-options.js +47 -0
- package/lib/cli/util/__tests__/reconfigure.js +78 -0
- package/lib/cli/util/get-or-initialise-navy.js +0 -7
- package/lib/cli/util/import.js +0 -9
- package/lib/cli/util/index.js +0 -2
- package/lib/cli/util/merge-action-options.js +20 -0
- package/lib/cli/util/reconfigure.js +0 -4
- package/lib/cli/wait-for-healthy.js +0 -21
- package/lib/client/registry/__tests__/get-credentials.js +62 -0
- package/lib/client/registry/__tests__/get-endpoint.js +124 -0
- package/lib/client/registry/__tests__/get-fat-manifest.js +67 -0
- package/lib/client/registry/__tests__/get-token.js +66 -0
- package/lib/client/registry/__tests__/helpers.js +26 -0
- package/lib/client/registry/get-credentials.js +3 -9
- package/lib/client/registry/get-endpoint.js +29 -63
- package/lib/client/registry/get-fat-manifest.js +2 -9
- package/lib/client/registry/get-token.js +2 -13
- package/lib/client/registry/helpers.js +0 -4
- package/lib/config-provider.js +0 -12
- package/lib/config-providers/filesystem/__tests__/index.js +176 -0
- package/lib/config-providers/filesystem/index.js +5 -23
- package/lib/config-providers/npm/__tests__/index.js +226 -0
- package/lib/config-providers/npm/__tests__/util.js +1 -2
- package/lib/config-providers/npm/index.js +12 -35
- package/lib/config-providers/npm/util.js +0 -3
- package/lib/config.js +4 -19
- package/lib/domain/__tests__/container-image.js +81 -0
- package/lib/domain/__tests__/oci-api-specification.js +23 -0
- package/lib/domain/container-image.js +8 -21
- package/lib/domain/oci-api-specification.js +3 -5
- package/lib/driver-logging.js +0 -19
- package/lib/driver.js +0 -4
- package/lib/drivers/docker-compose/__tests__/client.js +249 -0
- package/lib/drivers/docker-compose/__tests__/index.js +430 -0
- package/lib/drivers/docker-compose/client.js +0 -16
- package/lib/drivers/docker-compose/index.js +7 -49
- package/lib/errors.js +0 -10
- package/lib/http-proxy.js +28 -23
- package/lib/index.js +1 -9
- package/lib/middleware/__tests__/add-service-proxy-config.js +258 -0
- package/lib/middleware/__tests__/develop.js +120 -0
- package/lib/middleware/__tests__/helpers.js +154 -0
- package/lib/middleware/__tests__/port-override.js +125 -0
- package/lib/middleware/__tests__/set-env-vars.js +94 -0
- package/lib/middleware/__tests__/set-image.js +76 -0
- package/lib/middleware/__tests__/set-logging-driver.js +94 -0
- package/lib/middleware/__tests__/tag-override.js +92 -0
- package/lib/middleware/add-service-proxy-config.js +8 -16
- package/lib/middleware/develop.js +2 -5
- package/lib/middleware/helpers.js +6 -12
- package/lib/middleware/port-override.js +5 -8
- package/lib/middleware/set-env-vars.js +6 -6
- package/lib/middleware/set-image.js +4 -5
- package/lib/middleware/set-logging-driver.js +6 -6
- package/lib/middleware/tag-override.js +4 -6
- package/lib/navy/__tests__/default-middleware.js +40 -0
- package/lib/navy/__tests__/index.js +1612 -0
- package/lib/navy/__tests__/middleware.js +71 -0
- package/lib/navy/__tests__/plugin-interface.js +121 -0
- package/lib/navy/__tests__/state.js +103 -0
- package/lib/navy/__tests__/util.js +24 -0
- package/lib/navy/default-middleware.js +0 -10
- package/lib/navy/index.js +83 -138
- package/lib/navy/middleware.js +0 -6
- package/lib/navy/plugin-interface.js +2 -10
- package/lib/navy/state.js +12 -24
- package/lib/navy/util.js +0 -1
- package/lib/service.js +2 -3
- package/lib/util/__tests__/exec-async.js +83 -0
- package/lib/util/__tests__/external-ip.js +97 -2
- package/lib/util/__tests__/get-lan-ip.js +46 -0
- package/lib/util/__tests__/has-update.js +136 -0
- package/lib/util/__tests__/https.js +301 -0
- package/lib/util/__tests__/navyrc.js +45 -0
- package/lib/util/__tests__/service-host.js +63 -5
- package/lib/util/__tests__/table.js +44 -0
- package/lib/util/docker-client.js +2 -10
- package/lib/util/exec-async.js +0 -4
- package/lib/util/external-ip.js +8 -12
- package/lib/util/fs.js +1 -6
- package/lib/util/get-lan-ip.js +0 -5
- package/lib/util/has-update.js +2 -14
- package/lib/util/https.js +11 -55
- package/lib/util/navyrc.js +0 -5
- package/lib/util/service-host.js +0 -17
- package/lib/util/table.js +0 -6
- package/package.json +14 -13
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _chai = require("chai");
|
|
5
|
+
var _sinon = _interopRequireDefault(require("sinon"));
|
|
6
|
+
var _proxyquire = _interopRequireDefault(require("proxyquire"));
|
|
7
|
+
var _errors = require("../../errors");
|
|
8
|
+
/* eslint-env mocha */
|
|
9
|
+
|
|
10
|
+
describe('cli/program', function () {
|
|
11
|
+
let sandbox;
|
|
12
|
+
let fakeProgram;
|
|
13
|
+
let actionsByCommand;
|
|
14
|
+
let getConfigStub;
|
|
15
|
+
let startDriverLoggingStub;
|
|
16
|
+
let stopDriverLoggingStub;
|
|
17
|
+
let getImportCommandLineOptionsStub;
|
|
18
|
+
let getNavyStub;
|
|
19
|
+
let navyStub;
|
|
20
|
+
let consoleLogStub;
|
|
21
|
+
let consoleErrorStub;
|
|
22
|
+
let processExitStub;
|
|
23
|
+
let processOnStub;
|
|
24
|
+
let originalEnvName;
|
|
25
|
+
let helpHandlersByCommand;
|
|
26
|
+
function loadModule() {
|
|
27
|
+
actionsByCommand = {};
|
|
28
|
+
helpHandlersByCommand = {};
|
|
29
|
+
fakeProgram = {
|
|
30
|
+
option: sandbox.stub().returnsThis(),
|
|
31
|
+
command(spec) {
|
|
32
|
+
const name = spec.split(' ')[0];
|
|
33
|
+
const cmd = {
|
|
34
|
+
option: sandbox.stub().returnsThis(),
|
|
35
|
+
description: sandbox.stub().returnsThis(),
|
|
36
|
+
action(handler) {
|
|
37
|
+
actionsByCommand[name] = handler;
|
|
38
|
+
return cmd;
|
|
39
|
+
},
|
|
40
|
+
on(event, handler) {
|
|
41
|
+
if (event === '--help') {
|
|
42
|
+
helpHandlersByCommand[name] = handler;
|
|
43
|
+
}
|
|
44
|
+
return cmd;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
return cmd;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
return _proxyquire.default.noCallThru()('../program', {
|
|
51
|
+
commander: {
|
|
52
|
+
program: fakeProgram
|
|
53
|
+
},
|
|
54
|
+
'../errors': {
|
|
55
|
+
NavyError: _errors.NavyError
|
|
56
|
+
},
|
|
57
|
+
'../config': {
|
|
58
|
+
getConfig: getConfigStub
|
|
59
|
+
},
|
|
60
|
+
'../driver-logging': {
|
|
61
|
+
startDriverLogging: startDriverLoggingStub,
|
|
62
|
+
stopDriverLogging: stopDriverLoggingStub
|
|
63
|
+
},
|
|
64
|
+
'../config-provider': {
|
|
65
|
+
getImportCommandLineOptions: getImportCommandLineOptionsStub
|
|
66
|
+
},
|
|
67
|
+
'../navy': {
|
|
68
|
+
getNavy: getNavyStub
|
|
69
|
+
},
|
|
70
|
+
'./import': () => Promise.resolve('imported'),
|
|
71
|
+
'./launch': () => Promise.resolve('launched'),
|
|
72
|
+
'./ps': () => Promise.resolve(undefined),
|
|
73
|
+
'./updates': () => Promise.resolve(undefined),
|
|
74
|
+
'./logs': () => Promise.resolve(undefined),
|
|
75
|
+
'./health': () => Promise.resolve(undefined),
|
|
76
|
+
'./wait-for-healthy': () => Promise.resolve(undefined),
|
|
77
|
+
'./https': () => Promise.resolve(undefined),
|
|
78
|
+
'./open': () => Promise.resolve(undefined),
|
|
79
|
+
'./develop': () => Promise.resolve(undefined),
|
|
80
|
+
'./live': () => Promise.resolve(undefined),
|
|
81
|
+
'./run': () => Promise.resolve(undefined),
|
|
82
|
+
'./refresh-config': () => Promise.resolve(undefined),
|
|
83
|
+
'./status': () => Promise.resolve(undefined),
|
|
84
|
+
'./doctor': () => Promise.resolve(undefined),
|
|
85
|
+
'./config/wrapper': () => Promise.resolve(undefined),
|
|
86
|
+
'./external-ip': () => Promise.resolve(undefined),
|
|
87
|
+
'./lan-ip': () => Promise.resolve(undefined),
|
|
88
|
+
'./local-ip': () => Promise.resolve(undefined)
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
beforeEach(function () {
|
|
92
|
+
sandbox = _sinon.default.createSandbox();
|
|
93
|
+
getConfigStub = sandbox.stub().returns({
|
|
94
|
+
defaultNavy: 'dev'
|
|
95
|
+
});
|
|
96
|
+
startDriverLoggingStub = sandbox.stub();
|
|
97
|
+
stopDriverLoggingStub = sandbox.stub();
|
|
98
|
+
getImportCommandLineOptionsStub = sandbox.stub().returns([['-c, --config-provider [provider]', 'Config provider to use']]);
|
|
99
|
+
navyStub = {
|
|
100
|
+
ensurePluginsLoaded: sandbox.stub().resolves(),
|
|
101
|
+
emitAsync: sandbox.stub().resolves(),
|
|
102
|
+
destroy: sandbox.stub().resolves(),
|
|
103
|
+
kill: sandbox.stub().resolves(),
|
|
104
|
+
start: sandbox.stub().resolves(),
|
|
105
|
+
stop: sandbox.stub().resolves(),
|
|
106
|
+
url: sandbox.stub().resolves('http://web'),
|
|
107
|
+
getAvailableServiceNames: sandbox.stub().resolves(['web', 'api'])
|
|
108
|
+
};
|
|
109
|
+
getNavyStub = sandbox.stub().returns(navyStub);
|
|
110
|
+
consoleLogStub = sandbox.stub(console, 'log');
|
|
111
|
+
consoleErrorStub = sandbox.stub(console, 'error');
|
|
112
|
+
processExitStub = sandbox.stub(process, 'exit');
|
|
113
|
+
processOnStub = sandbox.stub(process, 'on');
|
|
114
|
+
originalEnvName = process.env.NAVY_NAME;
|
|
115
|
+
});
|
|
116
|
+
afterEach(function () {
|
|
117
|
+
if (originalEnvName === undefined) {
|
|
118
|
+
delete process.env.NAVY_NAME;
|
|
119
|
+
} else {
|
|
120
|
+
process.env.NAVY_NAME = originalEnvName;
|
|
121
|
+
}
|
|
122
|
+
sandbox.restore();
|
|
123
|
+
});
|
|
124
|
+
describe('module side effects', function () {
|
|
125
|
+
it('should register all known commands on the program', function () {
|
|
126
|
+
loadModule();
|
|
127
|
+
(0, _chai.expect)(actionsByCommand).to.have.keys('import', 'launch', 'destroy', 'delete', 'ps', 'start', 'stop', 'restart', 'kill', 'rm', 'update', 'updates', 'logs', 'health', 'wait-for-healthy', 'use-tag', 'reset-tag', 'https', 'use-port', 'reset-port', 'url', 'open', 'port', 'available-services', 'develop', 'live', 'run', 'refresh-config', 'status', 'doctor', 'config', 'external-ip', 'use-lan-ip', 'use-local-ip');
|
|
128
|
+
});
|
|
129
|
+
it('should derive the default navy from NAVY_NAME env when set', function () {
|
|
130
|
+
process.env.NAVY_NAME = 'foo-env';
|
|
131
|
+
loadModule();
|
|
132
|
+
(0, _chai.expect)(actionsByCommand.import).to.be.a('function');
|
|
133
|
+
});
|
|
134
|
+
it('should fall back to getConfig().defaultNavy when env is not set', function () {
|
|
135
|
+
delete process.env.NAVY_NAME;
|
|
136
|
+
loadModule();
|
|
137
|
+
(0, _chai.expect)(getConfigStub.called).to.equal(true);
|
|
138
|
+
});
|
|
139
|
+
it('should add import command-line options from getImportCommandLineOptions', function () {
|
|
140
|
+
loadModule();
|
|
141
|
+
(0, _chai.expect)(getImportCommandLineOptionsStub.calledOnce).to.equal(true);
|
|
142
|
+
});
|
|
143
|
+
it('should export the program as default', function () {
|
|
144
|
+
const mod = loadModule();
|
|
145
|
+
(0, _chai.expect)(mod).to.equal(fakeProgram);
|
|
146
|
+
});
|
|
147
|
+
it('should print examples when each command --help handler is invoked', function () {
|
|
148
|
+
loadModule();
|
|
149
|
+
Object.keys(helpHandlersByCommand).forEach(name => {
|
|
150
|
+
helpHandlersByCommand[name]();
|
|
151
|
+
});
|
|
152
|
+
(0, _chai.expect)(consoleLogStub.called).to.equal(true);
|
|
153
|
+
});
|
|
154
|
+
it('should register a global -e, --navy option on the root program', function () {
|
|
155
|
+
loadModule();
|
|
156
|
+
(0, _chai.expect)(fakeProgram.option.calledWith('-e, --navy [env]', _sinon.default.match.string, 'dev')).to.equal(true);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
describe('lazyRequire wrapped action', function () {
|
|
160
|
+
it('should pass through arguments to the underlying module', async function () {
|
|
161
|
+
loadModule();
|
|
162
|
+
const result = actionsByCommand.import({
|
|
163
|
+
navy: 'env-1'
|
|
164
|
+
});
|
|
165
|
+
return (0, _chai.expect)(result).to.exist;
|
|
166
|
+
});
|
|
167
|
+
it('should call stopDriverLogging and prettyPrint when the action throws a NavyError', async function () {
|
|
168
|
+
const err = new _errors.NavyError('boom');
|
|
169
|
+
const prettyPrintStub = sandbox.stub(err, 'prettyPrint');
|
|
170
|
+
_proxyquire.default.noCallThru()('../program', {
|
|
171
|
+
commander: {
|
|
172
|
+
program: createCapturingProgram()
|
|
173
|
+
},
|
|
174
|
+
'../errors': {
|
|
175
|
+
NavyError: _errors.NavyError
|
|
176
|
+
},
|
|
177
|
+
'../config': {
|
|
178
|
+
getConfig: getConfigStub
|
|
179
|
+
},
|
|
180
|
+
'../driver-logging': {
|
|
181
|
+
startDriverLogging: startDriverLoggingStub,
|
|
182
|
+
stopDriverLogging: stopDriverLoggingStub
|
|
183
|
+
},
|
|
184
|
+
'../config-provider': {
|
|
185
|
+
getImportCommandLineOptions: getImportCommandLineOptionsStub
|
|
186
|
+
},
|
|
187
|
+
'../navy': {
|
|
188
|
+
getNavy: getNavyStub
|
|
189
|
+
},
|
|
190
|
+
'./import': () => Promise.reject(err),
|
|
191
|
+
'./launch': () => Promise.resolve(),
|
|
192
|
+
'./ps': () => Promise.resolve(),
|
|
193
|
+
'./updates': () => Promise.resolve(),
|
|
194
|
+
'./logs': () => Promise.resolve(),
|
|
195
|
+
'./health': () => Promise.resolve(),
|
|
196
|
+
'./wait-for-healthy': () => Promise.resolve(),
|
|
197
|
+
'./https': () => Promise.resolve(),
|
|
198
|
+
'./open': () => Promise.resolve(),
|
|
199
|
+
'./develop': () => Promise.resolve(),
|
|
200
|
+
'./live': () => Promise.resolve(),
|
|
201
|
+
'./run': () => Promise.resolve(),
|
|
202
|
+
'./refresh-config': () => Promise.resolve(),
|
|
203
|
+
'./status': () => Promise.resolve(),
|
|
204
|
+
'./doctor': () => Promise.resolve(),
|
|
205
|
+
'./config/wrapper': () => Promise.resolve(),
|
|
206
|
+
'./external-ip': () => Promise.resolve(),
|
|
207
|
+
'./lan-ip': () => Promise.resolve(),
|
|
208
|
+
'./local-ip': () => Promise.resolve()
|
|
209
|
+
});
|
|
210
|
+
capturedActions.import({
|
|
211
|
+
navy: 'env-1'
|
|
212
|
+
});
|
|
213
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
214
|
+
(0, _chai.expect)(prettyPrintStub.calledOnce).to.equal(true);
|
|
215
|
+
(0, _chai.expect)(processExitStub.calledWith(1)).to.equal(true);
|
|
216
|
+
(0, _chai.expect)(stopDriverLoggingStub.calledWith({
|
|
217
|
+
success: false
|
|
218
|
+
})).to.equal(true);
|
|
219
|
+
});
|
|
220
|
+
it('should pretty-print invariant violations with troubleshooting hint', async function () {
|
|
221
|
+
const err = new Error('CODE: something went wrong');
|
|
222
|
+
err.name = 'Invariant Violation';
|
|
223
|
+
_proxyquire.default.noCallThru()('../program', {
|
|
224
|
+
commander: {
|
|
225
|
+
program: createCapturingProgram()
|
|
226
|
+
},
|
|
227
|
+
'../errors': {
|
|
228
|
+
NavyError: _errors.NavyError
|
|
229
|
+
},
|
|
230
|
+
'../config': {
|
|
231
|
+
getConfig: getConfigStub
|
|
232
|
+
},
|
|
233
|
+
'../driver-logging': {
|
|
234
|
+
startDriverLogging: startDriverLoggingStub,
|
|
235
|
+
stopDriverLogging: stopDriverLoggingStub
|
|
236
|
+
},
|
|
237
|
+
'../config-provider': {
|
|
238
|
+
getImportCommandLineOptions: getImportCommandLineOptionsStub
|
|
239
|
+
},
|
|
240
|
+
'../navy': {
|
|
241
|
+
getNavy: getNavyStub
|
|
242
|
+
},
|
|
243
|
+
'./import': () => Promise.reject(err),
|
|
244
|
+
'./launch': () => Promise.resolve(),
|
|
245
|
+
'./ps': () => Promise.resolve(),
|
|
246
|
+
'./updates': () => Promise.resolve(),
|
|
247
|
+
'./logs': () => Promise.resolve(),
|
|
248
|
+
'./health': () => Promise.resolve(),
|
|
249
|
+
'./wait-for-healthy': () => Promise.resolve(),
|
|
250
|
+
'./https': () => Promise.resolve(),
|
|
251
|
+
'./open': () => Promise.resolve(),
|
|
252
|
+
'./develop': () => Promise.resolve(),
|
|
253
|
+
'./live': () => Promise.resolve(),
|
|
254
|
+
'./run': () => Promise.resolve(),
|
|
255
|
+
'./refresh-config': () => Promise.resolve(),
|
|
256
|
+
'./status': () => Promise.resolve(),
|
|
257
|
+
'./doctor': () => Promise.resolve(),
|
|
258
|
+
'./config/wrapper': () => Promise.resolve(),
|
|
259
|
+
'./external-ip': () => Promise.resolve(),
|
|
260
|
+
'./lan-ip': () => Promise.resolve(),
|
|
261
|
+
'./local-ip': () => Promise.resolve()
|
|
262
|
+
});
|
|
263
|
+
capturedActions.import({
|
|
264
|
+
navy: 'env-1'
|
|
265
|
+
});
|
|
266
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
267
|
+
const printed = consoleLogStub.getCalls().map(c => c.args[0] || '').join('\n');
|
|
268
|
+
(0, _chai.expect)(printed).to.contain('Invariant Violation');
|
|
269
|
+
(0, _chai.expect)(printed).to.contain('navy doctor');
|
|
270
|
+
(0, _chai.expect)(processExitStub.calledWith(1)).to.equal(true);
|
|
271
|
+
});
|
|
272
|
+
it('should print stack for non-NavyError, non-Invariant errors', async function () {
|
|
273
|
+
const err = new Error('something broke');
|
|
274
|
+
_proxyquire.default.noCallThru()('../program', {
|
|
275
|
+
commander: {
|
|
276
|
+
program: createCapturingProgram()
|
|
277
|
+
},
|
|
278
|
+
'../errors': {
|
|
279
|
+
NavyError: _errors.NavyError
|
|
280
|
+
},
|
|
281
|
+
'../config': {
|
|
282
|
+
getConfig: getConfigStub
|
|
283
|
+
},
|
|
284
|
+
'../driver-logging': {
|
|
285
|
+
startDriverLogging: startDriverLoggingStub,
|
|
286
|
+
stopDriverLogging: stopDriverLoggingStub
|
|
287
|
+
},
|
|
288
|
+
'../config-provider': {
|
|
289
|
+
getImportCommandLineOptions: getImportCommandLineOptionsStub
|
|
290
|
+
},
|
|
291
|
+
'../navy': {
|
|
292
|
+
getNavy: getNavyStub
|
|
293
|
+
},
|
|
294
|
+
'./import': () => Promise.reject(err),
|
|
295
|
+
'./launch': () => Promise.resolve(),
|
|
296
|
+
'./ps': () => Promise.resolve(),
|
|
297
|
+
'./updates': () => Promise.resolve(),
|
|
298
|
+
'./logs': () => Promise.resolve(),
|
|
299
|
+
'./health': () => Promise.resolve(),
|
|
300
|
+
'./wait-for-healthy': () => Promise.resolve(),
|
|
301
|
+
'./https': () => Promise.resolve(),
|
|
302
|
+
'./open': () => Promise.resolve(),
|
|
303
|
+
'./develop': () => Promise.resolve(),
|
|
304
|
+
'./live': () => Promise.resolve(),
|
|
305
|
+
'./run': () => Promise.resolve(),
|
|
306
|
+
'./refresh-config': () => Promise.resolve(),
|
|
307
|
+
'./status': () => Promise.resolve(),
|
|
308
|
+
'./doctor': () => Promise.resolve(),
|
|
309
|
+
'./config/wrapper': () => Promise.resolve(),
|
|
310
|
+
'./external-ip': () => Promise.resolve(),
|
|
311
|
+
'./lan-ip': () => Promise.resolve(),
|
|
312
|
+
'./local-ip': () => Promise.resolve()
|
|
313
|
+
});
|
|
314
|
+
capturedActions.import({
|
|
315
|
+
navy: 'env-1'
|
|
316
|
+
});
|
|
317
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
318
|
+
(0, _chai.expect)(consoleErrorStub.calledWith(err.stack)).to.equal(true);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// NOTE: The internal wrapper in program.js does `if (res.catch)` without
|
|
322
|
+
// null-checking, so passing a non-promise return value would throw. All
|
|
323
|
+
// production action handlers return promises, so this code path is not
|
|
324
|
+
// exercised in practice. We do not test it because asserting that
|
|
325
|
+
// behaviour would lock in a latent bug.
|
|
326
|
+
});
|
|
327
|
+
describe('basicCliWrapper action', function () {
|
|
328
|
+
beforeEach(function () {
|
|
329
|
+
loadModule();
|
|
330
|
+
});
|
|
331
|
+
it('should call the named navy method with the supplied service list', async function () {
|
|
332
|
+
navyStub.start = sandbox.stub().resolves();
|
|
333
|
+
await actionsByCommand.start(['web', 'api'], {
|
|
334
|
+
navy: 'env-1'
|
|
335
|
+
}, {});
|
|
336
|
+
(0, _chai.expect)(navyStub.start.calledOnce).to.equal(true);
|
|
337
|
+
(0, _chai.expect)(navyStub.start.firstCall.args[0]).to.eql(['web', 'api']);
|
|
338
|
+
(0, _chai.expect)(navyStub.ensurePluginsLoaded.calledOnce).to.equal(true);
|
|
339
|
+
});
|
|
340
|
+
it('should merge optsWithGlobals so global navy is used when Commander passes the command', async function () {
|
|
341
|
+
navyStub.start = sandbox.stub().resolves();
|
|
342
|
+
const fakeCommand = {
|
|
343
|
+
optsWithGlobals: () => ({
|
|
344
|
+
navy: 'from-global'
|
|
345
|
+
})
|
|
346
|
+
};
|
|
347
|
+
await actionsByCommand.start(['web'], {
|
|
348
|
+
navy: 'subcommand-default'
|
|
349
|
+
}, fakeCommand);
|
|
350
|
+
(0, _chai.expect)(getNavyStub.firstCall.args[0]).to.equal('from-global');
|
|
351
|
+
});
|
|
352
|
+
it('should pass undefined when called with an empty service list', async function () {
|
|
353
|
+
navyStub.start = sandbox.stub().resolves();
|
|
354
|
+
await actionsByCommand.start([], {
|
|
355
|
+
navy: 'env-1'
|
|
356
|
+
}, {});
|
|
357
|
+
(0, _chai.expect)(navyStub.start.firstCall.args[0]).to.equal(undefined);
|
|
358
|
+
});
|
|
359
|
+
it('should drive logging by default', async function () {
|
|
360
|
+
navyStub.start = sandbox.stub().resolves();
|
|
361
|
+
await actionsByCommand.start(['web'], {
|
|
362
|
+
navy: 'env-1'
|
|
363
|
+
}, {});
|
|
364
|
+
(0, _chai.expect)(startDriverLoggingStub.calledWith('Starting services...')).to.equal(true);
|
|
365
|
+
(0, _chai.expect)(stopDriverLoggingStub.calledOnce).to.equal(true);
|
|
366
|
+
});
|
|
367
|
+
it('should skip driver logging for the url command (driverLogging: false)', async function () {
|
|
368
|
+
navyStub.url = sandbox.stub().resolves('http://web');
|
|
369
|
+
await actionsByCommand.url('web', {
|
|
370
|
+
navy: 'env-1'
|
|
371
|
+
}, {});
|
|
372
|
+
(0, _chai.expect)(startDriverLoggingStub.called).to.equal(false);
|
|
373
|
+
(0, _chai.expect)(stopDriverLoggingStub.called).to.equal(false);
|
|
374
|
+
});
|
|
375
|
+
it('should print arrays joined by newlines', async function () {
|
|
376
|
+
navyStub.getAvailableServiceNames = sandbox.stub().resolves(['web', 'api']);
|
|
377
|
+
await actionsByCommand['available-services']({
|
|
378
|
+
navy: 'env-1'
|
|
379
|
+
}, {});
|
|
380
|
+
(0, _chai.expect)(consoleLogStub.calledWith('web\napi')).to.equal(true);
|
|
381
|
+
});
|
|
382
|
+
it('should print non-null scalar return values', async function () {
|
|
383
|
+
navyStub.url = sandbox.stub().resolves('http://web');
|
|
384
|
+
await actionsByCommand.url('web', {
|
|
385
|
+
navy: 'env-1'
|
|
386
|
+
}, {});
|
|
387
|
+
(0, _chai.expect)(consoleLogStub.calledWith('http://web')).to.equal(true);
|
|
388
|
+
});
|
|
389
|
+
it('should not print when the navy method returns null', async function () {
|
|
390
|
+
navyStub.start = sandbox.stub().resolves(null);
|
|
391
|
+
await actionsByCommand.start(['web'], {
|
|
392
|
+
navy: 'env-1'
|
|
393
|
+
}, {});
|
|
394
|
+
(0, _chai.expect)(consoleLogStub.called).to.equal(false);
|
|
395
|
+
});
|
|
396
|
+
it('should redirect destroy with services to kill via serviceBasedAlias', async function () {
|
|
397
|
+
navyStub.kill = sandbox.stub().resolves();
|
|
398
|
+
await actionsByCommand.destroy('web api', {
|
|
399
|
+
navy: 'env-1'
|
|
400
|
+
}, {});
|
|
401
|
+
(0, _chai.expect)(navyStub.kill.calledOnce).to.equal(true);
|
|
402
|
+
(0, _chai.expect)(navyStub.kill.firstCall.args[0]).to.eql(['web', 'api']);
|
|
403
|
+
const printed = consoleLogStub.getCalls().map(c => c.args[0] || '').join('\n');
|
|
404
|
+
(0, _chai.expect)(printed).to.contain('should not be called with a list');
|
|
405
|
+
});
|
|
406
|
+
it('should emit cli.before.<fn> and cli.after.<fn>', async function () {
|
|
407
|
+
navyStub.start = sandbox.stub().resolves();
|
|
408
|
+
await actionsByCommand.start(['web'], {
|
|
409
|
+
navy: 'env-1'
|
|
410
|
+
}, {});
|
|
411
|
+
const events = navyStub.emitAsync.getCalls().map(c => c.args[0]);
|
|
412
|
+
(0, _chai.expect)(events).to.include('cli.before.start');
|
|
413
|
+
(0, _chai.expect)(events).to.include('cli.after.start');
|
|
414
|
+
});
|
|
415
|
+
it('should register an unhandledRejection handler', async function () {
|
|
416
|
+
navyStub.start = sandbox.stub().resolves();
|
|
417
|
+
await actionsByCommand.start(['web'], {
|
|
418
|
+
navy: 'env-1'
|
|
419
|
+
}, {});
|
|
420
|
+
(0, _chai.expect)(processOnStub.calledWith('unhandledRejection')).to.equal(true);
|
|
421
|
+
});
|
|
422
|
+
describe('unhandledRejection handler', function () {
|
|
423
|
+
it('should pretty-print NavyError and exit', async function () {
|
|
424
|
+
navyStub.start = sandbox.stub().resolves();
|
|
425
|
+
await actionsByCommand.start(['web'], {
|
|
426
|
+
navy: 'env-1'
|
|
427
|
+
}, {});
|
|
428
|
+
const handlers = processOnStub.getCalls().filter(c => c.args[0] === 'unhandledRejection').map(c => c.args[1]);
|
|
429
|
+
const handler = handlers[handlers.length - 1];
|
|
430
|
+
const err = new _errors.NavyError('boom');
|
|
431
|
+
const prettyPrintStub = sandbox.stub(err, 'prettyPrint');
|
|
432
|
+
handler(err);
|
|
433
|
+
(0, _chai.expect)(prettyPrintStub.calledOnce).to.equal(true);
|
|
434
|
+
(0, _chai.expect)(processExitStub.called).to.equal(true);
|
|
435
|
+
});
|
|
436
|
+
it('should print stack for non-NavyError and exit', async function () {
|
|
437
|
+
navyStub.start = sandbox.stub().resolves();
|
|
438
|
+
await actionsByCommand.start(['web'], {
|
|
439
|
+
navy: 'env-1'
|
|
440
|
+
}, {});
|
|
441
|
+
const handlers = processOnStub.getCalls().filter(c => c.args[0] === 'unhandledRejection').map(c => c.args[1]);
|
|
442
|
+
const handler = handlers[handlers.length - 1];
|
|
443
|
+
const err = new Error('boom');
|
|
444
|
+
handler(err);
|
|
445
|
+
(0, _chai.expect)(consoleErrorStub.calledWith(err.stack)).to.equal(true);
|
|
446
|
+
(0, _chai.expect)(processExitStub.called).to.equal(true);
|
|
447
|
+
});
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
// Helper to capture program actions for the failure-path tests
|
|
452
|
+
let capturedActions;
|
|
453
|
+
function createCapturingProgram() {
|
|
454
|
+
capturedActions = {};
|
|
455
|
+
return {
|
|
456
|
+
option: sandbox.stub().returnsThis(),
|
|
457
|
+
command(spec) {
|
|
458
|
+
const name = spec.split(' ')[0];
|
|
459
|
+
const cmd = {
|
|
460
|
+
option: sandbox.stub().returnsThis(),
|
|
461
|
+
description: sandbox.stub().returnsThis(),
|
|
462
|
+
action(handler) {
|
|
463
|
+
capturedActions[name] = handler;
|
|
464
|
+
return cmd;
|
|
465
|
+
},
|
|
466
|
+
on: sandbox.stub().returnsThis()
|
|
467
|
+
};
|
|
468
|
+
return cmd;
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
});
|