##// END OF EJS Templates
tests, refactoring, fixes
cin -
r40:6559c5b81a19 di-typescript
parent child
Show More
@@ -0,0 +1,26
1 import { test } from "./TestTraits";
2 import { Container } from "@implab/core/di/Container";
3 import { ReferenceDescriptor } from "@implab/core/di/ReferenceDescriptor";
4 import { AggregateDescriptor } from "@implab/core/di/AggregateDescriptor";
5
6 test("Container register/getService tests", async t => {
7 const container = new Container();
8
9 const connection1 = "db://localhost";
10
11 container.register("connection", connection1);
12
13 t.equals(container.getService("connection"), connection1);
14
15 container.register(
16 "dbParams",
17 new AggregateDescriptor({
18 timeout: 10,
19 connection: new ReferenceDescriptor({name: "connection"})
20 })
21 );
22
23 const dbParams = container.getService("dbParams");
24 t.equals(dbParams.connection, connection1);
25
26 });
@@ -0,0 +1,43
1 import { IActivatable, ICancellation, IActivationController } from "@implab/core/interfaces";
2 import { Cancellation } from "@implab/core/Cancellation";
3
4 export class MockActivationController implements IActivationController {
5
6 _active: IActivatable = null;
7
8 getActive(): IActivatable {
9 return this._active;
10 }
11
12 async deactivate() {
13 if (this._active)
14 await this._active.deactivate();
15 this._active = null;
16 }
17
18 async activate(component: IActivatable) {
19 if (!component || component.isActive())
20 return;
21 component.setActivationController(this);
22
23 await component.activate();
24 }
25
26 async activating(component: IActivatable, ct: ICancellation = Cancellation.none) {
27 if (component !== this._active)
28 await this.deactivate();
29 }
30
31 async activated(component: IActivatable, ct: ICancellation = Cancellation.none) {
32 this._active = component;
33 }
34
35 async deactivating(component: IActivatable, ct: ICancellation = Cancellation.none) {
36
37 }
38
39 async deactivated(component: IActivatable, ct: ICancellation = Cancellation.none) {
40 if (this._active === component)
41 this._active = null;
42 }
43 }
@@ -0,0 +1,6
1 import { AsyncComponent } from "@implab/core/components/AsyncComponent";
2 import { ActivatableMixin } from "@implab/core/components/ActivatableMixin";
3
4 export class SimpleActivatable extends ActivatableMixin(AsyncComponent) {
5
6 }
@@ -37,7 +37,7 task _legacyJs(type:Copy) {
37 37
38 38 task _buildTs(dependsOn: _npmInstall, type:Exec) {
39 39 inputs.dir('src/ts')
40 inputs.file('tsc.json')
40 inputs.file('tsconfig.json')
41 41 outputs.dir(distDir)
42 42
43 43 commandLine 'node_modules/.bin/tsc', '-p', 'tsconfig.json'
@@ -77,7 +77,7 task copyJsTests(type: Copy) {
77 77
78 78 task buildTests(dependsOn: _localInstall, type: Exec) {
79 79 inputs.dir('test/ts')
80 inputs.file('tsc.test.json')
80 inputs.file('tsconfig.test.json')
81 81 outputs.dir(testDir)
82 82
83 83 commandLine 'node_modules/.bin/tsc', '-p', 'tsconfig.test.json'
@@ -1,2 +1,2
1 version=1.1.1
1 version=1.1.2
2 2 release=rtm No newline at end of file
@@ -5,9 +5,9
5 5 "requires": true,
6 6 "dependencies": {
7 7 "@types/node": {
8 "version": "10.5.1",
9 "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.1.tgz",
10 "integrity": "sha512-AFLl1IALIuyt6oK4AYZsgWVJ/5rnyzQWud7IebaZWWV3YmgtPZkQmYio9R5Ze/2pdd7XfqF5bP+hWS11mAKoOQ==",
8 "version": "10.12.12",
9 "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.12.tgz",
10 "integrity": "sha512-Pr+6JRiKkfsFvmU/LK68oBRCQeEg36TyAbPhc2xpez24OOZZCuoIhWGTd39VZy6nGafSbxzGouFPTFD/rR1A0A==",
11 11 "dev": true
12 12 },
13 13 "@types/tape": {
@@ -48,25 +48,32
48 48 "dev": true
49 49 },
50 50 "deep-equal": {
51 "version": "1.0.1",
52 "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
53 "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
51 "version": "0.1.2",
52 "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.1.2.tgz",
53 "integrity": "sha1-skbCuApXCkfBG+HZvRBw7IeLh84=",
54 54 "dev": true
55 55 },
56 56 "define-properties": {
57 "version": "1.1.2",
58 "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
59 "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
57 "version": "1.1.3",
58 "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
59 "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
60 60 "dev": true,
61 61 "requires": {
62 "foreach": "^2.0.5",
63 "object-keys": "^1.0.8"
62 "object-keys": "^1.0.12"
63 },
64 "dependencies": {
65 "object-keys": {
66 "version": "1.0.12",
67 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
68 "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
69 "dev": true
70 }
64 71 }
65 72 },
66 73 "defined": {
67 "version": "1.0.0",
68 "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
69 "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
74 "version": "0.0.0",
75 "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz",
76 "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=",
70 77 "dev": true
71 78 },
72 79 "dojo": {
@@ -76,7 +83,7
76 83 },
77 84 "duplexer": {
78 85 "version": "0.1.1",
79 "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
86 "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
80 87 "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
81 88 "dev": true
82 89 },
@@ -94,14 +101,14
94 101 }
95 102 },
96 103 "es-to-primitive": {
97 "version": "1.1.1",
98 "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
99 "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
104 "version": "1.2.0",
105 "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
106 "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
100 107 "dev": true,
101 108 "requires": {
102 "is-callable": "^1.1.1",
109 "is-callable": "^1.1.4",
103 110 "is-date-object": "^1.0.1",
104 "is-symbol": "^1.0.1"
111 "is-symbol": "^1.0.2"
105 112 }
106 113 },
107 114 "faucet": {
@@ -119,27 +126,9
119 126 "through2": "~0.2.3"
120 127 },
121 128 "dependencies": {
122 "deep-equal": {
123 "version": "0.1.2",
124 "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.1.2.tgz",
125 "integrity": "sha1-skbCuApXCkfBG+HZvRBw7IeLh84=",
126 "dev": true
127 },
128 "defined": {
129 "version": "0.0.0",
130 "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz",
131 "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=",
132 "dev": true
133 },
134 "minimist": {
135 "version": "0.0.5",
136 "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz",
137 "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=",
138 "dev": true
139 },
140 129 "tape": {
141 130 "version": "2.3.3",
142 "resolved": "https://registry.npmjs.org/tape/-/tape-2.3.3.tgz",
131 "resolved": "http://registry.npmjs.org/tape/-/tape-2.3.3.tgz",
143 132 "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=",
144 133 "dev": true,
145 134 "requires": {
@@ -162,12 +151,6
162 151 "is-callable": "^1.1.3"
163 152 }
164 153 },
165 "foreach": {
166 "version": "2.0.5",
167 "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
168 "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
169 "dev": true
170 },
171 154 "fs.realpath": {
172 155 "version": "1.0.0",
173 156 "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -181,9 +164,9
181 164 "dev": true
182 165 },
183 166 "glob": {
184 "version": "7.1.2",
185 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
186 "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
167 "version": "7.1.3",
168 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
169 "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
187 170 "dev": true,
188 171 "requires": {
189 172 "fs.realpath": "^1.0.0",
@@ -203,6 +186,12
203 186 "function-bind": "^1.1.1"
204 187 }
205 188 },
189 "has-symbols": {
190 "version": "1.0.0",
191 "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
192 "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
193 "dev": true
194 },
206 195 "inflight": {
207 196 "version": "1.0.6",
208 197 "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -220,9 +209,9
220 209 "dev": true
221 210 },
222 211 "is-callable": {
223 "version": "1.1.3",
224 "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz",
225 "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=",
212 "version": "1.1.4",
213 "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
214 "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
226 215 "dev": true
227 216 },
228 217 "is-date-object": {
@@ -241,10 +230,13
241 230 }
242 231 },
243 232 "is-symbol": {
244 "version": "1.0.1",
245 "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
246 "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=",
247 "dev": true
233 "version": "1.0.2",
234 "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
235 "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
236 "dev": true,
237 "requires": {
238 "has-symbols": "^1.0.0"
239 }
248 240 },
249 241 "isarray": {
250 242 "version": "0.0.1",
@@ -268,9 +260,9
268 260 }
269 261 },
270 262 "minimist": {
271 "version": "1.2.0",
272 "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
273 "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
263 "version": "0.0.5",
264 "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz",
265 "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=",
274 266 "dev": true
275 267 },
276 268 "object-inspect": {
@@ -280,9 +272,9
280 272 "dev": true
281 273 },
282 274 "object-keys": {
283 "version": "1.0.12",
284 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
285 "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
275 "version": "0.4.0",
276 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
277 "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=",
286 278 "dev": true
287 279 },
288 280 "once": {
@@ -296,19 +288,19
296 288 },
297 289 "path-is-absolute": {
298 290 "version": "1.0.1",
299 "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
291 "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
300 292 "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
301 293 "dev": true
302 294 },
303 295 "path-parse": {
304 "version": "1.0.5",
305 "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
306 "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=",
296 "version": "1.0.6",
297 "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
298 "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
307 299 "dev": true
308 300 },
309 301 "readable-stream": {
310 302 "version": "1.1.14",
311 "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
303 "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
312 304 "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
313 305 "dev": true,
314 306 "requires": {
@@ -361,7 +353,7
361 353 },
362 354 "string_decoder": {
363 355 "version": "0.10.31",
364 "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
356 "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
365 357 "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
366 358 "dev": true
367 359 },
@@ -394,17 +386,37
394 386 "resumer": "~0.0.0",
395 387 "string.prototype.trim": "~1.1.2",
396 388 "through": "~2.3.8"
389 },
390 "dependencies": {
391 "deep-equal": {
392 "version": "1.0.1",
393 "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
394 "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
395 "dev": true
396 },
397 "defined": {
398 "version": "1.0.0",
399 "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
400 "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
401 "dev": true
402 },
403 "minimist": {
404 "version": "1.2.0",
405 "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
406 "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
407 "dev": true
408 }
397 409 }
398 410 },
399 411 "through": {
400 412 "version": "2.3.8",
401 "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
413 "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
402 414 "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
403 415 "dev": true
404 416 },
405 417 "through2": {
406 418 "version": "0.2.3",
407 "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
419 "resolved": "http://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
408 420 "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=",
409 421 "dev": true,
410 422 "requires": {
@@ -413,9 +425,9
413 425 }
414 426 },
415 427 "typescript": {
416 "version": "3.1.6",
417 "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.6.tgz",
418 "integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==",
428 "version": "3.2.1",
429 "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.1.tgz",
430 "integrity": "sha512-jw7P2z/h6aPT4AENXDGjcfHTu5CSqzsbZc6YlUIebTyBAq8XaKp78x7VcSh30xwSCcsu5irZkYZUSFP1MrAMbg==",
419 431 "dev": true
420 432 },
421 433 "wrappy": {
@@ -431,15 +443,7
431 443 "dev": true,
432 444 "requires": {
433 445 "object-keys": "~0.4.0"
434 },
435 "dependencies": {
436 "object-keys": {
437 "version": "0.4.0",
438 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
439 "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=",
440 "dev": true
441 446 }
442 447 }
443 448 }
444 449 }
445 }
@@ -44,7 +44,7 export class ActivationContext {
44 44 else
45 45 throw new Error(`Service ${name} not found`);
46 46
47 return d.activate(this, name);
47 return isDescriptor(d) ? d.activate(this, name) : d;
48 48 }
49 49
50 50 /**
@@ -80,7 +80,7 export class ActivationContext {
80 80 return (this._cache[id] = value);
81 81 }
82 82
83 parse(data: object, name: string) {
83 parse(data, name: string) {
84 84 if (isPrimitive(data))
85 85 return data;
86 86
@@ -39,7 +39,7 export class Container {
39 39 return this._parent;
40 40 }
41 41
42 getService<T = any>(name: string, def?: T) {
42 getService(name: string, def?) {
43 43 const d = this._services[name];
44 44 if (!d)
45 45 if (arguments.length > 1)
@@ -47,13 +47,16 export class Container {
47 47 else
48 48 throw new Error("Service '" + name + "' isn't found");
49 49
50 if (!isDescriptor(d))
51 return d;
52
50 53 if (d.isInstanceCreated())
51 return d.getInstance() as T;
54 return d.getInstance();
52 55
53 56 const context = new ActivationContext(this, this._services);
54 57
55 58 try {
56 return d.activate(context, name) as T;
59 return d.activate(context, name);
57 60 } catch (error) {
58 61 throw new ActivationError(name, context.getStack(), error);
59 62 }
@@ -65,8 +68,6 export class Container {
65 68 for (const name in data)
66 69 this.register(name, data[name]);
67 70 } else {
68 if (!(isDescriptor(service)))
69 service = new ValueDescriptor(service);
70 71 this._services[nameOrCollection] = service;
71 72 }
72 73 return this;
@@ -148,13 +149,13 export class Container {
148 149
149 150 if (isDependencyRegistration(registration)) {
150 151
151 return new ReferenceDescriptor(
152 registration.$dependency,
153 registration.lazy,
154 registration.optional,
155 registration["default"],
156 registration.services && this._parseObject(registration.services, resolver)
157 );
152 return new ReferenceDescriptor({
153 name: registration.$dependency,
154 lazy: registration.lazy,
155 optional: registration.optional,
156 default: registration.default,
157 services: registration.services && this._parseObject(registration.services, resolver)
158 });
158 159
159 160 } else if (isValueRegistration(registration)) {
160 161
@@ -3,6 +3,14 import { ActivationContext } from "./Act
3 3 import { ServiceMap, Descriptor } from "./interfaces";
4 4 import { ActivationError } from "./ActivationError";
5 5
6 export interface ReferenceDescriptorParams {
7 name: string;
8 lazy?: boolean;
9 optional?: boolean;
10 default?;
11 services?: ServiceMap;
12 }
13
6 14 export class ReferenceDescriptor implements Descriptor {
7 15 _name: string;
8 16
@@ -14,13 +22,13 export class ReferenceDescriptor impleme
14 22
15 23 _services: ServiceMap;
16 24
17 constructor(name: string, lazy: boolean, optional: boolean, def, services: ServiceMap) {
18 argumentNotEmptyString(name, "name");
19 this._name = name;
20 this._lazy = Boolean(lazy);
21 this._optional = Boolean(optional);
22 this._default = def;
23 this._services = services;
25 constructor(opts: ReferenceDescriptorParams) {
26 argumentNotEmptyString(opts && opts.name, "opts.name");
27 this._name = opts.name;
28 this._lazy = !!opts.lazy;
29 this._optional = !!opts.optional;
30 this._default = !!opts.default;
31 this._services = opts.services;
24 32 }
25 33
26 34 activate(context: ActivationContext, name: string) {
@@ -1,4 +1,4
1 import { isNull } from "../safe";
1 import { isNull, isPrimitive } from "../safe";
2 2 import { ActivationContext } from "./ActivationContext";
3 3 import { Constructor, Factory } from "../interfaces";
4 4
@@ -8,13 +8,13 export interface Descriptor {
8 8 getInstance();
9 9 }
10 10
11 export function isDescriptor(instance): instance is Descriptor {
12 return (!isNull(instance)) &&
13 ("activate" in instance);
11 export function isDescriptor(x): x is Descriptor {
12 return (!isPrimitive(x)) &&
13 (x.activate instanceof Function);
14 14 }
15 15
16 16 export interface ServiceMap {
17 [s: string]: Descriptor;
17 [s: string]: any;
18 18 }
19 19
20 20 export enum ActivationType {
@@ -56,13 +56,13 export interface DependencyRegistration
56 56 }
57 57
58 58 export function isServiceRegistration(x): x is ServiceRegistration {
59 return x && ("$type" in x || "$factory" in x);
59 return (!isPrimitive(x)) && ("$type" in x || "$factory" in x);
60 60 }
61 61
62 62 export function isValueRegistration(x): x is ValueRegistration {
63 return x && "$value" in x;
63 return (!isPrimitive(x)) && ("$value" in x);
64 64 }
65 65
66 66 export function isDependencyRegistration(x): x is DependencyRegistration {
67 return x && "$depdendency" in x;
67 return (!isPrimitive(x)) && ("$depdendency" in x);
68 68 }
@@ -1,3 +1,4
1 define(["./ActivatableTests", "./trace-test", "./TraceSourceTests", "./CancellationTests"]);
1 //define(["./ActivatableTests", "./trace-test", "./TraceSourceTests", "./CancellationTests"]);
2 2 //define(["./CancellationTests"]);
3 //define(["./ObservableTests"]); No newline at end of file
3 //define(["./ObservableTests"]);
4 define(["./ContainerTests"]); No newline at end of file
@@ -1,58 +1,10
1 import * as tape from 'tape';
2 import { ActivatableMixin} from '@implab/core/components/ActivatableMixin';
3 import { AsyncComponent } from '@implab/core/components/AsyncComponent';
4 import { IActivationController, IActivatable, ICancellation } from '@implab/core/interfaces';
5 import { Cancellation } from '@implab/core/Cancellation';
6
7 class SimpleActivatable extends ActivatableMixin(AsyncComponent) {
8
9 }
10
11 class MockActivationController implements IActivationController {
12
13 _active: IActivatable = null;
14
15
16 getActive() : IActivatable {
17 return this._active;
18 }
19
20 async deactivate() {
21 if (this._active)
22 await this._active.deactivate();
23 this._active = null;
24 }
1 import * as tape from "tape";
2 import { MockActivationController } from "./mock/MockActivationController";
3 import { SimpleActivatable } from "./mock/SimpleActivatable";
25 4
26 async activate(component: IActivatable) {
27 if (!component || component.isActive())
28 return;
29 component.setActivationController(this);
30
31 await component.activate();
32 }
33
34 async activating(component: IActivatable, ct: ICancellation = Cancellation.none) {
35 if (component != this._active)
36 await this.deactivate();
37 }
5 tape("simple activation", async t => {
38 6
39 async activated(component: IActivatable, ct: ICancellation = Cancellation.none) {
40 this._active = component;
41 }
42
43 async deactivating(component: IActivatable, ct: ICancellation = Cancellation.none) {
44
45 }
46
47 async deactivated(component: IActivatable, ct: ICancellation = Cancellation.none) {
48 if (this._active == component)
49 this._active = null;
50 }
51 }
52
53 tape('simple activation',async function(t){
54
55 let a = new SimpleActivatable();
7 const a = new SimpleActivatable();
56 8 t.false(a.isActive());
57 9
58 10 await a.activate();
@@ -64,10 +16,10 tape('simple activation',async function(
64 16 t.end();
65 17 });
66 18
67 tape('controller activation', async function(t) {
19 tape("controller activation", async t => {
68 20
69 let a = new SimpleActivatable();
70 let c = new MockActivationController();
21 const a = new SimpleActivatable();
22 const c = new MockActivationController();
71 23
72 24 t.false(a.isActive(), "the component is not active by default");
73 25 t.assert(c.getActive() == null, "the activation controller doesn't have an active component by default");
@@ -89,11 +41,11 tape('controller activation', async func
89 41 t.end();
90 42 });
91 43
92 tape('handle error in onActivating', async function(t) {
93 let a = new SimpleActivatable();
44 tape("handle error in onActivating", async t => {
45 const a = new SimpleActivatable();
94 46
95 a.onActivating = async function() {
96 throw "Should fail";
47 a.onActivating = async () => {
48 throw new Error("Should fail");
97 49 };
98 50
99 51 try {
@@ -105,4 +57,4 tape('handle error in onActivating', asy
105 57 t.false(a.isActive(), "the component should remain inactive");
106 58
107 59 t.end();
108 }); No newline at end of file
60 });
@@ -1,18 +1,18
1 import * as tape from 'tape';
2 import { Cancellation } from '@implab/core/Cancellation';
3 import { ICancellation } from '@implab/core/interfaces';
4 import { delay } from './TestTraits';
1 import * as tape from "tape";
2 import { Cancellation } from "@implab/core/Cancellation";
3 import { ICancellation } from "@implab/core/interfaces";
4 import { delay } from "./TestTraits";
5 5
6 tape('standalone cancellation', async t => {
6 tape("standalone cancellation", async t => {
7 7
8 8 let doCancel: (e) => void;
9 9
10 let ct = new Cancellation(cancel => {
10 const ct = new Cancellation(cancel => {
11 11 doCancel = cancel;
12 12 });
13 13
14 14 let counter = 0;
15 let reason = "BILL";
15 const reason = "BILL";
16 16
17 17 t.true(ct.isSupported(), "Cancellation must be supported");
18 18 t.false(ct.isRequested(), "Cancellation shouldn't be requested");
@@ -33,7 +33,7 tape('standalone cancellation', async t
33 33 t.equals(counter, 2, "The callback should be triggered immediately");
34 34
35 35 let msg;
36 ct.register((e) => msg = e);
36 ct.register(e => msg = e);
37 37 t.equals(msg, reason, "The cancellation reason should be passed to callback");
38 38
39 39 try {
@@ -48,9 +48,9 tape('standalone cancellation', async t
48 48 t.end();
49 49 });
50 50
51 tape('async cancellation', async t => {
51 tape("async cancellation", async t => {
52 52
53 let ct = new Cancellation(cancel => {
53 const ct = new Cancellation(cancel => {
54 54 cancel("STOP!");
55 55 });
56 56
@@ -64,10 +64,10 tape('async cancellation', async t => {
64 64 t.end();
65 65 });
66 66
67 tape('cancel with external event', async t => {
68 let ct = new Cancellation((cancel) => {
69 setTimeout(x => cancel('STOP!'), 0);
70 })
67 tape("cancel with external event", async t => {
68 const ct = new Cancellation(cancel => {
69 setTimeout(x => cancel("STOP!"), 0);
70 });
71 71
72 72 try {
73 73 await delay(10000, ct);
@@ -79,10 +79,10 tape('cancel with external event', async
79 79 t.end();
80 80 });
81 81
82 tape('operation normal flow', async t => {
82 tape("operation normal flow", async t => {
83 83
84 84 let htimeout;
85 let ct = new Cancellation((cancel) => {
85 const ct = new Cancellation(cancel => {
86 86 htimeout = setTimeout(() => cancel("STOP!"), 1000);
87 87 });
88 88
@@ -94,4 +94,4 tape('operation normal flow', async t =>
94 94 }
95 95
96 96 t.end();
97 }); No newline at end of file
97 });
@@ -1,23 +1,22
1 import { TraceSource, DebugLevel } from '@implab/core/log/TraceSource'
2 import * as tape from 'tape';
3 import { TapeWriter, delay } from './TestTraits';
4 import { Observable } from '@implab/core/Observable';
5 import { IObservable } from '@implab/core/interfaces';
6
7 let trace = TraceSource.get("ObservableTests");
1 import { TraceSource, DebugLevel } from "@implab/core/log/TraceSource";
2 import * as tape from "tape";
3 import { TapeWriter, delay } from "./TestTraits";
4 import { Observable } from "@implab/core/Observable";
5 import { IObservable } from "@implab/core/interfaces";
8 6
9 tape('events sequence example', async t => {
7 const trace = TraceSource.get("ObservableTests");
10 8
9 tape("events sequence example", async t => {
11 10
12 let events: IObservable<number>
11 let events: IObservable<number>;
13 12
14 let done = new Promise<void>((resolve) => {
15 events = new Observable<number>(async (notify, fail, complete) => {
13 const done = new Promise<void>(resolve => {
14 events = new Observable<number>(async (notify, fail, finish) => {
16 15 for (let i = 0; i < 10; i++) {
17 16 await delay(0);
18 17 notify(i);
19 18 }
20 complete();
19 finish();
21 20 resolve();
22 21 });
23 22 });
@@ -26,7 +25,7 tape('events sequence example', async t
26 25 let complete = false;
27 26 events.on(x => count = count + x, null, () => complete = true);
28 27
29 let first = await events.next();
28 const first = await events.next();
30 29
31 30 t.equals(first, 0, "the first event");
32 31 t.false(complete, "the sequence is not complete");
@@ -39,10 +38,10 tape('events sequence example', async t
39 38 t.end();
40 39 });
41 40
42 tape('event sequence termination', async t => {
43 let events: IObservable<number>
41 tape("event sequence termination", async t => {
42 let events: IObservable<number>;
44 43
45 let done = new Promise<void>((resolve) => {
44 const done = new Promise<void>(resolve => {
46 45 events = new Observable<number>(async (notify, fail, complete) => {
47 46 await delay(0);
48 47 notify(1);
@@ -55,9 +54,9 tape('event sequence termination', async
55 54 });
56 55
57 56 let count = 0;
58 events.on(() => {}, (e) => count++, () => count++);
57 events.on(() => {}, e => count++, () => count++);
59 58
60 let first = await events.next();
59 const first = await events.next();
61 60 t.equals(first, 1, "the first message");
62 61 try {
63 62 await events.next();
@@ -71,4 +70,4 tape('event sequence termination', async
71 70 t.equals(count, 1, "the sequence must be terminated once");
72 71
73 72 t.end();
74 }); No newline at end of file
73 });
@@ -1,21 +1,21
1 1 import { IObservable, ICancellation, IDestroyable } from "@implab/core/interfaces";
2 2 import { Cancellation } from "@implab/core/Cancellation";
3 3 import { TraceEvent, LogLevel, WarnLevel } from "@implab/core/log/TraceSource";
4 import * as tape from 'tape';
4 import * as tape from "tape";
5 5 import { argumentNotNull } from "@implab/core/safe";
6 6
7 7 export class TapeWriter implements IDestroyable {
8 readonly _tape: tape.Test
8 readonly _tape: tape.Test;
9 9
10 10 _subscriptions = new Array<IDestroyable>();
11 11
12 constructor(tape: tape.Test) {
13 argumentNotNull(tape, "tape");
14 this._tape = tape;
12 constructor(t: tape.Test) {
13 argumentNotNull(t, "tape");
14 this._tape = t;
15 15 }
16 16
17 17 writeEvents(source: IObservable<TraceEvent>, ct: ICancellation = Cancellation.none) {
18 let subscription = source.on(this.writeEvent.bind(this));
18 const subscription = source.on(this.writeEvent.bind(this));
19 19 if (ct.isSupported()) {
20 20 ct.register(subscription.destroy.bind(subscription));
21 21 }
@@ -45,7 +45,7 export async function delay(timeout: num
45 45 if (ct.isRequested()) {
46 46 un = ct.register(reject);
47 47 } else {
48 let ht = setTimeout(() => {
48 const ht = setTimeout(() => {
49 49 resolve();
50 50 }, timeout);
51 51
@@ -58,5 +58,18 export async function delay(timeout: num
58 58 } finally {
59 59 if(un)
60 60 un.destroy();
61 };
62 } No newline at end of file
61 }
62 }
63
64 export function test(name: string, cb: (t: tape.Test) => any) {
65 tape(name, async t => {
66 try {
67 await cb(t);
68 } catch (e) {
69 console.error(e);
70 t.fail(e);
71 } finally {
72 t.end();
73 }
74 });
75 }
@@ -1,15 +1,15
1 import { TraceSource, DebugLevel } from '@implab/core/log/TraceSource'
2 import * as tape from 'tape';
3 import { TapeWriter } from './TestTraits';
1 import { TraceSource, DebugLevel } from "@implab/core/log/TraceSource";
2 import * as tape from "tape";
3 import { TapeWriter } from "./TestTraits";
4 4
5 const sourceId = 'test/TraceSourceTests';
5 const sourceId = "test/TraceSourceTests";
6 6
7 tape('trace message', t => {
8 let trace = TraceSource.get(sourceId);
7 tape("trace message", t => {
8 const trace = TraceSource.get(sourceId);
9 9
10 10 trace.level = DebugLevel;
11 11
12 let h = trace.events.on((ev) => {
12 const h = trace.events.on(ev => {
13 13 t.equal(ev.source, trace, "sender should be the current trace source");
14 14 t.equal(ev.level, DebugLevel, "level should be debug level");
15 15 t.equal(ev.arg, "Hello, World!", "The message should be a formatted message");
@@ -22,16 +22,16 tape('trace message', t => {
22 22 h.destroy();
23 23 });
24 24
25 tape('trace event', t => {
26 let trace = TraceSource.get(sourceId);
25 tape("trace event", t => {
26 const trace = TraceSource.get(sourceId);
27 27
28 28 trace.level = DebugLevel;
29 29
30 let event = {
30 const event = {
31 31 name: "custom event"
32 32 };
33 33
34 let h = trace.events.on((ev) => {
34 const h = trace.events.on(ev => {
35 35 t.equal(ev.source, trace, "sender should be the current trace source");
36 36 t.equal(ev.level, DebugLevel, "level should be debug level");
37 37 t.equal(ev.arg, event, "The message should be the specified object");
@@ -44,17 +44,17 tape('trace event', t => {
44 44 h.destroy();
45 45 });
46 46
47 tape('tape comment writer', async t => {
48 let writer = new TapeWriter(t);
47 tape("tape comment writer", async t => {
48 const writer = new TapeWriter(t);
49 49
50 50 TraceSource.on(ts => {
51 51 writer.writeEvents(ts.events);
52 52 });
53 53
54 let trace = TraceSource.get(sourceId);
54 const trace = TraceSource.get(sourceId);
55 55 trace.level = DebugLevel;
56 56
57 trace.log("Hello, {0}!", 'World');
57 trace.log("Hello, {0}!", "World");
58 58 trace.log("Multi\n line");
59 59 trace.warn("Look at me!");
60 60 trace.error("DIE!");
@@ -66,4 +66,4 tape('tape comment writer', async t => {
66 66 t.comment("DONE");
67 67
68 68 t.end();
69 }); No newline at end of file
69 });
General Comments 0
You need to be logged in to leave comments. Login now