1 | 'use strict';
|
2 |
|
3 | const expect = require('chai').expect;
|
4 | const Application = require('../lib/Application');
|
5 | const Method = require('../lib/Method');
|
6 | const Controller = require('../lib/Controller');
|
7 |
|
8 | const DEFAULT_SETTINGS = { adapter: 'express', env: 'development', 'x-powered-by': true };
|
9 |
|
10 | describe('class Application', function() {
|
11 | let app;
|
12 |
|
13 | beforeEach(function() {
|
14 | app = new Application('test', {});
|
15 | });
|
16 |
|
17 | describe('constructor(name, settings)', function() {
|
18 | [
|
19 | ['name', 'test'],
|
20 | ['beforeHooks', {}],
|
21 | ['afterHooks', {}],
|
22 | ['afterErrorHooks', {}],
|
23 | ['settings', DEFAULT_SETTINGS],
|
24 | ['methods', []],
|
25 | ['mountedApps', []],
|
26 | ['locals', { settings: DEFAULT_SETTINGS }],
|
27 | ['mountPath', '/']
|
28 | ].forEach(function(prop) {
|
29 | it(`should have property '${prop[0]}' and corresponding value`, function() {
|
30 | expect(app).to.have.property(prop[0]).deep.eq(prop[1]);
|
31 | });
|
32 | });
|
33 |
|
34 | it('should be a valid instance of Application class', function() {
|
35 | expect(app).to.be.an.instanceof(Application);
|
36 | });
|
37 | });
|
38 |
|
39 | describe('setName(name)', function() {
|
40 | it('should change app name', function() {
|
41 | expect(app).to.have.a.property('name', 'test');
|
42 | app.setName('app');
|
43 | expect(app).to.have.a.property('name', 'app');
|
44 | });
|
45 | });
|
46 |
|
47 | describe('getName()', function() {
|
48 | it('should return app name', function() {
|
49 | expect(app.getName()).to.eq(app.name);
|
50 | });
|
51 | });
|
52 |
|
53 | describe('setMountPath(path)', function() {
|
54 | it('should change app mount path', function() {
|
55 | expect(app).to.have.property('mountPath', '/');
|
56 | app.setMountPath('/my-app');
|
57 | expect(app).to.have.property('mountPath', '/my-app');
|
58 | });
|
59 | });
|
60 |
|
61 | describe('getMountPath()', function() {
|
62 | it('should return app mount path', function() {
|
63 | expect(app.getMountPath()).to.eq(app.mountPath);
|
64 | });
|
65 | });
|
66 |
|
67 | describe('define()', function() {
|
68 | let methodName, methodFn, methodSettings, method;
|
69 |
|
70 | beforeEach(function() {
|
71 | methodName = 'test';
|
72 | methodFn = function() {};
|
73 | methodSettings = {
|
74 | description: 'method description',
|
75 | params: [{ name: 'gender', type: 'string' }],
|
76 | route: { path: 'test', verb: 'post' }
|
77 | };
|
78 | method = new Method(methodName, methodSettings, methodFn);
|
79 | });
|
80 |
|
81 | it('should add app as method parent', function() {
|
82 | app.define(method);
|
83 | expect(app.methods[0]).to.have.property('parent', app);
|
84 | });
|
85 |
|
86 | it('should define a new method and added to app', function() {
|
87 | expect(app).to.have.deep.property('methods.length', 0);
|
88 | app.define(methodName, methodSettings, methodFn);
|
89 | expect(app).to.have.deep.property('methods.length', 1);
|
90 | });
|
91 |
|
92 | it('should add a method instance', function() {
|
93 | expect(app).to.have.deep.property('methods.length', 0);
|
94 | app.define(method);
|
95 | expect(app).to.have.deep.property('methods.length', 1);
|
96 | });
|
97 | });
|
98 |
|
99 | describe('plugin(pluginOrPlugins, options)', function() {
|
100 | it('should accept plugin name for internal plugins', function() {
|
101 | expect(function() {
|
102 | app.plugin('evaluator', {});
|
103 | }).to.not.throw(Error);
|
104 | });
|
105 |
|
106 | it('should invoke one plugin function with options', function() {
|
107 | let pluginInvoked = false;
|
108 | let plugin = function() {
|
109 | pluginInvoked = true;
|
110 | };
|
111 | app.plugin(plugin, {});
|
112 | expect(pluginInvoked).to.be.true;
|
113 | });
|
114 |
|
115 | it('should invoke multiple plugins with options', function() {
|
116 | let pluginInvoked = 0;
|
117 | let plugin = function() {
|
118 | pluginInvoked++;
|
119 | };
|
120 | app.plugin([plugin, plugin, plugin], {});
|
121 | expect(pluginInvoked).to.equal(3);
|
122 | });
|
123 | });
|
124 |
|
125 | describe('clone()', function() {
|
126 | let cloned;
|
127 |
|
128 | beforeEach(function() {
|
129 | app.parent = app;
|
130 |
|
131 | app.define('test', {
|
132 | description: 'test description',
|
133 | params: [{ name: 'name', type: 'string' }]
|
134 | }, function(ctx, next) {
|
135 | next();
|
136 | });
|
137 |
|
138 | app.define('test1', {
|
139 | description: 'test1 description',
|
140 | params: [{ name: 'name', type: 'string' }]
|
141 | }, function(ctx, next) {
|
142 | next();
|
143 | });
|
144 |
|
145 | app.use(app);
|
146 |
|
147 | cloned = app.clone();
|
148 | });
|
149 |
|
150 | [
|
151 | 'parent',
|
152 | 'mountPath',
|
153 | 'settings',
|
154 | 'beforeHooks',
|
155 | 'afterHooks',
|
156 | 'afterErrorHooks',
|
157 | 'locals',
|
158 | 'mountedApps',
|
159 | 'methods'
|
160 | ].forEach(function() {
|
161 |
|
162 | });
|
163 |
|
164 | [
|
165 | 'parent',
|
166 | 'mountPath',
|
167 | 'settings',
|
168 | 'beforeHooks',
|
169 | 'afterHooks',
|
170 | 'afterErrorHooks',
|
171 | 'locals'
|
172 | ].forEach(function(prop) {
|
173 | it(`should return a cloned app with same ${prop} value`, function() {
|
174 | expect(cloned).to.have.property(prop).to.be.deep.eq(app[prop]);
|
175 | });
|
176 | });
|
177 |
|
178 | [
|
179 | 'settings',
|
180 | 'beforeHooks',
|
181 | 'afterHooks',
|
182 | 'afterErrorHooks',
|
183 | 'locals'
|
184 | ].forEach(function(prop) {
|
185 | it(`should return a cloned app without the same ${prop} reference`, function() {
|
186 | expect(cloned).to.have.property(prop).not.to.be.equal(app[prop]);
|
187 | });
|
188 | });
|
189 |
|
190 | it('should have all sub apps mounted', function() {
|
191 | expect(cloned.mountedApps).to.have.property('length').eq(app.mountedApps.length);
|
192 | cloned.mountedApps.forEach(function(mountedApp, i) {
|
193 | let originalMountedApp = app.mountedApps[i];
|
194 | expect(mountedApp).not.eq(originalMountedApp);
|
195 | expect(mountedApp).to.have.property('parent').eq(cloned);
|
196 | expect(mountedApp).to.have.property('name').eq(originalMountedApp.name);
|
197 | });
|
198 | });
|
199 |
|
200 | it('should have all methods added', function() {
|
201 | expect(cloned.methods).to.have.property('length').eq(app.methods.length);
|
202 | cloned.methods.forEach(function(method, i) {
|
203 | let originalMethod = app.methods[i];
|
204 | expect(method).not.eq(originalMethod);
|
205 | expect(method).to.have.property('parent').eq(cloned);
|
206 | expect(method).to.have.property('name').eq(originalMethod.name);
|
207 | });
|
208 | });
|
209 | });
|
210 |
|
211 | describe('use(fn, options)', function() {
|
212 | it('should be able to use an express or socketio middleware', function() {
|
213 | app.use(function() {});
|
214 | expect(app.methods.length).to.eq(1);
|
215 | });
|
216 |
|
217 | it('should be able to use an app', function() {
|
218 | let subApp = new Application('sub');
|
219 | app.use(subApp);
|
220 | expect(app.mountedApps).to.have.a.property('length').to.eq(1);
|
221 | expect(app.mountedApps[0]).to.have.a.property('parent').to.eq(app);
|
222 | });
|
223 |
|
224 | it('should be able to use a controller', function() {
|
225 | class UsersCtrl extends Controller {
|
226 | constructor() {
|
227 | super();
|
228 |
|
229 | this.beforeAction('signInRequired', { expect: 'signIn' });
|
230 | this.afterAction('insight');
|
231 | this.afterErrorAction('recordError');
|
232 | }
|
233 |
|
234 | initConfig() {
|
235 | return { list: {}, signIn: {} };
|
236 | }
|
237 |
|
238 | signInRequired() {}
|
239 | insight() {}
|
240 | recordError() {}
|
241 |
|
242 | list() {}
|
243 | signIn() {}
|
244 | }
|
245 |
|
246 | app.use(UsersCtrl);
|
247 |
|
248 | expect(app.mountedApps).to.have.a.property('length').to.eq(1);
|
249 |
|
250 | let subApp = app.mountedApps[0];
|
251 |
|
252 | expect(subApp).to.have.a.property('parent').to.eq(app);
|
253 | expect(subApp).to.have.a.property('name').to.eq('users');
|
254 |
|
255 | let methodsLength = 2;
|
256 | let beforeHooksLength = methodsLength + 1;
|
257 | let afterHooksLength = 2;
|
258 | let afterErrorHooksLength = 2;
|
259 | expect(Object.keys(subApp.beforeHooks).length).to.eq(beforeHooksLength);
|
260 | expect(Object.keys(subApp.afterHooks).length).to.eq(afterHooksLength);
|
261 | expect(Object.keys(subApp.afterErrorHooks).length).to.eq(afterErrorHooksLength);
|
262 | expect(subApp.methods.length).eq(methodsLength);
|
263 | });
|
264 |
|
265 | it('should be able to use a method', function() {
|
266 | let method = new Method('test', {}, function() {});
|
267 | app.use(method, {});
|
268 | expect(app.methods.length).to.eq(1);
|
269 | });
|
270 | });
|
271 |
|
272 | describe('set(setting, val)', function() {
|
273 | it('should add a setting with corresponding value', function() {
|
274 | app.set('abc', 1);
|
275 | app.set('person.gender', 'male');
|
276 | expect(app.settings).to.have.a.property('abc', 1);
|
277 | expect(app.settings).to.have.a.deep.property('person.gender', 'male');
|
278 | });
|
279 | });
|
280 |
|
281 | describe('get(setting)', function() {
|
282 | it('should get a setting with corresponding value', function() {
|
283 | app.set('abc', 1);
|
284 | app.set('person.gender', 'male');
|
285 | expect(app.get('abc')).to.eq(1);
|
286 | expect(app.get('person.gender')).to.eq('male');
|
287 | });
|
288 | });
|
289 |
|
290 | describe('enable(setting)', function() {
|
291 | it('should enable a setting', function() {
|
292 | app.enable('abc');
|
293 | expect(app.get('abc')).to.eq(true);
|
294 | });
|
295 | });
|
296 |
|
297 | describe('disable(setting)', function() {
|
298 | it('should disable a setting', function() {
|
299 | app.disable('abc');
|
300 | expect(app.get('abc')).to.eq(false);
|
301 | });
|
302 | });
|
303 |
|
304 | describe('enabled(setting)', function() {
|
305 | it('should return whether a setting is enabled', function() {
|
306 | app.enable('abc');
|
307 | expect(app.enabled('abc')).to.eq(true);
|
308 | app.disable('abc');
|
309 | expect(app.enabled('abc')).to.eq(false);
|
310 | });
|
311 | });
|
312 |
|
313 | describe('disabled(setting)', function() {
|
314 | it('should return whether a setting is disabled', function() {
|
315 | app.enable('abc');
|
316 | expect(app.disabled('abc')).to.eq(false);
|
317 | app.disable('abc');
|
318 | expect(app.disabled('abc')).to.eq(true);
|
319 | });
|
320 | });
|
321 |
|
322 | describe('fullName()', function() {
|
323 | it('should return expected full name with or without parent object', function() {
|
324 | expect(app.fullName()).to.be.eq('test');
|
325 |
|
326 | app.parent = {
|
327 | fullName: function() {
|
328 | return 'users';
|
329 | }
|
330 | };
|
331 |
|
332 | expect(app.fullName()).to.be.eq('users.test');
|
333 | });
|
334 | });
|
335 |
|
336 | describe('fullPath()', function() {
|
337 | it('should return expected full path with or without parent object', function() {
|
338 | expect(app.fullPath()).to.be.eq('/');
|
339 |
|
340 | app.setMountPath('/test');
|
341 |
|
342 | app.parent = {
|
343 | fullPath: function() {
|
344 | return '/users';
|
345 | }
|
346 | };
|
347 |
|
348 | expect(app.fullPath()).to.be.eq('/users/test');
|
349 | });
|
350 | });
|
351 | });
|