##// END OF EJS Templates
working on Observable
cin -
r14:53e756f117f7 propose cancellat...
parent child
Show More
@@ -0,0 +1,21
1 import * as TraceSource from './TraceSource'
2
3 class TraceEvent {
4 readonly source: TraceSource;
5
6 readonly level: Number;
7
8 readonly arg: any;
9
10 constructor(source: TraceSource, level: Number, arg: any) {
11 this.source = source;
12 this.level = level;
13 this.arg = arg;
14 }
15 }
16
17 namespace TraceEvent {
18
19 }
20
21 export = TraceEvent No newline at end of file
@@ -0,0 +1,29
1 import { IObservable } from "../../interfaces";
2 import * as TraceEvent from '../TraceEvent';
3 import { ICancellation } from "../../interfaces";
4 import { Cancellation } from "../../Cancellation";
5 import * as TraceSource from "../TraceSource";
6
7 class ConsoleWriter {
8 async write(source: IObservable<TraceEvent>, ct: ICancellation = Cancellation.none) {
9 let next;
10 while(next = await source.next(ct)) {
11 this._writeEvent(next);
12 }
13 }
14
15 private _writeEvent(next: TraceEvent) {
16 if (next.level >= TraceSource.LogLevel) {
17 console.log(next.source.toString(), next.arg);
18 } else if(next.level >= TraceSource.WarnLevel) {
19 console.warn(next.source.toString(), next.arg);
20 } else {
21 console.error(next.source.toString(), next.arg);
22 }
23 }
24 }
25
26 namespace ConsoleWriter {
27 }
28
29 export = ConsoleWriter; No newline at end of file
@@ -1,85 +1,94
1 import { IObservable, IObserver, IDestroyable, ICancellation } from '../interfaces';
1 import { IObservable, IDestroyable, ICancellation } from '../interfaces';
2 import { Cancellation } from '../Cancellation'
2 import { Cancellation } from '../Cancellation'
3 import * as TraceSource from '../log/TraceSource'
4 import { argumentNotNull } from '../safe';
3 import { argumentNotNull } from '../safe';
5
4
6 const trace = TraceSource.get('@implab/core/components/Observable');
7
8
5
9 class Observable<T> implements IObservable<T> {
6 interface Handler<T> {
10 private _once = new Array<IObserver<T>>();
7 (x:T) : void
11
8 }
12 private readonly _observers = new Array<IObserver<T>>();
13
9
14 constructor(func: (notify: IObserver<T>) => void) {
10 interface Initializer<T> {
15 argumentNotNull(func, "func");
11 (notify: Handler<T>) : (() => void) | void;
16
17 func(this._notify.bind(this));
18 }
12 }
19
13
20 on(observer: IObserver<T>): IDestroyable {
14
15 class Observable<T> implements IObservable<T>, IDestroyable {
16 private _once = new Array<Handler<T>>();
17
18 private readonly _observers = new Array<Handler<T>>();
19
20 private readonly _cleanup : (() => void) | void;
21
22 constructor(func?: Initializer<T>) {
23 this._cleanup = func && func(this._notify.bind(this));
24 }
25
26 on(observer: Handler<T>, error?: Handler<any>, complete?: () => void): IDestroyable {
21 argumentNotNull(observer, "observer");
27 argumentNotNull(observer, "observer");
22
28
23 this._observers.push(observer);
29 this._observers.push(observer);
24
30
25 let me = this;
31 let me = this;
26 return {
32 return {
27 destroy() {
33 destroy() {
28 me._removeObserver(observer);
34 me._removeObserver(observer);
29 }
35 }
30 }
36 }
31 }
37 }
32
38
33 wait(ct: ICancellation = Cancellation.none): Promise<T> {
39 next(ct: ICancellation = Cancellation.none): Promise<T> {
34 return new Promise<T>((resolve, reject) => {
40 return new Promise<T>((resolve, reject) => {
35 this._once.push(resolve);
41 this._once.push(resolve);
36 if (ct.isSupported()) {
42 if (ct.isSupported()) {
37 ct.register((e) => {
43 ct.register((e) => {
38 this._removeOnce(resolve);
44 this._removeOnce(resolve);
39 reject(e);
45 reject(e);
40 });
46 });
41 }
47 }
42 });
48 });
43 }
49 }
44
50
45 onObserverException(e: any) {
51 destroy() {
46 trace.error("Unhandled exception in the observer: {0}", e);
52 if(this._cleanup)
53 this._cleanup.call(null);
47 }
54 }
48
55
49 private _removeOnce(d: IObserver<T>) {
56 protected onObserverException(e: any) {
57 }
58
59 private _removeOnce(d: Handler<T>) {
50 let i = this._once.indexOf(d);
60 let i = this._once.indexOf(d);
51 if (i >= 0)
61 if (i >= 0)
52 this._once.splice(i);
62 this._once.splice(i);
53 }
63 }
54
64
55 private _removeObserver(d: IObserver<T>) {
65 private _removeObserver(d: Handler<T>) {
56 let i = this._observers.indexOf(d);
66 let i = this._observers.indexOf(d);
57 if (i >= 0)
67 if (i >= 0)
58 this._observers.splice(i);
68 this._observers.splice(i);
59 }
69 }
60
70
61 private _notify(evt: T) {
71 protected _notify(evt: T) {
62 let guard = (observer: IObserver<T>) => {
72 let guard = (observer: Handler<T>) => {
63 try {
73 try {
64 observer(evt);
74 observer(evt);
65 } catch (e) {
75 } catch (e) {
66 this.onObserverException(e);
76 this.onObserverException(e);
67 }
77 }
68 }
78 }
69
79
70 if (this._once.length) {
80 if (this._once.length) {
71 for (let i = 0; i < this._once.length; i++)
81 for (let i = 0; i < this._once.length; i++)
72 guard(this._once[i]);
82 guard(this._once[i]);
73 this._once = [];
83 this._once = [];
74 }
84 }
75
85
76 for (let i = 0; i < this._observers.length; i++)
86 for (let i = 0; i < this._observers.length; i++)
77 guard(this._observers[i]);
87 guard(this._observers[i]);
78 }
88 }
79 }
89 }
80
90
81 namespace Observable {
91 namespace Observable {
82 export const traceSource = trace;
83 }
92 }
84
93
85 export = Observable; No newline at end of file
94 export = Observable;
@@ -1,83 +1,76
1 import { watchFile } from "fs";
2
3 export interface IDestroyable {
1 export interface IDestroyable {
4 destroy();
2 destroy();
5 }
3 }
6
4
7 export interface ICancellation {
5 export interface ICancellation {
8 throwIfRequested(): void;
6 throwIfRequested(): void;
9 isRequested(): boolean;
7 isRequested(): boolean;
10 isSupported(): boolean;
8 isSupported(): boolean;
11 register(cb: (e: any) => void): void;
9 register(cb: (e: any) => void): void;
12 }
10 }
13
11
14 /**
12 /**
15 * Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‰ΠΈΠΉ Π°ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΡƒΡŽ Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΡŽ
13 * Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‰ΠΈΠΉ Π°ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΡƒΡŽ Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΡŽ
16 */
14 */
17 export interface IActivatable {
15 export interface IActivatable {
18 /**
16 /**
19 * @returns Boolean indicates the current state
17 * @returns Boolean indicates the current state
20 */
18 */
21 isActive(): boolean;
19 isActive(): boolean;
22
20
23 /**
21 /**
24 * Starts the component activation
22 * Starts the component activation
25 * @param ct cancellation token for this operation
23 * @param ct cancellation token for this operation
26 */
24 */
27 activate(ct?: ICancellation) : Promise<void>;
25 activate(ct?: ICancellation) : Promise<void>;
28
26
29 /**
27 /**
30 * Starts the component deactivation
28 * Starts the component deactivation
31 * @param ct cancellation token for this operation
29 * @param ct cancellation token for this operation
32 */
30 */
33 deactivate(ct?: ICancellation) : Promise<void>;
31 deactivate(ct?: ICancellation) : Promise<void>;
34
32
35 /**
33 /**
36 * Sets the activation controller for this component
34 * Sets the activation controller for this component
37 * @param controller The activation controller
35 * @param controller The activation controller
38 *
36 *
39 * Activation controller checks whether this component
37 * Activation controller checks whether this component
40 * can be activated and manages the active state of the
38 * can be activated and manages the active state of the
41 * component
39 * component
42 */
40 */
43 setActivationController(controller: IActivationController);
41 setActivationController(controller: IActivationController);
44
42
45 /**
43 /**
46 * Gets the current activation controller for this component
44 * Gets the current activation controller for this component
47 */
45 */
48 getActivationController(): IActivationController;
46 getActivationController(): IActivationController;
49 }
47 }
50
48
51 export interface IActivationController {
49 export interface IActivationController {
52 activating(component: IActivatable, ct?: ICancellation): Promise<void>;
50 activating(component: IActivatable, ct?: ICancellation): Promise<void>;
53
51
54 activated(component: IActivatable, ct?: ICancellation): Promise<void>;
52 activated(component: IActivatable, ct?: ICancellation): Promise<void>;
55
53
56 deactivating(component: IActivatable, ct?: ICancellation): Promise<void>;
54 deactivating(component: IActivatable, ct?: ICancellation): Promise<void>;
57
55
58 deactivated(component: IActivatable, ct?: ICancellation): Promise<void>;
56 deactivated(component: IActivatable, ct?: ICancellation): Promise<void>;
59
57
60 deactivate(ct?: ICancellation): Promise<void>;
58 deactivate(ct?: ICancellation): Promise<void>;
61
59
62 activate(component: IActivatable, ct?: ICancellation): Promise<void>;
60 activate(component: IActivatable, ct?: ICancellation): Promise<void>;
63
61
64 getActive(): IActivatable;
62 getActive(): IActivatable;
65 }
63 }
66
64
67 export interface IAsyncComponent {
65 export interface IAsyncComponent {
68 getCompletion(): Promise<void>;
66 getCompletion(): Promise<void>;
69 }
67 }
70
68
71 export interface ICancellable {
69 export interface ICancellable {
72 cancel(reason?: any): void;
70 cancel(reason?: any): void;
73 }
71 }
74
72
75 export interface IObserver<T> {
76 (x:T): void;
77 }
78
79 export interface IObservable<T> {
73 export interface IObservable<T> {
80 on(observer: IObserver<T>): IDestroyable;
74 on(next: (x:T) => void, error?: (e:any) => void, complete?:() => void): IDestroyable;
81
75 next(ct?: ICancellation) : Promise<T>;
82 wait(ct?: ICancellation) : Promise<T>;
83 } No newline at end of file
76 }
@@ -1,207 +1,171
1 import * as format from '../text/format'
1 import * as format from '../text/format'
2 import { argumentNotNull } from '../safe';
2 import { argumentNotNull } from '../safe';
3
3 import * as Observable from '../components/Observable'
4 interface TraceEventHandler {
4 import { IDestroyable } from '../interfaces';
5 (sender: TraceSource, level: number, arg: any): void;
5 import * as TraceEvent from './TraceEvent'
6 }
7
8 interface TraceSourceHandler {
9 (source: TraceSource): void;
10 }
11
12 interface Destroyable {
13 destroy();
14 }
15
6
16 class Registry {
7 class Registry {
17 static readonly instance = new Registry();
8 static readonly instance = new Registry();
18
9
19 private _registry: object = new Object();
10 private _registry: object = new Object();
20 private _listeners: object = new Object();
11 private _listeners: object = new Object();
21 private _nextCookie: number = 1;
12 private _nextCookie: number = 1;
22
13
23 get(id: any): TraceSource {
14 get(id: any): TraceSource {
24 argumentNotNull(id, "id");
15 argumentNotNull(id, "id");
25
16
26 if (this._registry[id])
17 if (this._registry[id])
27 return this._registry[id];
18 return this._registry[id];
28
19
29 var source = new TraceSource(id);
20 var source = new TraceSource(id);
30 this._registry[id] = source;
21 this._registry[id] = source;
31 this._onNewSource(source);
22 this._onNewSource(source);
32
23
33 return source;
24 return source;
34 }
25 }
35
26
36 add(id: any, source: TraceSource) {
27 add(id: any, source: TraceSource) {
37 argumentNotNull(id, "id");
28 argumentNotNull(id, "id");
38 argumentNotNull(source, "source");
29 argumentNotNull(source, "source");
39
30
40 this._registry[id] = source;
31 this._registry[id] = source;
41 this._onNewSource(source);
32 this._onNewSource(source);
42 }
33 }
43
34
44 _onNewSource(source: TraceSource) {
35 _onNewSource(source: TraceSource) {
45 for (let i in this._listeners)
36 for (let i in this._listeners)
46 this._listeners[i].call(null, source);
37 this._listeners[i].call(null, source);
47 }
38 }
48
39
49 on(handler: TraceSourceHandler): Destroyable {
40 on(handler: (source: TraceSource) => void): IDestroyable {
50 argumentNotNull(handler, "handler");
41 argumentNotNull(handler, "handler");
51 var me = this;
42 var me = this;
52
43
53 var cookie = this._nextCookie++;
44 var cookie = this._nextCookie++;
54
45
55 this._listeners[cookie] = handler;
46 this._listeners[cookie] = handler;
56
47
57 for (let i in this._registry)
48 for (let i in this._registry)
58 handler(this._registry[i]);
49 handler(this._registry[i]);
59
50
60 return {
51 return {
61 destroy() {
52 destroy() {
62 delete me._listeners[cookie];
53 delete me._listeners[cookie];
63 }
54 }
64 };
55 };
65 }
56 }
66 }
57 }
67
58
68 class TraceSource {
59 class TraceSource extends Observable<TraceEvent> {
69
70 readonly id: any
60 readonly id: any
71
61
72 // using array will provide faster iteration the with object
73 private _handlers: Array<TraceEventHandler> = new Array<TraceEventHandler>();
74
75 level: number
62 level: number
76
63
77 constructor(id: any) {
64 constructor(id: any) {
65 super();
78 this.id = id || new Object();
66 this.id = id || new Object();
79 }
67 }
80
68
81 on(handler: TraceEventHandler): Destroyable {
82 argumentNotNull(handler, "handler");
83 var me = this;
84 me._handlers.push(handler);
85
86 return {
87 destroy() {
88 me.remove(handler);
89 }
90 }
91 }
92
93 remove(handler: TraceEventHandler): void {
94 let i = this._handlers.indexOf(handler);
95 if (i >= 0)
96 this._handlers.splice(i, 1);
97 }
98
99 protected emit(level: number, arg: any) {
69 protected emit(level: number, arg: any) {
100 this._handlers.forEach(h => {
70 this._notify(new TraceEvent(this, level, arg));
101 try {
102 h(this, level, arg);
103 } catch (e) {
104 // suppress error in log handlers
105 }
106 });
107 }
71 }
108
72
109 isDebugEnabled() {
73 isDebugEnabled() {
110 return this.level >= TraceSource.DebugLevel;
74 return this.level >= TraceSource.DebugLevel;
111 }
75 }
112
76
113 debug(msg: string, ...args: any[]) {
77 debug(msg: string, ...args: any[]) {
114 if (this.isEnabled(TraceSource.DebugLevel))
78 if (this.isEnabled(TraceSource.DebugLevel))
115 this.emit(TraceSource.DebugLevel, format(msg, args));
79 this.emit(TraceSource.DebugLevel, format(msg, args));
116 }
80 }
117
81
118 isLogEnabled() {
82 isLogEnabled() {
119 return this.level >= TraceSource.LogLevel;
83 return this.level >= TraceSource.LogLevel;
120 }
84 }
121
85
122 log(msg: string, ...args: any[]) {
86 log(msg: string, ...args: any[]) {
123 if (this.isEnabled(TraceSource.LogLevel))
87 if (this.isEnabled(TraceSource.LogLevel))
124 this.emit(TraceSource.LogLevel, format(msg, args));
88 this.emit(TraceSource.LogLevel, format(msg, args));
125 }
89 }
126
90
127 isWarnEnabled() {
91 isWarnEnabled() {
128 return this.level >= TraceSource.WarnLevel;
92 return this.level >= TraceSource.WarnLevel;
129 }
93 }
130
94
131 warn(msg: string, ...args: any[]) {
95 warn(msg: string, ...args: any[]) {
132 if (this.isEnabled(TraceSource.WarnLevel))
96 if (this.isEnabled(TraceSource.WarnLevel))
133 this.emit(TraceSource.WarnLevel, format(msg, args));
97 this.emit(TraceSource.WarnLevel, format(msg, args));
134 }
98 }
135
99
136 /**
100 /**
137 * returns true if errors will be recorded.
101 * returns true if errors will be recorded.
138 */
102 */
139 isErrorEnabled() {
103 isErrorEnabled() {
140 return this.level >= TraceSource.ErrorLevel;
104 return this.level >= TraceSource.ErrorLevel;
141 }
105 }
142
106
143 /**
107 /**
144 * Traces a error.
108 * Traces a error.
145 *
109 *
146 * @param msg the message.
110 * @param msg the message.
147 * @param args parameters which will be substituted in the message.
111 * @param args parameters which will be substituted in the message.
148 */
112 */
149 error(msg: string, ...args: any[]) {
113 error(msg: string, ...args: any[]) {
150 if (this.isEnabled(TraceSource.ErrorLevel))
114 if (this.isEnabled(TraceSource.ErrorLevel))
151 this.emit(TraceSource.ErrorLevel, format(msg, args));
115 this.emit(TraceSource.ErrorLevel, format(msg, args));
152 }
116 }
153
117
154 /**
118 /**
155 * Checks whether the specified level is enabled for this
119 * Checks whether the specified level is enabled for this
156 * trace source.
120 * trace source.
157 *
121 *
158 * @param level the trace level which should be checked.
122 * @param level the trace level which should be checked.
159 */
123 */
160 isEnabled(level: number) {
124 isEnabled(level: number) {
161 return (this.level >= level);
125 return (this.level >= level);
162 }
126 }
163
127
164 /**
128 /**
165 * Traces a raw event, passing data as it is to the underlying listeners
129 * Traces a raw event, passing data as it is to the underlying listeners
166 *
130 *
167 * @param level the level of the event
131 * @param level the level of the event
168 * @param arg the data of the event, can be a simple string or any object.
132 * @param arg the data of the event, can be a simple string or any object.
169 */
133 */
170 traceEvent(level: number, arg: any) {
134 traceEvent(level: number, arg: any) {
171 if (this.isEnabled(level))
135 if (this.isEnabled(level))
172 this.emit(level, arg);
136 this.emit(level, arg);
173 }
137 }
174
138
175 /**
139 /**
176 * Register the specified handler to be called for every new and already
140 * Register the specified handler to be called for every new and already
177 * created trace source.
141 * created trace source.
178 *
142 *
179 * @param handler the handler which will be called for each trace source
143 * @param handler the handler which will be called for each trace source
180 */
144 */
181 static on(handler: TraceSourceHandler) {
145 static on(handler: (source: TraceSource) => void) {
182 return Registry.instance.on(handler);
146 return Registry.instance.on(handler);
183 }
147 }
184
148
185 /**
149 /**
186 * Creates or returns already created trace source for the specified id.
150 * Creates or returns already created trace source for the specified id.
187 *
151 *
188 * @param id the id for the trace source
152 * @param id the id for the trace source
189 */
153 */
190 static get(id: any) {
154 static get(id: any) {
191 return Registry.instance.get(id);
155 return Registry.instance.get(id);
192 }
156 }
193 }
157 }
194
158
195 namespace TraceSource {
159 namespace TraceSource {
196 export const DebugLevel = 400;
160 export const DebugLevel = 400;
197
161
198 export const LogLevel = 300;
162 export const LogLevel = 300;
199
163
200 export const WarnLevel = 200;
164 export const WarnLevel = 200;
201
165
202 export const ErrorLevel = 100;
166 export const ErrorLevel = 100;
203
167
204 export const SilentLevel = 0;
168 export const SilentLevel = 0;
205 }
169 }
206
170
207 export = TraceSource; No newline at end of file
171 export = TraceSource;
@@ -1,110 +1,108
1 import * as tape from 'tape';
1 import * as tape from 'tape';
2 import * as ActivatableMixin from '@implab/core/components/ActivatableMixin';
2 import * as ActivatableMixin from '@implab/core/components/ActivatableMixin';
3 import { AsyncComponent } from '@implab/core/components/AsyncComponent';
3 import { AsyncComponent } from '@implab/core/components/AsyncComponent';
4 import { IActivationController } from '@implab/core/components/IActivationController';
4 import { IActivationController, IActivatable, ICancellation } from '@implab/core/interfaces';
5 import { IActivatable } from '@implab/core/components/IActivatable';
5 import { Cancellation } from '@implab/core/Cancellation';
6 import { ICancellation } from '@implab/core/ICancellation';
7 import { EmptyCancellation } from '@implab/core/EmptyCancellation';
8
6
9 class SimpleActivatable extends ActivatableMixin(AsyncComponent) {
7 class SimpleActivatable extends ActivatableMixin(AsyncComponent) {
10
8
11 }
9 }
12
10
13 class MockActivationController implements IActivationController {
11 class MockActivationController implements IActivationController {
14
12
15 _active: IActivatable = null;
13 _active: IActivatable = null;
16
14
17
15
18 getActive() : IActivatable {
16 getActive() : IActivatable {
19 return this._active;
17 return this._active;
20 }
18 }
21
19
22 async deactivate() {
20 async deactivate() {
23 if (this._active)
21 if (this._active)
24 await this._active.deactivate();
22 await this._active.deactivate();
25 this._active = null;
23 this._active = null;
26 }
24 }
27
25
28 async activate(component: IActivatable) {
26 async activate(component: IActivatable) {
29 if (!component || component.isActive())
27 if (!component || component.isActive())
30 return;
28 return;
31 component.setActivationController(this);
29 component.setActivationController(this);
32
30
33 await component.activate();
31 await component.activate();
34 }
32 }
35
33
36 async activating(component: IActivatable, ct: ICancellation = EmptyCancellation.default) {
34 async activating(component: IActivatable, ct: ICancellation = Cancellation.none) {
37 if (component != this._active)
35 if (component != this._active)
38 await this.deactivate();
36 await this.deactivate();
39 }
37 }
40
38
41 async activated(component: IActivatable, ct: ICancellation = EmptyCancellation.default) {
39 async activated(component: IActivatable, ct: ICancellation = Cancellation.none) {
42 this._active = component;
40 this._active = component;
43 }
41 }
44
42
45 async deactivating(component: IActivatable, ct: ICancellation = EmptyCancellation.default) {
43 async deactivating(component: IActivatable, ct: ICancellation = Cancellation.none) {
46
44
47 }
45 }
48
46
49 async deactivated(component: IActivatable, ct: ICancellation = EmptyCancellation.default) {
47 async deactivated(component: IActivatable, ct: ICancellation = Cancellation.none) {
50 if (this._active == component)
48 if (this._active == component)
51 this._active = null;
49 this._active = null;
52 }
50 }
53 }
51 }
54
52
55 tape('simple activation',async function(t){
53 tape('simple activation',async function(t){
56
54
57 let a = new SimpleActivatable();
55 let a = new SimpleActivatable();
58 t.false(a.isActive());
56 t.false(a.isActive());
59
57
60 await a.activate();
58 await a.activate();
61 t.true(a.isActive());
59 t.true(a.isActive());
62
60
63 await a.deactivate();
61 await a.deactivate();
64 t.false(a.isActive());
62 t.false(a.isActive());
65
63
66 t.end();
64 t.end();
67 });
65 });
68
66
69 tape('controller activation', async function(t) {
67 tape('controller activation', async function(t) {
70
68
71 let a = new SimpleActivatable();
69 let a = new SimpleActivatable();
72 let c = new MockActivationController();
70 let c = new MockActivationController();
73
71
74 t.false(a.isActive(), "the component is not active by default");
72 t.false(a.isActive(), "the component is not active by default");
75 t.assert(c.getActive() == null, "the activation controller doesn't have an active component by default");
73 t.assert(c.getActive() == null, "the activation controller doesn't have an active component by default");
76 t.assert(a.getActivationController() == null, "the component doesn't have an activation controller by default");
74 t.assert(a.getActivationController() == null, "the component doesn't have an activation controller by default");
77
75
78 t.comment("Active the component through the controller");
76 t.comment("Active the component through the controller");
79 await c.activate(a);
77 await c.activate(a);
80 t.true(a.isActive(), "The component should successfully activate");
78 t.true(a.isActive(), "The component should successfully activate");
81 t.equal(c.getActive(), a, "The controller should point to the activated component");
79 t.equal(c.getActive(), a, "The controller should point to the activated component");
82 t.equal(a.getActivationController(), c, "The component should point to the controller");
80 t.equal(a.getActivationController(), c, "The component should point to the controller");
83
81
84 t.comment("Deactive the component throug the controller");
82 t.comment("Deactive the component throug the controller");
85 await c.deactivate();
83 await c.deactivate();
86
84
87 t.false(a.isActive(), "The component should successfully deactivate");
85 t.false(a.isActive(), "The component should successfully deactivate");
88 t.equal(c.getActive(), null, "The controller shouldn't point to any component");
86 t.equal(c.getActive(), null, "The controller shouldn't point to any component");
89 t.equal(a.getActivationController(), c, "The componet should point to it's controller");
87 t.equal(a.getActivationController(), c, "The componet should point to it's controller");
90
88
91 t.end();
89 t.end();
92 });
90 });
93
91
94 tape('handle error in onActivating', async function(t) {
92 tape('handle error in onActivating', async function(t) {
95 let a = new SimpleActivatable();
93 let a = new SimpleActivatable();
96
94
97 a.onActivating = async function() {
95 a.onActivating = async function() {
98 throw "Should fail";
96 throw "Should fail";
99 };
97 };
100
98
101 try {
99 try {
102 await a.activate();
100 await a.activate();
103 t.fail("activation should fail");
101 t.fail("activation should fail");
104 } catch {
102 } catch {
105 }
103 }
106
104
107 t.false(a.isActive(), "the component should remain inactive");
105 t.false(a.isActive(), "the component should remain inactive");
108
106
109 t.end();
107 t.end();
110 }); No newline at end of file
108 });
@@ -1,44 +1,62
1 import * as TraceSource from '@implab/core/log/TraceSource'
1 import * as TraceSource from '@implab/core/log/TraceSource'
2 import * as tape from 'tape';
2 import * as tape from 'tape';
3 import * as ConsoleWriter from '@implab/core/log/writers/ConsoleWriter';
3
4
4 const sourceId = 'test/TraceSourceTests';
5 const sourceId = 'test/TraceSourceTests';
5
6
6 tape('trace message', t => {
7 tape('trace message', t => {
7 let trace = TraceSource.get(sourceId);
8 let trace = TraceSource.get(sourceId);
8
9
9 trace.level = TraceSource.DebugLevel;
10 trace.level = TraceSource.DebugLevel;
10
11
11 let h = trace.on((sender,level,msg) => {
12 let h = trace.on((ev) => {
12 t.equal(sender, trace, "sender should be the current trace source");
13 t.equal(ev.source, trace, "sender should be the current trace source");
13 t.equal(TraceSource.DebugLevel, level, "level should be debug level");
14 t.equal(ev.level, TraceSource.DebugLevel, "level should be debug level");
14 t.equal(msg, "Hello, World!", "The message should be a formatted message");
15 t.equal(ev.arg, "Hello, World!", "The message should be a formatted message");
15
16
16 t.end();
17 t.end();
17 });
18 });
18
19
19 trace.debug("Hello, {0}!", "World");
20 trace.debug("Hello, {0}!", "World");
20
21
21 h.destroy();
22 h.destroy();
22 });
23 });
23
24
24 tape('trace event', t => {
25 tape('trace event', t => {
25 let trace = TraceSource.get(sourceId);
26 let trace = TraceSource.get(sourceId);
26
27
27 trace.level = TraceSource.DebugLevel;
28 trace.level = TraceSource.DebugLevel;
28
29
29 let event = {
30 let event = {
30 name: "custom event"
31 name: "custom event"
31 };
32 };
32
33
33 let h = trace.on((sender,level,msg) => {
34 let h = trace.on((ev) => {
34 t.equal(sender, trace, "sender should be the current trace source");
35 t.equal(ev.source, trace, "sender should be the current trace source");
35 t.equal(TraceSource.DebugLevel, level, "level should be debug level");
36 t.equal(ev.level, TraceSource.DebugLevel, "level should be debug level");
36 t.equal(msg, event, "The message should be the specified object");
37 t.equal(ev.arg, event, "The message should be the specified object");
37
38
38 t.end();
39 t.end();
39 });
40 });
40
41
41 trace.traceEvent(TraceSource.DebugLevel, event);
42 trace.traceEvent(TraceSource.DebugLevel, event);
42
43
43 h.destroy();
44 h.destroy();
45 });
46
47 tape('console writer', async t => {
48 let writer = new ConsoleWriter();
49
50 let trace = TraceSource.get(sourceId);
51 trace.level = TraceSource.DebugLevel;
52
53 let p = writer.write(trace);
54
55 trace.log("Hello, {0}!", 'World');
56 trace.warn("Look at me!");
57 trace.error("DIE!");
58
59 console.log("DONE");
60
61 t.end();
44 }); No newline at end of file
62 });
General Comments 0
You need to be logged in to leave comments. Login now