@angular-wave/angular.ts 0.0.26 → 0.0.28
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/README.md +1 -2
- package/dist/angular-ts.esm.js +1 -1
- package/dist/angular-ts.umd.js +1 -1
- package/e2e/unit.spec.ts +2 -1
- package/index.html +8 -9
- package/package.json +1 -1
- package/src/core/pubsub.js +329 -0
- package/src/router/globals.js +0 -5
- package/src/router/hooks/core-resolvables.js +12 -11
- package/src/router/hooks/ignored-transition.js +1 -1
- package/src/router/hooks/lazy-load.js +40 -41
- package/src/router/hooks/redirect-to.js +32 -29
- package/src/router/hooks/update-globals.js +1 -1
- package/src/router/hooks/url.js +33 -24
- package/src/router/hooks/views.js +21 -20
- package/src/router/params/param-factory.js +17 -0
- package/src/router/params/param-types.js +0 -3
- package/src/router/router.js +78 -62
- package/src/router/services.js +2 -4
- package/src/router/state/state-queue-manager.js +5 -7
- package/src/router/state/state-registry.js +8 -10
- package/src/router/state/state-service.js +34 -33
- package/src/router/transition/hook-builder.js +2 -2
- package/src/router/transition/transition-hook.js +3 -9
- package/src/router/transition/transition-service.js +12 -30
- package/src/router/transition/transition.js +28 -25
- package/src/router/url/url-config.js +1 -49
- package/src/router/url/url-matcher-factory.js +10 -51
- package/src/router/url/url-router.js +27 -17
- package/src/router/url/url-rule.js +9 -13
- package/src/router/url/url-rules.js +3 -7
- package/src/router/url/url-service.js +134 -97
- package/src/router/view/view.js +3 -3
- package/src/shared/hof.js +1 -1
- package/test/angular.spec.js +1 -0
- package/test/aria/aria.spec.js +2 -1
- package/test/core/interval.spec.js +1 -1
- package/test/core/pubsub.spec.js +314 -0
- package/test/directive/bind.spec.js +2 -1
- package/test/directive/boolean.spec.js +4 -2
- package/test/directive/change.spec.js +1 -1
- package/test/directive/class.spec.js +1 -0
- package/test/directive/click.spec.js +2 -1
- package/test/directive/cloak.spec.js +1 -2
- package/test/directive/{constoller.spec.js → controller.spec.js} +1 -0
- package/test/directive/element-style.spec.js +1 -0
- package/test/directive/event.spec.js +1 -1
- package/test/directive/href.spec.js +2 -1
- package/test/directive/init.spec.js +1 -0
- package/test/directive/input.spec.js +200 -285
- package/test/directive/list.spec.js +2 -1
- package/test/directive/model.spec.js +1 -0
- package/test/directive/non-bindable.spec.js +2 -1
- package/test/directive/script.spec.js +1 -0
- package/test/directive/scrset.spec.js +2 -1
- package/test/directive/show-hide.spec.js +1 -0
- package/test/directive/src.spec.js +2 -1
- package/test/directive/style.spec.js +1 -0
- package/test/directive/switch.spec.js +2 -1
- package/test/directive/validators.spec.js +1 -1
- package/test/router/state-directives.spec.js +72 -72
- package/test/router/state.spec.js +5 -5
- package/test/router/template-factory.spec.js +2 -2
- package/test/router/view-directive.spec.js +65 -65
- package/test/router/view-hook.spec.js +13 -13
- package/test/router/view-scroll.spec.js +3 -3
- package/test/router/view.spec.js +2 -2
- package/types/router/core/common/coreservices.d.ts +2 -3
- package/types/router/core/globals.d.ts +1 -4
- package/types/router/core/interface.d.ts +2 -8
- package/types/router/core/params/paramTypes.d.ts +0 -1
- package/types/router/core/router.d.ts +2 -3
- package/types/router/core/state/stateQueueManager.d.ts +1 -3
- package/types/router/core/state/stateRegistry.d.ts +0 -2
- package/types/router/core/state/stateService.d.ts +1 -2
- package/types/router/core/transition/interface.d.ts +3 -3
- package/types/router/core/transition/transitionService.d.ts +1 -2
- package/types/router/core/url/urlConfig.d.ts +1 -2
- package/types/router/core/url/urlRules.d.ts +1 -2
- package/types/router/core/url/urlService.d.ts +1 -2
- package/types/router/locationServices.d.ts +0 -1
- package/src/router/location-services.js +0 -67
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { isString } from "../../shared/utils";
|
|
1
|
+
import { isDefined, isObject, isString } from "../../shared/utils";
|
|
2
2
|
import { is, pattern } from "../../shared/hof";
|
|
3
3
|
import { UrlRules } from "./url-rules";
|
|
4
4
|
import { UrlConfig } from "./url-config";
|
|
5
5
|
import { TargetState } from "../state/target-state";
|
|
6
|
+
import { removeFrom } from "../../shared/common";
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
9
|
* API for URL management
|
|
8
10
|
*/
|
|
9
11
|
export class UrlService {
|
|
10
12
|
/**
|
|
11
|
-
*
|
|
12
|
-
* @param {import('../router').UIRouter} router
|
|
13
|
+
* @param {angular.ILocationProvider} $locationProvider
|
|
13
14
|
*/
|
|
14
|
-
constructor(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
this.router = router;
|
|
15
|
+
constructor($locationProvider, urlRuleFactory, stateService) {
|
|
16
|
+
this.stateService = stateService;
|
|
17
|
+
|
|
18
|
+
this.$locationProvider = $locationProvider;
|
|
19
19
|
|
|
20
20
|
/** @type {boolean} */
|
|
21
21
|
this.interceptDeferred = false;
|
|
@@ -25,69 +25,15 @@ export class UrlService {
|
|
|
25
25
|
* See: [[UrlRules]] for details
|
|
26
26
|
* @type {UrlRules}
|
|
27
27
|
*/
|
|
28
|
-
this.rules = new UrlRules(
|
|
28
|
+
this.rules = new UrlRules(urlRuleFactory);
|
|
29
29
|
/**
|
|
30
30
|
* The nested [[UrlConfig]] API to configure the URL and retrieve URL information
|
|
31
31
|
*
|
|
32
32
|
* See: [[UrlConfig]] for details
|
|
33
33
|
* @type {UrlConfig}
|
|
34
34
|
*/
|
|
35
|
-
this.config = new UrlConfig(
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Gets the current url, or updates the url
|
|
39
|
-
*
|
|
40
|
-
* ### Getting the current URL
|
|
41
|
-
*
|
|
42
|
-
* When no arguments are passed, returns the current URL.
|
|
43
|
-
* The URL is normalized using the internal [[path]]/[[search]]/[[hash]] values.
|
|
44
|
-
*
|
|
45
|
-
* For example, the URL may be stored in the hash ([[HashLocationServices]]) or
|
|
46
|
-
* have a base HREF prepended ([[PushStateLocationServices]]).
|
|
47
|
-
*
|
|
48
|
-
* The raw URL in the browser might be:
|
|
49
|
-
*
|
|
50
|
-
* ```
|
|
51
|
-
* http://mysite.com/somepath/index.html#/internal/path/123?param1=foo#anchor
|
|
52
|
-
* ```
|
|
53
|
-
*
|
|
54
|
-
* or
|
|
55
|
-
*
|
|
56
|
-
* ```
|
|
57
|
-
* http://mysite.com/basepath/internal/path/123?param1=foo#anchor
|
|
58
|
-
* ```
|
|
59
|
-
*
|
|
60
|
-
* then this method returns:
|
|
61
|
-
*
|
|
62
|
-
* ```
|
|
63
|
-
* /internal/path/123?param1=foo#anchor
|
|
64
|
-
* ```
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
* #### Example:
|
|
68
|
-
* ```js
|
|
69
|
-
* locationServices.url(); // "/some/path?query=value#anchor"
|
|
70
|
-
* ```
|
|
71
|
-
*
|
|
72
|
-
* ### Updating the URL
|
|
73
|
-
*
|
|
74
|
-
* When `newurl` arguments is provided, changes the URL to reflect `newurl`
|
|
75
|
-
*
|
|
76
|
-
* #### Example:
|
|
77
|
-
* ```js
|
|
78
|
-
* locationServices.url("/some/path?query=value#anchor", true);
|
|
79
|
-
* ```
|
|
80
|
-
*
|
|
81
|
-
* @param {string} newurl The new value for the URL.
|
|
82
|
-
* This url should reflect only the new internal [[path]], [[search]], and [[hash]] values.
|
|
83
|
-
* It should not include the protocol, site, port, or base path of an absolute HREF.
|
|
84
|
-
* @param {boolean} replace When true, replaces the current history entry (instead of appending it) with this new url
|
|
85
|
-
* @param {any} state The history's state object, i.e., pushState (if the LocationServices implementation supports it)
|
|
86
|
-
*
|
|
87
|
-
* @return the url (after potentially being processed)
|
|
88
|
-
*/
|
|
89
|
-
this.url = (newurl, replace, state) =>
|
|
90
|
-
this.router.locationService.url(newurl, replace, state);
|
|
35
|
+
this.config = new UrlConfig();
|
|
36
|
+
|
|
91
37
|
/**
|
|
92
38
|
* Gets the path part of the current url
|
|
93
39
|
*
|
|
@@ -95,7 +41,7 @@ export class UrlService {
|
|
|
95
41
|
*
|
|
96
42
|
* @return the path portion of the url
|
|
97
43
|
*/
|
|
98
|
-
this.path = () => this.
|
|
44
|
+
this.path = () => this.$location.path();
|
|
99
45
|
/**
|
|
100
46
|
* Gets the search part of the current url as an object
|
|
101
47
|
*
|
|
@@ -103,7 +49,7 @@ export class UrlService {
|
|
|
103
49
|
*
|
|
104
50
|
* @return the search (query) portion of the url, as an object
|
|
105
51
|
*/
|
|
106
|
-
this.search = () => this.
|
|
52
|
+
this.search = () => this.$location.search();
|
|
107
53
|
/**
|
|
108
54
|
* Gets the hash part of the current url
|
|
109
55
|
*
|
|
@@ -111,30 +57,103 @@ export class UrlService {
|
|
|
111
57
|
*
|
|
112
58
|
* @return the hash (anchor) portion of the url
|
|
113
59
|
*/
|
|
114
|
-
this.hash = () => this.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
* ```js
|
|
124
|
-
* let deregisterFn = locationServices.onChange((evt) => console.log("url change", evt));
|
|
125
|
-
* ```
|
|
126
|
-
*
|
|
127
|
-
* @param callback a function that will be called when the url is changing
|
|
128
|
-
* @return a function that de-registers the callback
|
|
129
|
-
*/
|
|
130
|
-
this.onChange = (callback) =>
|
|
131
|
-
this.router.locationService.onChange(callback);
|
|
60
|
+
this.hash = () => this.$location.hash();
|
|
61
|
+
|
|
62
|
+
this._urlListeners = [];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
html5Mode() {
|
|
66
|
+
let html5Mode = this.$locationProvider.html5Mode();
|
|
67
|
+
html5Mode = isObject(html5Mode) ? html5Mode.enabled : html5Mode;
|
|
68
|
+
return html5Mode && typeof history !== "undefined";
|
|
132
69
|
}
|
|
133
70
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
71
|
+
baseHref() {
|
|
72
|
+
return (
|
|
73
|
+
this._baseHref ||
|
|
74
|
+
(this._baseHref = this.$browser.baseHref() || window.location.pathname)
|
|
75
|
+
);
|
|
137
76
|
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Gets the current url, or updates the url
|
|
80
|
+
*
|
|
81
|
+
* ### Getting the current URL
|
|
82
|
+
*
|
|
83
|
+
* When no arguments are passed, returns the current URL.
|
|
84
|
+
* The URL is normalized using the internal [[path]]/[[search]]/[[hash]] values.
|
|
85
|
+
*
|
|
86
|
+
* For example, the URL may be stored in the hash ([[HashLocationServices]]) or
|
|
87
|
+
* have a base HREF prepended ([[PushStateLocationServices]]).
|
|
88
|
+
*
|
|
89
|
+
* The raw URL in the browser might be:
|
|
90
|
+
*
|
|
91
|
+
* ```
|
|
92
|
+
* http://mysite.com/somepath/index.html#/internal/path/123?param1=foo#anchor
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* or
|
|
96
|
+
*
|
|
97
|
+
* ```
|
|
98
|
+
* http://mysite.com/basepath/internal/path/123?param1=foo#anchor
|
|
99
|
+
* ```
|
|
100
|
+
*
|
|
101
|
+
* then this method returns:
|
|
102
|
+
*
|
|
103
|
+
* ```
|
|
104
|
+
* /internal/path/123?param1=foo#anchor
|
|
105
|
+
* ```
|
|
106
|
+
*
|
|
107
|
+
*
|
|
108
|
+
* #### Example:
|
|
109
|
+
* ```js
|
|
110
|
+
* locationServices.url(); // "/some/path?query=value#anchor"
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* ### Updating the URL
|
|
114
|
+
*
|
|
115
|
+
* When `newurl` arguments is provided, changes the URL to reflect `newurl`
|
|
116
|
+
*
|
|
117
|
+
* #### Example:
|
|
118
|
+
* ```js
|
|
119
|
+
* locationServices.url("/some/path?query=value#anchor", true);
|
|
120
|
+
* ```
|
|
121
|
+
*
|
|
122
|
+
* @param {string} newUrl The new value for the URL.
|
|
123
|
+
* This url should reflect only the new internal [[path]], [[search]], and [[hash]] values.
|
|
124
|
+
* It should not include the protocol, site, port, or base path of an absolute HREF.
|
|
125
|
+
* @param {boolean} replace When true, replaces the current history entry (instead of appending it) with this new url
|
|
126
|
+
* @param {any} state The history's state object, i.e., pushState (if the LocationServices implementation supports it)
|
|
127
|
+
*
|
|
128
|
+
* @return the url (after potentially being processed)
|
|
129
|
+
*/
|
|
130
|
+
url(newUrl, replace = false, state) {
|
|
131
|
+
if (isDefined(newUrl)) this.$location.url(newUrl);
|
|
132
|
+
if (replace) this.$location.replace();
|
|
133
|
+
if (state) this.$location.state(state);
|
|
134
|
+
return this.$location.url();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @internal
|
|
139
|
+
*
|
|
140
|
+
* Registers a low level url change handler
|
|
141
|
+
*
|
|
142
|
+
* Note: Because this is a low level handler, it's not recommended for general use.
|
|
143
|
+
*
|
|
144
|
+
* #### Example:
|
|
145
|
+
* ```js
|
|
146
|
+
* let deregisterFn = locationServices.onChange((evt) => console.log("url change", evt));
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* @param callback a function that will be called when the url is changing
|
|
150
|
+
* @return a function that de-registers the callback
|
|
151
|
+
*/
|
|
152
|
+
onChange(callback) {
|
|
153
|
+
this._urlListeners.push(callback);
|
|
154
|
+
return () => removeFrom(this._urlListeners)(callback);
|
|
155
|
+
}
|
|
156
|
+
|
|
138
157
|
/**
|
|
139
158
|
* Gets the current URL parts
|
|
140
159
|
*
|
|
@@ -165,15 +184,18 @@ export class UrlService {
|
|
|
165
184
|
*/
|
|
166
185
|
sync(evt) {
|
|
167
186
|
if (evt && evt.defaultPrevented) return;
|
|
168
|
-
const
|
|
187
|
+
const stateService = this.stateService;
|
|
169
188
|
const url = {
|
|
170
|
-
path:
|
|
171
|
-
search:
|
|
172
|
-
hash:
|
|
189
|
+
path: this.path(),
|
|
190
|
+
search: this.search(),
|
|
191
|
+
hash: this.hash(),
|
|
173
192
|
};
|
|
193
|
+
/**
|
|
194
|
+
* @type {angular.MatchResult}
|
|
195
|
+
*/
|
|
174
196
|
const best = this.match(url);
|
|
175
197
|
const applyResult = pattern([
|
|
176
|
-
[isString, (newurl) =>
|
|
198
|
+
[isString, (newurl) => this.url(newurl, true)],
|
|
177
199
|
[
|
|
178
200
|
TargetState.isDef,
|
|
179
201
|
(def) => stateService.go(def.state, def.params, def.options),
|
|
@@ -184,7 +206,8 @@ export class UrlService {
|
|
|
184
206
|
stateService.go(target.state(), target.params(), target.options()),
|
|
185
207
|
],
|
|
186
208
|
]);
|
|
187
|
-
|
|
209
|
+
|
|
210
|
+
applyResult(best && best.rule.handler(best.match, url));
|
|
188
211
|
}
|
|
189
212
|
/**
|
|
190
213
|
* Starts or stops listening for URL changes
|
|
@@ -214,8 +237,7 @@ export class UrlService {
|
|
|
214
237
|
delete this._stopListeningFn;
|
|
215
238
|
} else {
|
|
216
239
|
return (this._stopListeningFn =
|
|
217
|
-
this._stopListeningFn ||
|
|
218
|
-
this.router.urlService.onChange((evt) => this.sync(evt)));
|
|
240
|
+
this._stopListeningFn || this.onChange((evt) => this.sync(evt)));
|
|
219
241
|
}
|
|
220
242
|
}
|
|
221
243
|
/**
|
|
@@ -251,13 +273,18 @@ export class UrlService {
|
|
|
251
273
|
*
|
|
252
274
|
* Given a URL (as a [[UrlParts]] object), check all rules and determine the best matching rule.
|
|
253
275
|
* Return the result as a [[MatchResult]].
|
|
276
|
+
* @returns {angular.MatchResult}
|
|
254
277
|
*/
|
|
255
278
|
match(url) {
|
|
256
279
|
url = Object.assign({ path: "", search: {}, hash: "" }, url);
|
|
257
280
|
const rules = this.rules.rules();
|
|
258
281
|
// Checks a single rule. Returns { rule: rule, match: match, weight: weight } if it matched, or undefined
|
|
282
|
+
/**
|
|
283
|
+
*
|
|
284
|
+
* @param {import("./url-rule").BaseUrlRule} rule
|
|
285
|
+
*/
|
|
259
286
|
const checkRule = (rule) => {
|
|
260
|
-
const match = rule.match(url
|
|
287
|
+
const match = rule.match(url);
|
|
261
288
|
return match && { match, rule, weight: rule.matchPriority(match) };
|
|
262
289
|
};
|
|
263
290
|
// The rules are pre-sorted.
|
|
@@ -275,4 +302,14 @@ export class UrlService {
|
|
|
275
302
|
}
|
|
276
303
|
return best;
|
|
277
304
|
}
|
|
305
|
+
|
|
306
|
+
_runtimeServices($rootScope, $location, $browser) {
|
|
307
|
+
/** @type {angular.ILocationService} */
|
|
308
|
+
this.$location = $location;
|
|
309
|
+
this.$browser = $browser;
|
|
310
|
+
// Bind $locationChangeSuccess to the listeners registered in LocationService.onChange
|
|
311
|
+
$rootScope.$on("$locationChangeSuccess", (evt) =>
|
|
312
|
+
this._urlListeners.forEach((fn) => fn(evt)),
|
|
313
|
+
);
|
|
314
|
+
}
|
|
278
315
|
}
|
package/src/router/view/view.js
CHANGED
|
@@ -26,9 +26,9 @@ import { trace } from "../common/trace";
|
|
|
26
26
|
*/
|
|
27
27
|
export class ViewService {
|
|
28
28
|
/**
|
|
29
|
-
* @param {
|
|
29
|
+
* @param {number} $id
|
|
30
30
|
*/
|
|
31
|
-
constructor(
|
|
31
|
+
constructor($id) {
|
|
32
32
|
this._uiViews = [];
|
|
33
33
|
this._viewConfigs = [];
|
|
34
34
|
this._viewConfigFactories = {};
|
|
@@ -37,7 +37,7 @@ export class ViewService {
|
|
|
37
37
|
_rootViewContext: this._rootViewContext.bind(this),
|
|
38
38
|
_viewConfigFactory: this._viewConfigFactory.bind(this),
|
|
39
39
|
_registeredUIView: (id) =>
|
|
40
|
-
find(this._uiViews, (view) => `${
|
|
40
|
+
find(this._uiViews, (view) => `${$id}.${view.id}` === id),
|
|
41
41
|
_registeredUIViews: () => this._uiViews,
|
|
42
42
|
_activeViewConfigs: () => this._viewConfigs,
|
|
43
43
|
_onSync: (listener) => {
|
package/src/shared/hof.js
CHANGED
package/test/angular.spec.js
CHANGED
package/test/aria/aria.spec.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createInjector } from "../../src/injector";
|
|
2
2
|
import { publishExternalAPI } from "../../src/public";
|
|
3
|
-
import { dealoc } from "../../src/jqLite";
|
|
3
|
+
import { dealoc, jqLite } from "../../src/jqLite";
|
|
4
4
|
|
|
5
5
|
describe("$aria", () => {
|
|
6
6
|
let scope;
|
|
@@ -17,6 +17,7 @@ describe("$aria", () => {
|
|
|
17
17
|
|
|
18
18
|
afterEach(() => {
|
|
19
19
|
dealoc(element);
|
|
20
|
+
jqLite.CACHE.clear();
|
|
20
21
|
});
|
|
21
22
|
|
|
22
23
|
describe("with `ngAriaDisable`", () => {
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { PubSub } from "../../src/core/pubsub";
|
|
2
|
+
|
|
3
|
+
describe("PubSub", function () {
|
|
4
|
+
let pubsub;
|
|
5
|
+
let asyncPubsub;
|
|
6
|
+
|
|
7
|
+
beforeEach(function () {
|
|
8
|
+
pubsub = new PubSub();
|
|
9
|
+
asyncPubsub = new PubSub(true);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
afterEach(function () {
|
|
13
|
+
asyncPubsub.dispose();
|
|
14
|
+
pubsub.dispose();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("should create a PubSub instance", function () {
|
|
18
|
+
expect(pubsub).not.toBeNull();
|
|
19
|
+
expect(pubsub instanceof PubSub).toBe(true);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should dispose of the PubSub instance", function () {
|
|
23
|
+
expect(pubsub.isDisposed()).toBe(false);
|
|
24
|
+
pubsub.dispose();
|
|
25
|
+
expect(pubsub.isDisposed()).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("should subscribe and unsubscribe correctly", function () {
|
|
29
|
+
function foo1() {}
|
|
30
|
+
function bar1() {}
|
|
31
|
+
function foo2() {}
|
|
32
|
+
function bar2() {}
|
|
33
|
+
|
|
34
|
+
expect(pubsub.getCount("foo")).toBe(0);
|
|
35
|
+
expect(pubsub.getCount("bar")).toBe(0);
|
|
36
|
+
|
|
37
|
+
pubsub.subscribe("foo", foo1);
|
|
38
|
+
expect(pubsub.getCount("foo")).toBe(1);
|
|
39
|
+
expect(pubsub.getCount("bar")).toBe(0);
|
|
40
|
+
|
|
41
|
+
pubsub.subscribe("bar", bar1);
|
|
42
|
+
expect(pubsub.getCount("foo")).toBe(1);
|
|
43
|
+
expect(pubsub.getCount("bar")).toBe(1);
|
|
44
|
+
|
|
45
|
+
pubsub.subscribe("foo", foo2);
|
|
46
|
+
expect(pubsub.getCount("foo")).toBe(2);
|
|
47
|
+
expect(pubsub.getCount("bar")).toBe(1);
|
|
48
|
+
|
|
49
|
+
pubsub.subscribe("bar", bar2);
|
|
50
|
+
expect(pubsub.getCount("foo")).toBe(2);
|
|
51
|
+
expect(pubsub.getCount("bar")).toBe(2);
|
|
52
|
+
|
|
53
|
+
expect(pubsub.unsubscribe("foo", foo1)).toBe(true);
|
|
54
|
+
expect(pubsub.getCount("foo")).toBe(1);
|
|
55
|
+
expect(pubsub.getCount("bar")).toBe(2);
|
|
56
|
+
|
|
57
|
+
expect(pubsub.unsubscribe("foo", foo2)).toBe(true);
|
|
58
|
+
expect(pubsub.getCount("foo")).toBe(0);
|
|
59
|
+
expect(pubsub.getCount("bar")).toBe(2);
|
|
60
|
+
|
|
61
|
+
expect(pubsub.unsubscribe("bar", bar1)).toBe(true);
|
|
62
|
+
expect(pubsub.getCount("foo")).toBe(0);
|
|
63
|
+
expect(pubsub.getCount("bar")).toBe(1);
|
|
64
|
+
|
|
65
|
+
expect(pubsub.unsubscribe("bar", bar2)).toBe(true);
|
|
66
|
+
expect(pubsub.getCount("foo")).toBe(0);
|
|
67
|
+
expect(pubsub.getCount("bar")).toBe(0);
|
|
68
|
+
|
|
69
|
+
expect(pubsub.unsubscribe("baz", foo1)).toBe(false);
|
|
70
|
+
expect(pubsub.unsubscribe("foo", () => {})).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("should subscribe and unsubscribe with context correctly", function () {
|
|
74
|
+
function foo() {}
|
|
75
|
+
function bar() {}
|
|
76
|
+
|
|
77
|
+
const contextA = {};
|
|
78
|
+
const contextB = {};
|
|
79
|
+
|
|
80
|
+
expect(pubsub.getCount("X")).toBe(0);
|
|
81
|
+
|
|
82
|
+
pubsub.subscribe("X", foo, contextA);
|
|
83
|
+
expect(pubsub.getCount("X")).toBe(1);
|
|
84
|
+
|
|
85
|
+
pubsub.subscribe("X", bar);
|
|
86
|
+
expect(pubsub.getCount("X")).toBe(2);
|
|
87
|
+
|
|
88
|
+
pubsub.subscribe("X", bar, contextB);
|
|
89
|
+
expect(pubsub.getCount("X")).toBe(3);
|
|
90
|
+
|
|
91
|
+
expect(pubsub.unsubscribe("X", foo, contextB)).toBe(false);
|
|
92
|
+
|
|
93
|
+
expect(pubsub.unsubscribe("X", foo, contextA)).toBe(true);
|
|
94
|
+
expect(pubsub.getCount("X")).toBe(2);
|
|
95
|
+
|
|
96
|
+
expect(pubsub.unsubscribe("X", bar)).toBe(true);
|
|
97
|
+
expect(pubsub.getCount("X")).toBe(1);
|
|
98
|
+
|
|
99
|
+
expect(pubsub.unsubscribe("X", bar, contextB)).toBe(true);
|
|
100
|
+
expect(pubsub.getCount("X")).toBe(0);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("should subscribe once correctly", function () {
|
|
104
|
+
let called;
|
|
105
|
+
let context;
|
|
106
|
+
|
|
107
|
+
called = false;
|
|
108
|
+
pubsub.subscribeOnce("someTopic", () => {
|
|
109
|
+
called = true;
|
|
110
|
+
});
|
|
111
|
+
expect(pubsub.getCount("someTopic")).toBe(1);
|
|
112
|
+
expect(called).toBe(false);
|
|
113
|
+
|
|
114
|
+
pubsub.publish("someTopic");
|
|
115
|
+
expect(pubsub.getCount("someTopic")).toBe(0);
|
|
116
|
+
expect(called).toBe(true);
|
|
117
|
+
|
|
118
|
+
context = { called: false };
|
|
119
|
+
pubsub.subscribeOnce(
|
|
120
|
+
"someTopic",
|
|
121
|
+
function () {
|
|
122
|
+
this.called = true;
|
|
123
|
+
},
|
|
124
|
+
context,
|
|
125
|
+
);
|
|
126
|
+
expect(pubsub.getCount("someTopic")).toBe(1);
|
|
127
|
+
expect(context.called).toBe(false);
|
|
128
|
+
|
|
129
|
+
pubsub.publish("someTopic");
|
|
130
|
+
expect(pubsub.getCount("someTopic")).toBe(0);
|
|
131
|
+
expect(context.called).toBe(true);
|
|
132
|
+
|
|
133
|
+
context = { called: false, value: 0 };
|
|
134
|
+
pubsub.subscribeOnce(
|
|
135
|
+
"someTopic",
|
|
136
|
+
function (value) {
|
|
137
|
+
this.called = true;
|
|
138
|
+
this.value = value;
|
|
139
|
+
},
|
|
140
|
+
context,
|
|
141
|
+
);
|
|
142
|
+
expect(pubsub.getCount("someTopic")).toBe(1);
|
|
143
|
+
expect(context.called).toBe(false);
|
|
144
|
+
expect(context.value).toBe(0);
|
|
145
|
+
|
|
146
|
+
pubsub.publish("someTopic", 17);
|
|
147
|
+
expect(pubsub.getCount("someTopic")).toBe(0);
|
|
148
|
+
expect(context.called).toBe(true);
|
|
149
|
+
expect(context.value).toBe(17);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("should async subscribe once correctly", function (done) {
|
|
153
|
+
let callCount = 0;
|
|
154
|
+
asyncPubsub.subscribeOnce("someTopic", () => {
|
|
155
|
+
callCount++;
|
|
156
|
+
});
|
|
157
|
+
expect(asyncPubsub.getCount("someTopic")).toBe(1);
|
|
158
|
+
|
|
159
|
+
asyncPubsub.publish("someTopic");
|
|
160
|
+
asyncPubsub.publish("someTopic");
|
|
161
|
+
|
|
162
|
+
setTimeout(() => {
|
|
163
|
+
expect(asyncPubsub.getCount("someTopic")).toBe(0);
|
|
164
|
+
expect(callCount).toBe(1);
|
|
165
|
+
done();
|
|
166
|
+
}, 0);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("should async subscribe once with context correctly", function (done) {
|
|
170
|
+
const context = { callCount: 0 };
|
|
171
|
+
asyncPubsub.subscribeOnce(
|
|
172
|
+
"someTopic",
|
|
173
|
+
function () {
|
|
174
|
+
this.callCount++;
|
|
175
|
+
},
|
|
176
|
+
context,
|
|
177
|
+
);
|
|
178
|
+
expect(asyncPubsub.getCount("someTopic")).toBe(1);
|
|
179
|
+
|
|
180
|
+
asyncPubsub.publish("someTopic");
|
|
181
|
+
asyncPubsub.publish("someTopic");
|
|
182
|
+
|
|
183
|
+
setTimeout(() => {
|
|
184
|
+
expect(asyncPubsub.getCount("someTopic")).toBe(0);
|
|
185
|
+
expect(context.callCount).toBe(1);
|
|
186
|
+
done();
|
|
187
|
+
}, 0);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("should async subscribe once with context and value correctly", function (done) {
|
|
191
|
+
const context = { callCount: 0, value: 0 };
|
|
192
|
+
asyncPubsub.subscribeOnce(
|
|
193
|
+
"someTopic",
|
|
194
|
+
function (value) {
|
|
195
|
+
this.callCount++;
|
|
196
|
+
this.value = value;
|
|
197
|
+
},
|
|
198
|
+
context,
|
|
199
|
+
);
|
|
200
|
+
expect(asyncPubsub.getCount("someTopic")).toBe(1);
|
|
201
|
+
|
|
202
|
+
asyncPubsub.publish("someTopic", 17);
|
|
203
|
+
asyncPubsub.publish("someTopic", 42);
|
|
204
|
+
|
|
205
|
+
setTimeout(() => {
|
|
206
|
+
expect(asyncPubsub.getCount("someTopic")).toBe(0);
|
|
207
|
+
expect(context.callCount).toBe(1);
|
|
208
|
+
expect(context.value).toBe(17);
|
|
209
|
+
done();
|
|
210
|
+
}, 0);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it("should subscribe once with bound function correctly", function () {
|
|
214
|
+
const context = { called: false, value: 0 };
|
|
215
|
+
|
|
216
|
+
function subscriber(value) {
|
|
217
|
+
this.called = true;
|
|
218
|
+
this.value = value;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
pubsub.subscribeOnce("someTopic", subscriber.bind(context));
|
|
222
|
+
expect(pubsub.getCount("someTopic")).toBe(1);
|
|
223
|
+
expect(context.called).toBe(false);
|
|
224
|
+
expect(context.value).toBe(0);
|
|
225
|
+
|
|
226
|
+
pubsub.publish("someTopic", 17);
|
|
227
|
+
expect(pubsub.getCount("someTopic")).toBe(0);
|
|
228
|
+
expect(context.called).toBe(true);
|
|
229
|
+
expect(context.value).toBe(17);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it("should subscribe once with partial function correctly", function () {
|
|
233
|
+
let called = false;
|
|
234
|
+
let value = 0;
|
|
235
|
+
|
|
236
|
+
function subscriber(hasBeenCalled, newValue) {
|
|
237
|
+
called = hasBeenCalled;
|
|
238
|
+
value = newValue;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
pubsub.subscribeOnce("someTopic", subscriber.bind(null, true));
|
|
242
|
+
expect(pubsub.getCount("someTopic")).toBe(1);
|
|
243
|
+
expect(called).toBe(false);
|
|
244
|
+
expect(value).toBe(0);
|
|
245
|
+
|
|
246
|
+
pubsub.publish("someTopic", 17);
|
|
247
|
+
expect(pubsub.getCount("someTopic")).toBe(0);
|
|
248
|
+
expect(called).toBe(true);
|
|
249
|
+
expect(value).toBe(17);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it("should handle self resubscribe correctly", function () {
|
|
253
|
+
let value = null;
|
|
254
|
+
|
|
255
|
+
function resubscribe(iteration, newValue) {
|
|
256
|
+
pubsub.subscribeOnce("someTopic", resubscribe.bind(null, iteration + 1));
|
|
257
|
+
value = `${newValue}:${iteration}`;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
pubsub.subscribeOnce("someTopic", resubscribe.bind(null, 0));
|
|
261
|
+
expect(pubsub.getCount("someTopic")).toBe(1);
|
|
262
|
+
expect(value).toBeNull();
|
|
263
|
+
|
|
264
|
+
pubsub.publish("someTopic", "foo");
|
|
265
|
+
expect(pubsub.getCount("someTopic")).toBe(1);
|
|
266
|
+
expect(value).toBe("foo:0");
|
|
267
|
+
|
|
268
|
+
pubsub.publish("someTopic", "bar");
|
|
269
|
+
expect(pubsub.getCount("someTopic")).toBe(1);
|
|
270
|
+
expect(value).toBe("bar:1");
|
|
271
|
+
|
|
272
|
+
pubsub.publish("someTopic", "baz");
|
|
273
|
+
expect(pubsub.getCount("someTopic")).toBe(1);
|
|
274
|
+
expect(value).toBe("baz:2");
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it("should handle async self resubscribe correctly", function (done) {
|
|
278
|
+
let value = null;
|
|
279
|
+
|
|
280
|
+
function resubscribe(iteration, newValue) {
|
|
281
|
+
asyncPubsub.subscribeOnce(
|
|
282
|
+
"someTopic",
|
|
283
|
+
resubscribe.bind(null, iteration + 1),
|
|
284
|
+
);
|
|
285
|
+
value = `${newValue}:${iteration}`;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
asyncPubsub.subscribeOnce("someTopic", resubscribe.bind(null, 0));
|
|
289
|
+
expect(asyncPubsub.getCount("someTopic")).toBe(1);
|
|
290
|
+
expect(value).toBeNull();
|
|
291
|
+
|
|
292
|
+
asyncPubsub.publish("someTopic", "foo");
|
|
293
|
+
|
|
294
|
+
setTimeout(() => {
|
|
295
|
+
expect(asyncPubsub.getCount("someTopic")).toBe(1);
|
|
296
|
+
expect(value).toBe("foo:0");
|
|
297
|
+
|
|
298
|
+
asyncPubsub.publish("someTopic", "bar");
|
|
299
|
+
|
|
300
|
+
setTimeout(() => {
|
|
301
|
+
expect(asyncPubsub.getCount("someTopic")).toBe(1);
|
|
302
|
+
expect(value).toBe("bar:1");
|
|
303
|
+
|
|
304
|
+
asyncPubsub.publish("someTopic", "baz");
|
|
305
|
+
|
|
306
|
+
setTimeout(() => {
|
|
307
|
+
expect(asyncPubsub.getCount("someTopic")).toBe(1);
|
|
308
|
+
expect(value).toBe("baz:2");
|
|
309
|
+
done();
|
|
310
|
+
}, 0);
|
|
311
|
+
}, 0);
|
|
312
|
+
}, 0);
|
|
313
|
+
});
|
|
314
|
+
});
|