UNPKG

17.2 kBJavaScriptView Raw
1/**
2 * @license Angular v9.0.4
3 * (c) 2010-2020 Google LLC. https://angular.io/
4 * License: MIT
5 */
6
7import { __decorate, __extends, __metadata, __assign, __param } from 'tslib';
8import { EventEmitter, Injectable, InjectionToken, Inject, Optional } from '@angular/core';
9import { LocationStrategy } from '@angular/common';
10import { Subject } from 'rxjs';
11
12/**
13 * @license
14 * Copyright Google Inc. All Rights Reserved.
15 *
16 * Use of this source code is governed by an MIT-style license that can be
17 * found in the LICENSE file at https://angular.io/license
18 */
19/**
20 * A spy for {@link Location} that allows tests to fire simulated location events.
21 *
22 * @publicApi
23 */
24var SpyLocation = /** @class */ (function () {
25 function SpyLocation() {
26 this.urlChanges = [];
27 this._history = [new LocationState('', '', null)];
28 this._historyIndex = 0;
29 /** @internal */
30 this._subject = new EventEmitter();
31 /** @internal */
32 this._baseHref = '';
33 /** @internal */
34 this._platformStrategy = null;
35 /** @internal */
36 this._platformLocation = null;
37 /** @internal */
38 this._urlChangeListeners = [];
39 }
40 SpyLocation.prototype.setInitialPath = function (url) { this._history[this._historyIndex].path = url; };
41 SpyLocation.prototype.setBaseHref = function (url) { this._baseHref = url; };
42 SpyLocation.prototype.path = function () { return this._history[this._historyIndex].path; };
43 SpyLocation.prototype.getState = function () { return this._history[this._historyIndex].state; };
44 SpyLocation.prototype.isCurrentPathEqualTo = function (path, query) {
45 if (query === void 0) { query = ''; }
46 var givenPath = path.endsWith('/') ? path.substring(0, path.length - 1) : path;
47 var currPath = this.path().endsWith('/') ? this.path().substring(0, this.path().length - 1) : this.path();
48 return currPath == givenPath + (query.length > 0 ? ('?' + query) : '');
49 };
50 SpyLocation.prototype.simulateUrlPop = function (pathname) {
51 this._subject.emit({ 'url': pathname, 'pop': true, 'type': 'popstate' });
52 };
53 SpyLocation.prototype.simulateHashChange = function (pathname) {
54 // Because we don't prevent the native event, the browser will independently update the path
55 this.setInitialPath(pathname);
56 this.urlChanges.push('hash: ' + pathname);
57 this._subject.emit({ 'url': pathname, 'pop': true, 'type': 'hashchange' });
58 };
59 SpyLocation.prototype.prepareExternalUrl = function (url) {
60 if (url.length > 0 && !url.startsWith('/')) {
61 url = '/' + url;
62 }
63 return this._baseHref + url;
64 };
65 SpyLocation.prototype.go = function (path, query, state) {
66 if (query === void 0) { query = ''; }
67 if (state === void 0) { state = null; }
68 path = this.prepareExternalUrl(path);
69 if (this._historyIndex > 0) {
70 this._history.splice(this._historyIndex + 1);
71 }
72 this._history.push(new LocationState(path, query, state));
73 this._historyIndex = this._history.length - 1;
74 var locationState = this._history[this._historyIndex - 1];
75 if (locationState.path == path && locationState.query == query) {
76 return;
77 }
78 var url = path + (query.length > 0 ? ('?' + query) : '');
79 this.urlChanges.push(url);
80 this._subject.emit({ 'url': url, 'pop': false });
81 };
82 SpyLocation.prototype.replaceState = function (path, query, state) {
83 if (query === void 0) { query = ''; }
84 if (state === void 0) { state = null; }
85 path = this.prepareExternalUrl(path);
86 var history = this._history[this._historyIndex];
87 if (history.path == path && history.query == query) {
88 return;
89 }
90 history.path = path;
91 history.query = query;
92 history.state = state;
93 var url = path + (query.length > 0 ? ('?' + query) : '');
94 this.urlChanges.push('replace: ' + url);
95 };
96 SpyLocation.prototype.forward = function () {
97 if (this._historyIndex < (this._history.length - 1)) {
98 this._historyIndex++;
99 this._subject.emit({ 'url': this.path(), 'state': this.getState(), 'pop': true });
100 }
101 };
102 SpyLocation.prototype.back = function () {
103 if (this._historyIndex > 0) {
104 this._historyIndex--;
105 this._subject.emit({ 'url': this.path(), 'state': this.getState(), 'pop': true });
106 }
107 };
108 SpyLocation.prototype.onUrlChange = function (fn) {
109 var _this = this;
110 this._urlChangeListeners.push(fn);
111 this.subscribe(function (v) { _this._notifyUrlChangeListeners(v.url, v.state); });
112 };
113 /** @internal */
114 SpyLocation.prototype._notifyUrlChangeListeners = function (url, state) {
115 if (url === void 0) { url = ''; }
116 this._urlChangeListeners.forEach(function (fn) { return fn(url, state); });
117 };
118 SpyLocation.prototype.subscribe = function (onNext, onThrow, onReturn) {
119 return this._subject.subscribe({ next: onNext, error: onThrow, complete: onReturn });
120 };
121 SpyLocation.prototype.normalize = function (url) { return null; };
122 SpyLocation = __decorate([
123 Injectable()
124 ], SpyLocation);
125 return SpyLocation;
126}());
127var LocationState = /** @class */ (function () {
128 function LocationState(path, query, state) {
129 this.path = path;
130 this.query = query;
131 this.state = state;
132 }
133 return LocationState;
134}());
135
136/**
137 * @license
138 * Copyright Google Inc. All Rights Reserved.
139 *
140 * Use of this source code is governed by an MIT-style license that can be
141 * found in the LICENSE file at https://angular.io/license
142 */
143/**
144 * A mock implementation of {@link LocationStrategy} that allows tests to fire simulated
145 * location events.
146 *
147 * @publicApi
148 */
149var MockLocationStrategy = /** @class */ (function (_super) {
150 __extends(MockLocationStrategy, _super);
151 function MockLocationStrategy() {
152 var _this = _super.call(this) || this;
153 _this.internalBaseHref = '/';
154 _this.internalPath = '/';
155 _this.internalTitle = '';
156 _this.urlChanges = [];
157 /** @internal */
158 _this._subject = new EventEmitter();
159 _this.stateChanges = [];
160 return _this;
161 }
162 MockLocationStrategy.prototype.simulatePopState = function (url) {
163 this.internalPath = url;
164 this._subject.emit(new _MockPopStateEvent(this.path()));
165 };
166 MockLocationStrategy.prototype.path = function (includeHash) {
167 if (includeHash === void 0) { includeHash = false; }
168 return this.internalPath;
169 };
170 MockLocationStrategy.prototype.prepareExternalUrl = function (internal) {
171 if (internal.startsWith('/') && this.internalBaseHref.endsWith('/')) {
172 return this.internalBaseHref + internal.substring(1);
173 }
174 return this.internalBaseHref + internal;
175 };
176 MockLocationStrategy.prototype.pushState = function (ctx, title, path, query) {
177 // Add state change to changes array
178 this.stateChanges.push(ctx);
179 this.internalTitle = title;
180 var url = path + (query.length > 0 ? ('?' + query) : '');
181 this.internalPath = url;
182 var externalUrl = this.prepareExternalUrl(url);
183 this.urlChanges.push(externalUrl);
184 };
185 MockLocationStrategy.prototype.replaceState = function (ctx, title, path, query) {
186 // Reset the last index of stateChanges to the ctx (state) object
187 this.stateChanges[(this.stateChanges.length || 1) - 1] = ctx;
188 this.internalTitle = title;
189 var url = path + (query.length > 0 ? ('?' + query) : '');
190 this.internalPath = url;
191 var externalUrl = this.prepareExternalUrl(url);
192 this.urlChanges.push('replace: ' + externalUrl);
193 };
194 MockLocationStrategy.prototype.onPopState = function (fn) { this._subject.subscribe({ next: fn }); };
195 MockLocationStrategy.prototype.getBaseHref = function () { return this.internalBaseHref; };
196 MockLocationStrategy.prototype.back = function () {
197 if (this.urlChanges.length > 0) {
198 this.urlChanges.pop();
199 this.stateChanges.pop();
200 var nextUrl = this.urlChanges.length > 0 ? this.urlChanges[this.urlChanges.length - 1] : '';
201 this.simulatePopState(nextUrl);
202 }
203 };
204 MockLocationStrategy.prototype.forward = function () { throw 'not implemented'; };
205 MockLocationStrategy.prototype.getState = function () { return this.stateChanges[(this.stateChanges.length || 1) - 1]; };
206 MockLocationStrategy = __decorate([
207 Injectable(),
208 __metadata("design:paramtypes", [])
209 ], MockLocationStrategy);
210 return MockLocationStrategy;
211}(LocationStrategy));
212var _MockPopStateEvent = /** @class */ (function () {
213 function _MockPopStateEvent(newUrl) {
214 this.newUrl = newUrl;
215 this.pop = true;
216 this.type = 'popstate';
217 }
218 return _MockPopStateEvent;
219}());
220
221/**
222 * @license
223 * Copyright Google Inc. All Rights Reserved.
224 *
225 * Use of this source code is governed by an MIT-style license that can be
226 * found in the LICENSE file at https://angular.io/license
227 */
228/**
229 * Parser from https://tools.ietf.org/html/rfc3986#appendix-B
230 * ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
231 * 12 3 4 5 6 7 8 9
232 *
233 * Example: http://www.ics.uci.edu/pub/ietf/uri/#Related
234 *
235 * Results in:
236 *
237 * $1 = http:
238 * $2 = http
239 * $3 = //www.ics.uci.edu
240 * $4 = www.ics.uci.edu
241 * $5 = /pub/ietf/uri/
242 * $6 = <undefined>
243 * $7 = <undefined>
244 * $8 = #Related
245 * $9 = Related
246 */
247var urlParse = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
248function parseUrl(urlStr, baseHref) {
249 var verifyProtocol = /^((http[s]?|ftp):\/\/)/;
250 var serverBase;
251 // URL class requires full URL. If the URL string doesn't start with protocol, we need to add
252 // an arbitrary base URL which can be removed afterward.
253 if (!verifyProtocol.test(urlStr)) {
254 serverBase = 'http://empty.com/';
255 }
256 var parsedUrl;
257 try {
258 parsedUrl = new URL(urlStr, serverBase);
259 }
260 catch (e) {
261 var result = urlParse.exec(serverBase || '' + urlStr);
262 if (!result) {
263 throw new Error("Invalid URL: " + urlStr + " with base: " + baseHref);
264 }
265 var hostSplit = result[4].split(':');
266 parsedUrl = {
267 protocol: result[1],
268 hostname: hostSplit[0],
269 port: hostSplit[1] || '',
270 pathname: result[5],
271 search: result[6],
272 hash: result[8],
273 };
274 }
275 if (parsedUrl.pathname && parsedUrl.pathname.indexOf(baseHref) === 0) {
276 parsedUrl.pathname = parsedUrl.pathname.substring(baseHref.length);
277 }
278 return {
279 hostname: !serverBase && parsedUrl.hostname || '',
280 protocol: !serverBase && parsedUrl.protocol || '',
281 port: !serverBase && parsedUrl.port || '',
282 pathname: parsedUrl.pathname || '/',
283 search: parsedUrl.search || '',
284 hash: parsedUrl.hash || '',
285 };
286}
287/**
288 * Provider for mock platform location config
289 *
290 * @publicApi
291 */
292var MOCK_PLATFORM_LOCATION_CONFIG = new InjectionToken('MOCK_PLATFORM_LOCATION_CONFIG');
293/**
294 * Mock implementation of URL state.
295 *
296 * @publicApi
297 */
298var MockPlatformLocation = /** @class */ (function () {
299 function MockPlatformLocation(config) {
300 this.baseHref = '';
301 this.hashUpdate = new Subject();
302 this.urlChanges = [{ hostname: '', protocol: '', port: '', pathname: '/', search: '', hash: '', state: null }];
303 if (config) {
304 this.baseHref = config.appBaseHref || '';
305 var parsedChanges = this.parseChanges(null, config.startUrl || 'http://<empty>/', this.baseHref);
306 this.urlChanges[0] = __assign({}, parsedChanges);
307 }
308 }
309 Object.defineProperty(MockPlatformLocation.prototype, "hostname", {
310 get: function () { return this.urlChanges[0].hostname; },
311 enumerable: true,
312 configurable: true
313 });
314 Object.defineProperty(MockPlatformLocation.prototype, "protocol", {
315 get: function () { return this.urlChanges[0].protocol; },
316 enumerable: true,
317 configurable: true
318 });
319 Object.defineProperty(MockPlatformLocation.prototype, "port", {
320 get: function () { return this.urlChanges[0].port; },
321 enumerable: true,
322 configurable: true
323 });
324 Object.defineProperty(MockPlatformLocation.prototype, "pathname", {
325 get: function () { return this.urlChanges[0].pathname; },
326 enumerable: true,
327 configurable: true
328 });
329 Object.defineProperty(MockPlatformLocation.prototype, "search", {
330 get: function () { return this.urlChanges[0].search; },
331 enumerable: true,
332 configurable: true
333 });
334 Object.defineProperty(MockPlatformLocation.prototype, "hash", {
335 get: function () { return this.urlChanges[0].hash; },
336 enumerable: true,
337 configurable: true
338 });
339 Object.defineProperty(MockPlatformLocation.prototype, "state", {
340 get: function () { return this.urlChanges[0].state; },
341 enumerable: true,
342 configurable: true
343 });
344 MockPlatformLocation.prototype.getBaseHrefFromDOM = function () { return this.baseHref; };
345 MockPlatformLocation.prototype.onPopState = function (fn) {
346 // No-op: a state stack is not implemented, so
347 // no events will ever come.
348 };
349 MockPlatformLocation.prototype.onHashChange = function (fn) { this.hashUpdate.subscribe(fn); };
350 Object.defineProperty(MockPlatformLocation.prototype, "href", {
351 get: function () {
352 var url = this.protocol + "//" + this.hostname + (this.port ? ':' + this.port : '');
353 url += "" + (this.pathname === '/' ? '' : this.pathname) + this.search + this.hash;
354 return url;
355 },
356 enumerable: true,
357 configurable: true
358 });
359 Object.defineProperty(MockPlatformLocation.prototype, "url", {
360 get: function () { return "" + this.pathname + this.search + this.hash; },
361 enumerable: true,
362 configurable: true
363 });
364 MockPlatformLocation.prototype.parseChanges = function (state, url, baseHref) {
365 if (baseHref === void 0) { baseHref = ''; }
366 // When the `history.state` value is stored, it is always copied.
367 state = JSON.parse(JSON.stringify(state));
368 return __assign(__assign({}, parseUrl(url, baseHref)), { state: state });
369 };
370 MockPlatformLocation.prototype.replaceState = function (state, title, newUrl) {
371 var _a = this.parseChanges(state, newUrl), pathname = _a.pathname, search = _a.search, parsedState = _a.state, hash = _a.hash;
372 this.urlChanges[0] = __assign(__assign({}, this.urlChanges[0]), { pathname: pathname, search: search, hash: hash, state: parsedState });
373 };
374 MockPlatformLocation.prototype.pushState = function (state, title, newUrl) {
375 var _a = this.parseChanges(state, newUrl), pathname = _a.pathname, search = _a.search, parsedState = _a.state, hash = _a.hash;
376 this.urlChanges.unshift(__assign(__assign({}, this.urlChanges[0]), { pathname: pathname, search: search, hash: hash, state: parsedState }));
377 };
378 MockPlatformLocation.prototype.forward = function () { throw new Error('Not implemented'); };
379 MockPlatformLocation.prototype.back = function () {
380 var _this = this;
381 var oldUrl = this.url;
382 var oldHash = this.hash;
383 this.urlChanges.shift();
384 var newHash = this.hash;
385 if (oldHash !== newHash) {
386 scheduleMicroTask(function () { return _this.hashUpdate.next({
387 type: 'hashchange', state: null, oldUrl: oldUrl, newUrl: _this.url
388 }); });
389 }
390 };
391 MockPlatformLocation.prototype.getState = function () { return this.state; };
392 MockPlatformLocation = __decorate([
393 Injectable(),
394 __param(0, Inject(MOCK_PLATFORM_LOCATION_CONFIG)), __param(0, Optional()),
395 __metadata("design:paramtypes", [Object])
396 ], MockPlatformLocation);
397 return MockPlatformLocation;
398}());
399function scheduleMicroTask(cb) {
400 Promise.resolve(null).then(cb);
401}
402
403/**
404 * @license
405 * Copyright Google Inc. All Rights Reserved.
406 *
407 * Use of this source code is governed by an MIT-style license that can be
408 * found in the LICENSE file at https://angular.io/license
409 */
410
411/**
412 * @license
413 * Copyright Google Inc. All Rights Reserved.
414 *
415 * Use of this source code is governed by an MIT-style license that can be
416 * found in the LICENSE file at https://angular.io/license
417 */
418// This file only reexports content of the `src` folder. Keep it that way.
419
420/**
421 * @license
422 * Copyright Google Inc. All Rights Reserved.
423 *
424 * Use of this source code is governed by an MIT-style license that can be
425 * found in the LICENSE file at https://angular.io/license
426 */
427
428/**
429 * Generated bundle index. Do not edit.
430 */
431
432export { MOCK_PLATFORM_LOCATION_CONFIG, MockLocationStrategy, MockPlatformLocation, SpyLocation };
433//# sourceMappingURL=testing.js.map