UNPKG

19.6 kBJavaScriptView Raw
1/**
2 * @license Angular v9.0.3
3 * (c) 2010-2020 Google LLC. https://angular.io/
4 * License: MIT
5 */
6
7import { EventEmitter, Injectable, InjectionToken, Inject, Optional } from '@angular/core';
8import { LocationStrategy } from '@angular/common';
9import { Subject } from 'rxjs';
10
11/**
12 * @fileoverview added by tsickle
13 * Generated from: packages/common/testing/src/location_mock.ts
14 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
15 */
16/**
17 * A spy for {\@link Location} that allows tests to fire simulated location events.
18 *
19 * \@publicApi
20 */
21class SpyLocation {
22 constructor() {
23 this.urlChanges = [];
24 this._history = [new LocationState('', '', null)];
25 this._historyIndex = 0;
26 /**
27 * \@internal
28 */
29 this._subject = new EventEmitter();
30 /**
31 * \@internal
32 */
33 this._baseHref = '';
34 /**
35 * \@internal
36 */
37 this._platformStrategy = (/** @type {?} */ (null));
38 /**
39 * \@internal
40 */
41 this._platformLocation = (/** @type {?} */ (null));
42 /**
43 * \@internal
44 */
45 this._urlChangeListeners = [];
46 }
47 /**
48 * @param {?} url
49 * @return {?}
50 */
51 setInitialPath(url) { this._history[this._historyIndex].path = url; }
52 /**
53 * @param {?} url
54 * @return {?}
55 */
56 setBaseHref(url) { this._baseHref = url; }
57 /**
58 * @return {?}
59 */
60 path() { return this._history[this._historyIndex].path; }
61 /**
62 * @return {?}
63 */
64 getState() { return this._history[this._historyIndex].state; }
65 /**
66 * @param {?} path
67 * @param {?=} query
68 * @return {?}
69 */
70 isCurrentPathEqualTo(path, query = '') {
71 /** @type {?} */
72 const givenPath = path.endsWith('/') ? path.substring(0, path.length - 1) : path;
73 /** @type {?} */
74 const currPath = this.path().endsWith('/') ? this.path().substring(0, this.path().length - 1) : this.path();
75 return currPath == givenPath + (query.length > 0 ? ('?' + query) : '');
76 }
77 /**
78 * @param {?} pathname
79 * @return {?}
80 */
81 simulateUrlPop(pathname) {
82 this._subject.emit({ 'url': pathname, 'pop': true, 'type': 'popstate' });
83 }
84 /**
85 * @param {?} pathname
86 * @return {?}
87 */
88 simulateHashChange(pathname) {
89 // Because we don't prevent the native event, the browser will independently update the path
90 this.setInitialPath(pathname);
91 this.urlChanges.push('hash: ' + pathname);
92 this._subject.emit({ 'url': pathname, 'pop': true, 'type': 'hashchange' });
93 }
94 /**
95 * @param {?} url
96 * @return {?}
97 */
98 prepareExternalUrl(url) {
99 if (url.length > 0 && !url.startsWith('/')) {
100 url = '/' + url;
101 }
102 return this._baseHref + url;
103 }
104 /**
105 * @param {?} path
106 * @param {?=} query
107 * @param {?=} state
108 * @return {?}
109 */
110 go(path, query = '', state = null) {
111 path = this.prepareExternalUrl(path);
112 if (this._historyIndex > 0) {
113 this._history.splice(this._historyIndex + 1);
114 }
115 this._history.push(new LocationState(path, query, state));
116 this._historyIndex = this._history.length - 1;
117 /** @type {?} */
118 const locationState = this._history[this._historyIndex - 1];
119 if (locationState.path == path && locationState.query == query) {
120 return;
121 }
122 /** @type {?} */
123 const url = path + (query.length > 0 ? ('?' + query) : '');
124 this.urlChanges.push(url);
125 this._subject.emit({ 'url': url, 'pop': false });
126 }
127 /**
128 * @param {?} path
129 * @param {?=} query
130 * @param {?=} state
131 * @return {?}
132 */
133 replaceState(path, query = '', state = null) {
134 path = this.prepareExternalUrl(path);
135 /** @type {?} */
136 const history = this._history[this._historyIndex];
137 if (history.path == path && history.query == query) {
138 return;
139 }
140 history.path = path;
141 history.query = query;
142 history.state = state;
143 /** @type {?} */
144 const url = path + (query.length > 0 ? ('?' + query) : '');
145 this.urlChanges.push('replace: ' + url);
146 }
147 /**
148 * @return {?}
149 */
150 forward() {
151 if (this._historyIndex < (this._history.length - 1)) {
152 this._historyIndex++;
153 this._subject.emit({ 'url': this.path(), 'state': this.getState(), 'pop': true });
154 }
155 }
156 /**
157 * @return {?}
158 */
159 back() {
160 if (this._historyIndex > 0) {
161 this._historyIndex--;
162 this._subject.emit({ 'url': this.path(), 'state': this.getState(), 'pop': true });
163 }
164 }
165 /**
166 * @param {?} fn
167 * @return {?}
168 */
169 onUrlChange(fn) {
170 this._urlChangeListeners.push(fn);
171 this.subscribe((/**
172 * @param {?} v
173 * @return {?}
174 */
175 v => { this._notifyUrlChangeListeners(v.url, v.state); }));
176 }
177 /**
178 * \@internal
179 * @param {?=} url
180 * @param {?=} state
181 * @return {?}
182 */
183 _notifyUrlChangeListeners(url = '', state) {
184 this._urlChangeListeners.forEach((/**
185 * @param {?} fn
186 * @return {?}
187 */
188 fn => fn(url, state)));
189 }
190 /**
191 * @param {?} onNext
192 * @param {?=} onThrow
193 * @param {?=} onReturn
194 * @return {?}
195 */
196 subscribe(onNext, onThrow, onReturn) {
197 return this._subject.subscribe({ next: onNext, error: onThrow, complete: onReturn });
198 }
199 /**
200 * @param {?} url
201 * @return {?}
202 */
203 normalize(url) { return (/** @type {?} */ (null)); }
204}
205SpyLocation.decorators = [
206 { type: Injectable }
207];
208if (false) {
209 /** @type {?} */
210 SpyLocation.prototype.urlChanges;
211 /**
212 * @type {?}
213 * @private
214 */
215 SpyLocation.prototype._history;
216 /**
217 * @type {?}
218 * @private
219 */
220 SpyLocation.prototype._historyIndex;
221 /**
222 * \@internal
223 * @type {?}
224 */
225 SpyLocation.prototype._subject;
226 /**
227 * \@internal
228 * @type {?}
229 */
230 SpyLocation.prototype._baseHref;
231 /**
232 * \@internal
233 * @type {?}
234 */
235 SpyLocation.prototype._platformStrategy;
236 /**
237 * \@internal
238 * @type {?}
239 */
240 SpyLocation.prototype._platformLocation;
241 /**
242 * \@internal
243 * @type {?}
244 */
245 SpyLocation.prototype._urlChangeListeners;
246}
247class LocationState {
248 /**
249 * @param {?} path
250 * @param {?} query
251 * @param {?} state
252 */
253 constructor(path, query, state) {
254 this.path = path;
255 this.query = query;
256 this.state = state;
257 }
258}
259if (false) {
260 /** @type {?} */
261 LocationState.prototype.path;
262 /** @type {?} */
263 LocationState.prototype.query;
264 /** @type {?} */
265 LocationState.prototype.state;
266}
267
268/**
269 * @fileoverview added by tsickle
270 * Generated from: packages/common/testing/src/mock_location_strategy.ts
271 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
272 */
273/**
274 * A mock implementation of {\@link LocationStrategy} that allows tests to fire simulated
275 * location events.
276 *
277 * \@publicApi
278 */
279class MockLocationStrategy extends LocationStrategy {
280 constructor() {
281 super();
282 this.internalBaseHref = '/';
283 this.internalPath = '/';
284 this.internalTitle = '';
285 this.urlChanges = [];
286 /**
287 * \@internal
288 */
289 this._subject = new EventEmitter();
290 this.stateChanges = [];
291 }
292 /**
293 * @param {?} url
294 * @return {?}
295 */
296 simulatePopState(url) {
297 this.internalPath = url;
298 this._subject.emit(new _MockPopStateEvent(this.path()));
299 }
300 /**
301 * @param {?=} includeHash
302 * @return {?}
303 */
304 path(includeHash = false) { return this.internalPath; }
305 /**
306 * @param {?} internal
307 * @return {?}
308 */
309 prepareExternalUrl(internal) {
310 if (internal.startsWith('/') && this.internalBaseHref.endsWith('/')) {
311 return this.internalBaseHref + internal.substring(1);
312 }
313 return this.internalBaseHref + internal;
314 }
315 /**
316 * @param {?} ctx
317 * @param {?} title
318 * @param {?} path
319 * @param {?} query
320 * @return {?}
321 */
322 pushState(ctx, title, path, query) {
323 // Add state change to changes array
324 this.stateChanges.push(ctx);
325 this.internalTitle = title;
326 /** @type {?} */
327 const url = path + (query.length > 0 ? ('?' + query) : '');
328 this.internalPath = url;
329 /** @type {?} */
330 const externalUrl = this.prepareExternalUrl(url);
331 this.urlChanges.push(externalUrl);
332 }
333 /**
334 * @param {?} ctx
335 * @param {?} title
336 * @param {?} path
337 * @param {?} query
338 * @return {?}
339 */
340 replaceState(ctx, title, path, query) {
341 // Reset the last index of stateChanges to the ctx (state) object
342 this.stateChanges[(this.stateChanges.length || 1) - 1] = ctx;
343 this.internalTitle = title;
344 /** @type {?} */
345 const url = path + (query.length > 0 ? ('?' + query) : '');
346 this.internalPath = url;
347 /** @type {?} */
348 const externalUrl = this.prepareExternalUrl(url);
349 this.urlChanges.push('replace: ' + externalUrl);
350 }
351 /**
352 * @param {?} fn
353 * @return {?}
354 */
355 onPopState(fn) { this._subject.subscribe({ next: fn }); }
356 /**
357 * @return {?}
358 */
359 getBaseHref() { return this.internalBaseHref; }
360 /**
361 * @return {?}
362 */
363 back() {
364 if (this.urlChanges.length > 0) {
365 this.urlChanges.pop();
366 this.stateChanges.pop();
367 /** @type {?} */
368 const nextUrl = this.urlChanges.length > 0 ? this.urlChanges[this.urlChanges.length - 1] : '';
369 this.simulatePopState(nextUrl);
370 }
371 }
372 /**
373 * @return {?}
374 */
375 forward() { throw 'not implemented'; }
376 /**
377 * @return {?}
378 */
379 getState() { return this.stateChanges[(this.stateChanges.length || 1) - 1]; }
380}
381MockLocationStrategy.decorators = [
382 { type: Injectable }
383];
384/** @nocollapse */
385MockLocationStrategy.ctorParameters = () => [];
386if (false) {
387 /** @type {?} */
388 MockLocationStrategy.prototype.internalBaseHref;
389 /** @type {?} */
390 MockLocationStrategy.prototype.internalPath;
391 /** @type {?} */
392 MockLocationStrategy.prototype.internalTitle;
393 /** @type {?} */
394 MockLocationStrategy.prototype.urlChanges;
395 /**
396 * \@internal
397 * @type {?}
398 */
399 MockLocationStrategy.prototype._subject;
400 /**
401 * @type {?}
402 * @private
403 */
404 MockLocationStrategy.prototype.stateChanges;
405}
406class _MockPopStateEvent {
407 /**
408 * @param {?} newUrl
409 */
410 constructor(newUrl) {
411 this.newUrl = newUrl;
412 this.pop = true;
413 this.type = 'popstate';
414 }
415}
416if (false) {
417 /** @type {?} */
418 _MockPopStateEvent.prototype.pop;
419 /** @type {?} */
420 _MockPopStateEvent.prototype.type;
421 /** @type {?} */
422 _MockPopStateEvent.prototype.newUrl;
423}
424
425/**
426 * @fileoverview added by tsickle
427 * Generated from: packages/common/testing/src/mock_platform_location.ts
428 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
429 */
430/**
431 * Parser from https://tools.ietf.org/html/rfc3986#appendix-B
432 * ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
433 * 12 3 4 5 6 7 8 9
434 *
435 * Example: http://www.ics.uci.edu/pub/ietf/uri/#Related
436 *
437 * Results in:
438 *
439 * $1 = http:
440 * $2 = http
441 * $3 = //www.ics.uci.edu
442 * $4 = www.ics.uci.edu
443 * $5 = /pub/ietf/uri/
444 * $6 = <undefined>
445 * $7 = <undefined>
446 * $8 = #Related
447 * $9 = Related
448 * @type {?}
449 */
450const urlParse = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
451/**
452 * @param {?} urlStr
453 * @param {?} baseHref
454 * @return {?}
455 */
456function parseUrl(urlStr, baseHref) {
457 /** @type {?} */
458 const verifyProtocol = /^((http[s]?|ftp):\/\/)/;
459 /** @type {?} */
460 let serverBase;
461 // URL class requires full URL. If the URL string doesn't start with protocol, we need to add
462 // an arbitrary base URL which can be removed afterward.
463 if (!verifyProtocol.test(urlStr)) {
464 serverBase = 'http://empty.com/';
465 }
466 /** @type {?} */
467 let parsedUrl;
468 try {
469 parsedUrl = new URL(urlStr, serverBase);
470 }
471 catch (e) {
472 /** @type {?} */
473 const result = urlParse.exec(serverBase || '' + urlStr);
474 if (!result) {
475 throw new Error(`Invalid URL: ${urlStr} with base: ${baseHref}`);
476 }
477 /** @type {?} */
478 const hostSplit = result[4].split(':');
479 parsedUrl = {
480 protocol: result[1],
481 hostname: hostSplit[0],
482 port: hostSplit[1] || '',
483 pathname: result[5],
484 search: result[6],
485 hash: result[8],
486 };
487 }
488 if (parsedUrl.pathname && parsedUrl.pathname.indexOf(baseHref) === 0) {
489 parsedUrl.pathname = parsedUrl.pathname.substring(baseHref.length);
490 }
491 return {
492 hostname: !serverBase && parsedUrl.hostname || '',
493 protocol: !serverBase && parsedUrl.protocol || '',
494 port: !serverBase && parsedUrl.port || '',
495 pathname: parsedUrl.pathname || '/',
496 search: parsedUrl.search || '',
497 hash: parsedUrl.hash || '',
498 };
499}
500/**
501 * Mock platform location config
502 *
503 * \@publicApi
504 * @record
505 */
506function MockPlatformLocationConfig() { }
507if (false) {
508 /** @type {?|undefined} */
509 MockPlatformLocationConfig.prototype.startUrl;
510 /** @type {?|undefined} */
511 MockPlatformLocationConfig.prototype.appBaseHref;
512}
513/**
514 * Provider for mock platform location config
515 *
516 * \@publicApi
517 * @type {?}
518 */
519const MOCK_PLATFORM_LOCATION_CONFIG = new InjectionToken('MOCK_PLATFORM_LOCATION_CONFIG');
520/**
521 * Mock implementation of URL state.
522 *
523 * \@publicApi
524 */
525class MockPlatformLocation {
526 /**
527 * @param {?=} config
528 */
529 constructor(config) {
530 this.baseHref = '';
531 this.hashUpdate = new Subject();
532 this.urlChanges = [{ hostname: '', protocol: '', port: '', pathname: '/', search: '', hash: '', state: null }];
533 if (config) {
534 this.baseHref = config.appBaseHref || '';
535 /** @type {?} */
536 const parsedChanges = this.parseChanges(null, config.startUrl || 'http://<empty>/', this.baseHref);
537 this.urlChanges[0] = Object.assign({}, parsedChanges);
538 }
539 }
540 /**
541 * @return {?}
542 */
543 get hostname() { return this.urlChanges[0].hostname; }
544 /**
545 * @return {?}
546 */
547 get protocol() { return this.urlChanges[0].protocol; }
548 /**
549 * @return {?}
550 */
551 get port() { return this.urlChanges[0].port; }
552 /**
553 * @return {?}
554 */
555 get pathname() { return this.urlChanges[0].pathname; }
556 /**
557 * @return {?}
558 */
559 get search() { return this.urlChanges[0].search; }
560 /**
561 * @return {?}
562 */
563 get hash() { return this.urlChanges[0].hash; }
564 /**
565 * @return {?}
566 */
567 get state() { return this.urlChanges[0].state; }
568 /**
569 * @return {?}
570 */
571 getBaseHrefFromDOM() { return this.baseHref; }
572 /**
573 * @param {?} fn
574 * @return {?}
575 */
576 onPopState(fn) {
577 // No-op: a state stack is not implemented, so
578 // no events will ever come.
579 }
580 /**
581 * @param {?} fn
582 * @return {?}
583 */
584 onHashChange(fn) { this.hashUpdate.subscribe(fn); }
585 /**
586 * @return {?}
587 */
588 get href() {
589 /** @type {?} */
590 let url = `${this.protocol}//${this.hostname}${this.port ? ':' + this.port : ''}`;
591 url += `${this.pathname === '/' ? '' : this.pathname}${this.search}${this.hash}`;
592 return url;
593 }
594 /**
595 * @return {?}
596 */
597 get url() { return `${this.pathname}${this.search}${this.hash}`; }
598 /**
599 * @private
600 * @param {?} state
601 * @param {?} url
602 * @param {?=} baseHref
603 * @return {?}
604 */
605 parseChanges(state, url, baseHref = '') {
606 // When the `history.state` value is stored, it is always copied.
607 state = JSON.parse(JSON.stringify(state));
608 return Object.assign(Object.assign({}, parseUrl(url, baseHref)), { state });
609 }
610 /**
611 * @param {?} state
612 * @param {?} title
613 * @param {?} newUrl
614 * @return {?}
615 */
616 replaceState(state, title, newUrl) {
617 const { pathname, search, state: parsedState, hash } = this.parseChanges(state, newUrl);
618 this.urlChanges[0] = Object.assign(Object.assign({}, this.urlChanges[0]), { pathname, search, hash, state: parsedState });
619 }
620 /**
621 * @param {?} state
622 * @param {?} title
623 * @param {?} newUrl
624 * @return {?}
625 */
626 pushState(state, title, newUrl) {
627 const { pathname, search, state: parsedState, hash } = this.parseChanges(state, newUrl);
628 this.urlChanges.unshift(Object.assign(Object.assign({}, this.urlChanges[0]), { pathname, search, hash, state: parsedState }));
629 }
630 /**
631 * @return {?}
632 */
633 forward() { throw new Error('Not implemented'); }
634 /**
635 * @return {?}
636 */
637 back() {
638 /** @type {?} */
639 const oldUrl = this.url;
640 /** @type {?} */
641 const oldHash = this.hash;
642 this.urlChanges.shift();
643 /** @type {?} */
644 const newHash = this.hash;
645 if (oldHash !== newHash) {
646 scheduleMicroTask((/**
647 * @return {?}
648 */
649 () => this.hashUpdate.next((/** @type {?} */ ({
650 type: 'hashchange', state: null, oldUrl, newUrl: this.url
651 })))));
652 }
653 }
654 /**
655 * @return {?}
656 */
657 getState() { return this.state; }
658}
659MockPlatformLocation.decorators = [
660 { type: Injectable }
661];
662/** @nocollapse */
663MockPlatformLocation.ctorParameters = () => [
664 { type: undefined, decorators: [{ type: Inject, args: [MOCK_PLATFORM_LOCATION_CONFIG,] }, { type: Optional }] }
665];
666if (false) {
667 /**
668 * @type {?}
669 * @private
670 */
671 MockPlatformLocation.prototype.baseHref;
672 /**
673 * @type {?}
674 * @private
675 */
676 MockPlatformLocation.prototype.hashUpdate;
677 /**
678 * @type {?}
679 * @private
680 */
681 MockPlatformLocation.prototype.urlChanges;
682}
683/**
684 * @param {?} cb
685 * @return {?}
686 */
687function scheduleMicroTask(cb) {
688 Promise.resolve(null).then(cb);
689}
690
691/**
692 * @fileoverview added by tsickle
693 * Generated from: packages/common/testing/src/testing.ts
694 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
695 */
696
697/**
698 * @fileoverview added by tsickle
699 * Generated from: packages/common/testing/public_api.ts
700 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
701 */
702
703/**
704 * @fileoverview added by tsickle
705 * Generated from: packages/common/testing/index.ts
706 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
707 */
708
709/**
710 * Generated bundle index. Do not edit.
711 */
712
713export { MOCK_PLATFORM_LOCATION_CONFIG, MockLocationStrategy, MockPlatformLocation, SpyLocation };
714//# sourceMappingURL=testing.js.map