build: reformat repo to new clang@1.4.0 (#36628)

PR Close #36628
This commit is contained in:
Joey Perrott
2020-04-13 17:43:52 -07:00
committed by atscott
parent 4b3f9ac739
commit 26f49151e7
1163 changed files with 31727 additions and 24036 deletions

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@ export class HttpHeaders {
* Internal map of lowercase header names to values.
*/
// TODO(issue/24571): remove '!'.
private headers !: Map<string, string[]>;
private headers!: Map<string, string[]>;
/**
@ -36,7 +36,7 @@ export class HttpHeaders {
/**
* Complete the lazy initialization of this object (needed before reading).
*/
private lazyInit !: HttpHeaders | Function | null;
private lazyInit!: HttpHeaders|Function|null;
/**
* Queued updates to be materialized the next initialization.
@ -59,7 +59,7 @@ export class HttpHeaders {
const value = line.slice(index + 1).trim();
this.maybeSetNormalizedName(name, key);
if (this.headers.has(key)) {
this.headers.get(key) !.push(value);
this.headers.get(key)!.push(value);
} else {
this.headers.set(key, [value]);
}
@ -169,7 +169,7 @@ export class HttpHeaders {
*
* @returns A clone of the HTTP headers object with the given value deleted.
*/
delete (name: string, value?: string|string[]): HttpHeaders {
delete(name: string, value?: string|string[]): HttpHeaders {
return this.clone({name, value, op: 'd'});
}
@ -197,8 +197,8 @@ export class HttpHeaders {
private copyFrom(other: HttpHeaders) {
other.init();
Array.from(other.headers.keys()).forEach(key => {
this.headers.set(key, other.headers.get(key) !);
this.normalizedNames.set(key, other.normalizedNames.get(key) !);
this.headers.set(key, other.headers.get(key)!);
this.normalizedNames.set(key, other.normalizedNames.get(key)!);
});
}
@ -215,7 +215,7 @@ export class HttpHeaders {
switch (update.op) {
case 'a':
case 's':
let value = update.value !;
let value = update.value!;
if (typeof value === 'string') {
value = [value];
}
@ -255,6 +255,6 @@ export class HttpHeaders {
forEach(fn: (name: string, values: string[]) => void) {
this.init();
Array.from(this.normalizedNames.keys())
.forEach(key => fn(this.normalizedNames.get(key) !, this.headers.get(key) !));
.forEach(key => fn(this.normalizedNames.get(key)!, this.headers.get(key)!));
}
}

View File

@ -38,8 +38,8 @@ import {HttpEvent} from './response';
* To use the same instance of `HttpInterceptors` for the entire app, import the `HttpClientModule`
* only in your `AppModule`, and add the interceptors to the root application injector .
* If you import `HttpClientModule` multiple times across different modules (for example, in lazy
* loading modules), each import creates a new copy of the `HttpClientModule`, which overwrites the interceptors
* provided in the root module.
* loading modules), each import creates a new copy of the `HttpClientModule`, which overwrites the
* interceptors provided in the root module.
*
*/
export interface HttpInterceptor {

View File

@ -36,7 +36,9 @@ export const JSONP_ERR_WRONG_RESPONSE_TYPE = 'JSONP requests must use Json respo
*
*
*/
export abstract class JsonpCallbackContext { [key: string]: (data: any) => void; }
export abstract class JsonpCallbackContext {
[key: string]: (data: any) => void;
}
/**
* Processes an `HttpRequest` with the JSONP method,
@ -53,7 +55,9 @@ export class JsonpClientBackend implements HttpBackend {
/**
* Get the name of the next callback method, by incrementing the global `nextRequestId`.
*/
private nextCallback(): string { return `ng_jsonp_callback_${nextRequestId++}`; }
private nextCallback(): string {
return `ng_jsonp_callback_${nextRequestId++}`;
}
/**
* Processes a JSONP request and returns an event stream of the results.
@ -157,7 +161,8 @@ export class JsonpClientBackend implements HttpBackend {
observer.next(new HttpResponse({
body,
status: 200,
statusText: 'OK', url,
statusText: 'OK',
url,
}));
// Complete the stream, the response is over.
@ -178,7 +183,8 @@ export class JsonpClientBackend implements HttpBackend {
observer.error(new HttpErrorResponse({
error,
status: 0,
statusText: 'JSONP Error', url,
statusText: 'JSONP Error',
url,
}));
};

View File

@ -52,7 +52,7 @@ export class HttpInterceptingHandler implements HttpHandler {
*
*/
export function interceptingHandler(
backend: HttpBackend, interceptors: HttpInterceptor[] | null = []): HttpHandler {
backend: HttpBackend, interceptors: HttpInterceptor[]|null = []): HttpHandler {
if (!interceptors) {
return backend;
}

View File

@ -37,28 +37,36 @@ export class HttpUrlEncodingCodec implements HttpParameterCodec {
* @param key The key name.
* @returns The encoded key name.
*/
encodeKey(key: string): string { return standardEncoding(key); }
encodeKey(key: string): string {
return standardEncoding(key);
}
/**
* Encodes the value of a URL parameter or query-string.
* @param value The value.
* @returns The encoded value.
*/
encodeValue(value: string): string { return standardEncoding(value); }
encodeValue(value: string): string {
return standardEncoding(value);
}
/**
* Decodes an encoded URL parameter or query-string key.
* @param key The encoded key name.
* @returns The decoded key name.
*/
decodeKey(key: string): string { return decodeURIComponent(key); }
decodeKey(key: string): string {
return decodeURIComponent(key);
}
/**
* Decodes an encoded URL parameter or query-string value.
* @param value The encoded value.
* @returns The decoded value.
*/
decodeValue(value: string) { return decodeURIComponent(value); }
decodeValue(value: string) {
return decodeURIComponent(value);
}
}
@ -97,7 +105,8 @@ interface Update {
op: 'a'|'d'|'s';
}
/** Options used to construct an `HttpParams` instance.
/**
* Options used to construct an `HttpParams` instance.
*
* @publicApi
*/
@ -109,7 +118,7 @@ export interface HttpParamsOptions {
fromString?: string;
/** Object map of the HTTP parameters. Mutually exclusive with `fromString`. */
fromObject?: {[param: string]: string | ReadonlyArray<string>};
fromObject?: {[param: string]: string|ReadonlyArray<string>};
/** Encoding codec used to parse and serialize the parameters. */
encoder?: HttpParameterCodec;
@ -140,7 +149,7 @@ export class HttpParams {
this.map = new Map<string, string[]>();
Object.keys(options.fromObject).forEach(key => {
const value = (options.fromObject as any)[key];
this.map !.set(key, Array.isArray(value) ? value : [value]);
this.map!.set(key, Array.isArray(value) ? value : [value]);
});
} else {
this.map = null;
@ -155,7 +164,7 @@ export class HttpParams {
*/
has(param: string): boolean {
this.init();
return this.map !.has(param);
return this.map!.has(param);
}
/**
@ -166,7 +175,7 @@ export class HttpParams {
*/
get(param: string): string|null {
this.init();
const res = this.map !.get(param);
const res = this.map!.get(param);
return !!res ? res[0] : null;
}
@ -178,7 +187,7 @@ export class HttpParams {
*/
getAll(param: string): string[]|null {
this.init();
return this.map !.get(param) || null;
return this.map!.get(param) || null;
}
/**
@ -187,7 +196,7 @@ export class HttpParams {
*/
keys(): string[] {
this.init();
return Array.from(this.map !.keys());
return Array.from(this.map!.keys());
}
/**
@ -196,7 +205,9 @@ export class HttpParams {
* @param value The new value to add.
* @return A new body with the appended value.
*/
append(param: string, value: string): HttpParams { return this.clone({param, value, op: 'a'}); }
append(param: string, value: string): HttpParams {
return this.clone({param, value, op: 'a'});
}
/**
* Replaces the value for a parameter.
@ -204,7 +215,9 @@ export class HttpParams {
* @param value The new value.
* @return A new body with the new value.
*/
set(param: string, value: string): HttpParams { return this.clone({param, value, op: 's'}); }
set(param: string, value: string): HttpParams {
return this.clone({param, value, op: 's'});
}
/**
* Removes a given value or all values from a parameter.
@ -213,7 +226,9 @@ export class HttpParams {
* @return A new body with the given value removed, or with all values
* removed if no value is specified.
*/
delete (param: string, value?: string): HttpParams { return this.clone({param, value, op: 'd'}); }
delete(param: string, value?: string): HttpParams {
return this.clone({param, value, op: 'd'});
}
/**
* Serializes the body to an encoded string, where key-value pairs (separated by `=`) are
@ -227,7 +242,7 @@ export class HttpParams {
// `a: ['1']` produces `'a=1'`
// `b: []` produces `''`
// `c: ['1', '2']` produces `'c=1&c=2'`
return this.map !.get(key) !.map(value => eKey + '=' + this.encoder.encodeValue(value))
return this.map!.get(key)!.map(value => eKey + '=' + this.encoder.encodeValue(value))
.join('&');
})
// filter out empty values because `b: []` produces `''`
@ -237,7 +252,7 @@ export class HttpParams {
}
private clone(update: Update): HttpParams {
const clone = new HttpParams({ encoder: this.encoder } as HttpParamsOptions);
const clone = new HttpParams({encoder: this.encoder} as HttpParamsOptions);
clone.cloneFrom = this.cloneFrom || this;
clone.updates = (this.updates || []).concat([update]);
return clone;
@ -249,29 +264,29 @@ export class HttpParams {
}
if (this.cloneFrom !== null) {
this.cloneFrom.init();
this.cloneFrom.keys().forEach(key => this.map !.set(key, this.cloneFrom !.map !.get(key) !));
this.updates !.forEach(update => {
this.cloneFrom.keys().forEach(key => this.map!.set(key, this.cloneFrom!.map!.get(key)!));
this.updates!.forEach(update => {
switch (update.op) {
case 'a':
case 's':
const base = (update.op === 'a' ? this.map !.get(update.param) : undefined) || [];
base.push(update.value !);
this.map !.set(update.param, base);
const base = (update.op === 'a' ? this.map!.get(update.param) : undefined) || [];
base.push(update.value!);
this.map!.set(update.param, base);
break;
case 'd':
if (update.value !== undefined) {
let base = this.map !.get(update.param) || [];
let base = this.map!.get(update.param) || [];
const idx = base.indexOf(update.value);
if (idx !== -1) {
base.splice(idx, 1);
}
if (base.length > 0) {
this.map !.set(update.param, base);
this.map!.set(update.param, base);
} else {
this.map !.delete(update.param);
this.map!.delete(update.param);
}
} else {
this.map !.delete(update.param);
this.map!.delete(update.param);
break;
}
}

View File

@ -89,7 +89,7 @@ export class HttpRequest<T> {
* Outgoing headers for this request.
*/
// TODO(issue/24571): remove '!'.
readonly headers !: HttpHeaders;
readonly headers!: HttpHeaders;
/**
* Whether this request should be made in a way that exposes progress events.
@ -121,7 +121,7 @@ export class HttpRequest<T> {
* Outgoing URL parameters.
*/
// TODO(issue/24571): remove '!'.
readonly params !: HttpParams;
readonly params!: HttpParams;
/**
* The outgoing URL with all URL parameters set.
@ -312,7 +312,7 @@ export class HttpRequest<T> {
body?: T|null,
method?: string,
url?: string,
setHeaders?: {[name: string]: string | string[]},
setHeaders?: {[name: string]: string|string[]},
setParams?: {[param: string]: string},
}): HttpRequest<T>;
clone<V>(update: {
@ -324,7 +324,7 @@ export class HttpRequest<T> {
body?: V|null,
method?: string,
url?: string,
setHeaders?: {[name: string]: string | string[]},
setHeaders?: {[name: string]: string|string[]},
setParams?: {[param: string]: string},
}): HttpRequest<V>;
clone(update: {
@ -336,7 +336,7 @@ export class HttpRequest<T> {
body?: any|null,
method?: string,
url?: string,
setHeaders?: {[name: string]: string | string[]},
setHeaders?: {[name: string]: string|string[]},
setParams?: {[param: string]: string};
} = {}): HttpRequest<any> {
// For method, url, and responseType, take the current value unless
@ -368,20 +368,23 @@ export class HttpRequest<T> {
// Set every requested header.
headers =
Object.keys(update.setHeaders)
.reduce((headers, name) => headers.set(name, update.setHeaders ![name]), headers);
.reduce((headers, name) => headers.set(name, update.setHeaders![name]), headers);
}
// Check whether the caller has asked to set params.
if (update.setParams) {
// Set every requested param.
params = Object.keys(update.setParams)
.reduce((params, param) => params.set(param, update.setParams ![param]), params);
.reduce((params, param) => params.set(param, update.setParams![param]), params);
}
// Finally, construct the new HttpRequest using the pieces from above.
return new HttpRequest(
method, url, body, {
params, headers, reportProgress, responseType, withCredentials,
});
return new HttpRequest(method, url, body, {
params,
headers,
reportProgress,
responseType,
withCredentials,
});
}
}

View File

@ -100,7 +100,9 @@ export interface HttpUploadProgressEvent extends HttpProgressEvent {
*
* @publicApi
*/
export interface HttpSentEvent { type: HttpEventType.Sent; }
export interface HttpSentEvent {
type: HttpEventType.Sent;
}
/**
* A user-defined event.
@ -110,7 +112,9 @@ export interface HttpSentEvent { type: HttpEventType.Sent; }
*
* @publicApi
*/
export interface HttpUserEvent<T> { type: HttpEventType.User; }
export interface HttpUserEvent<T> {
type: HttpEventType.User;
}
/**
* An error that represents a failed attempt to JSON.parse text coming back
@ -133,7 +137,7 @@ export interface HttpJsonParseError {
* @publicApi
*/
export type HttpEvent<T> =
HttpSentEvent | HttpHeaderResponse | HttpResponse<T>| HttpProgressEvent | HttpUserEvent<T>;
HttpSentEvent|HttpHeaderResponse|HttpResponse<T>|HttpProgressEvent|HttpUserEvent<T>;
/**
* Base class for both `HttpResponse` and `HttpHeaderResponse`.
@ -172,7 +176,7 @@ export abstract class HttpResponseBase {
* Type of the response, narrowed to either the full response or the header.
*/
// TODO(issue/24571): remove '!'.
readonly type !: HttpEventType.Response | HttpEventType.ResponseHeader;
readonly type!: HttpEventType.Response|HttpEventType.ResponseHeader;
/**
* Super-constructor for all responses.
@ -260,7 +264,11 @@ export class HttpResponse<T> extends HttpResponseBase {
* Construct a new `HttpResponse`.
*/
constructor(init: {
body?: T | null, headers?: HttpHeaders; status?: number; statusText?: string; url?: string;
body?: T|null,
headers?: HttpHeaders;
status?: number;
statusText?: string;
url?: string;
} = {}) {
super(init);
this.body = init.body !== undefined ? init.body : null;
@ -272,10 +280,18 @@ export class HttpResponse<T> extends HttpResponseBase {
clone(update: {headers?: HttpHeaders; status?: number; statusText?: string; url?: string;}):
HttpResponse<T>;
clone<V>(update: {
body?: V | null, headers?: HttpHeaders; status?: number; statusText?: string; url?: string;
body?: V|null,
headers?: HttpHeaders;
status?: number;
statusText?: string;
url?: string;
}): HttpResponse<V>;
clone(update: {
body?: any | null; headers?: HttpHeaders; status?: number; statusText?: string; url?: string;
body?: any|null;
headers?: HttpHeaders;
status?: number;
statusText?: string;
url?: string;
} = {}): HttpResponse<any> {
return new HttpResponse<any>({
body: (update.body !== undefined) ? update.body : this.body,
@ -311,7 +327,11 @@ export class HttpErrorResponse extends HttpResponseBase implements Error {
readonly ok = false;
constructor(init: {
error?: any; headers?: HttpHeaders; status?: number; statusText?: string; url?: string;
error?: any;
headers?: HttpHeaders;
status?: number;
statusText?: string;
url?: string;
}) {
// Initialize with a default status of 0 / Unknown Error.
super(init, 0, 'Unknown Error');
@ -322,8 +342,8 @@ export class HttpErrorResponse extends HttpResponseBase implements Error {
if (this.status >= 200 && this.status < 300) {
this.message = `Http failure during parsing for ${init.url || '(unknown url)'}`;
} else {
this.message =
`Http failure response for ${init.url || '(unknown url)'}: ${init.status} ${init.statusText}`;
this.message = `Http failure response for ${init.url || '(unknown url)'}: ${init.status} ${
init.statusText}`;
}
this.error = init.error || null;
}

View File

@ -35,7 +35,9 @@ function getResponseUrl(xhr: any): string|null {
*
* @publicApi
*/
export abstract class XhrFactory { abstract build(): XMLHttpRequest; }
export abstract class XhrFactory {
abstract build(): XMLHttpRequest;
}
/**
* A factory for `HttpXhrBackend` that uses the `XMLHttpRequest` browser API.
@ -44,7 +46,9 @@ export abstract class XhrFactory { abstract build(): XMLHttpRequest; }
@Injectable()
export class BrowserXhr implements XhrFactory {
constructor() {}
build(): any { return <any>(new XMLHttpRequest()); }
build(): any {
return <any>(new XMLHttpRequest());
}
}
/**
@ -200,7 +204,7 @@ export class HttpXhrBackend implements HttpBackend {
// Even though the response status was 2xx, this is still an error.
ok = false;
// The parse error contains the text of the body that failed to parse.
body = { error, text: body } as HttpJsonParseError;
body = {error, text: body} as HttpJsonParseError;
}
}
}
@ -318,7 +322,7 @@ export class HttpXhrBackend implements HttpBackend {
}
// Fire the request, and notify the event stream that it was fired.
xhr.send(reqBody !);
xhr.send(reqBody!);
observer.next({type: HttpEventType.Sent});
// This is the return from the Observable function, which is the

View File

@ -14,13 +14,15 @@ import {toArray} from 'rxjs/operators';
{
describe('HttpClient', () => {
let client: HttpClient = null !;
let backend: HttpClientTestingBackend = null !;
let client: HttpClient = null!;
let backend: HttpClientTestingBackend = null!;
beforeEach(() => {
backend = new HttpClientTestingBackend();
client = new HttpClient(backend);
});
afterEach(() => { backend.verify(); });
afterEach(() => {
backend.verify();
});
describe('makes a basic request', () => {
it('for JSON data', done => {
client.get('/test').subscribe(res => {

View File

@ -10,7 +10,6 @@ import {HttpHeaders} from '@angular/common/http/src/headers';
{
describe('HttpHeaders', () => {
describe('initialization', () => {
it('should conform to spec', () => {
const httpHeaders = {

View File

@ -18,19 +18,23 @@ export class MockScriptElement {
this.listeners[event] = handler as any;
}
removeEventListener(event: 'load'|'error'): void { delete this.listeners[event]; }
removeEventListener(event: 'load'|'error'): void {
delete this.listeners[event];
}
}
export class MockDocument {
// TODO(issue/24571): remove '!'.
mock !: MockScriptElement | null;
mock!: MockScriptElement|null;
readonly body: any = this;
createElement(tag: 'script'): HTMLScriptElement {
return new MockScriptElement() as any as HTMLScriptElement;
}
appendChild(node: any): void { this.mock = node; }
appendChild(node: any): void {
this.mock = node;
}
removeNode(node: any): void {
if (this.mock === node) {
@ -38,7 +42,11 @@ export class MockDocument {
}
}
mockLoad(): void { this.mock !.listeners.load !(null as any); }
mockLoad(): void {
this.mock!.listeners.load!(null as any);
}
mockError(err: Error) { this.mock !.listeners.error !(err); }
mockError(err: Error) {
this.mock!.listeners.error!(err);
}
}

View File

@ -38,11 +38,15 @@ class TestInterceptor implements HttpInterceptor {
}
class InterceptorA extends TestInterceptor {
constructor() { super('A'); }
constructor() {
super('A');
}
}
class InterceptorB extends TestInterceptor {
constructor() { super('B'); }
constructor() {
super('B');
}
}
@Injectable()
@ -98,7 +102,9 @@ class ReentrantInterceptor implements HttpInterceptor {
{provide: HTTP_INTERCEPTORS, useClass: ReentrantInterceptor, multi: true},
],
});
injector.get(HttpClient).get('/test').subscribe(() => { done(); });
injector.get(HttpClient).get('/test').subscribe(() => {
done();
});
injector.get(HttpTestingController).expectOne('/test').flush('ok!');
});
});

View File

@ -80,16 +80,21 @@ const TEST_STRING = `I'm a body!`;
expect(clone.headers).toBe(headers);
expect(clone.headers.get('Test')).toBe('Test header');
});
it('and updates the url',
() => { expect(req.clone({url: '/changed'}).url).toBe('/changed'); });
it('and updates the method',
() => { expect(req.clone({method: 'PUT'}).method).toBe('PUT'); });
it('and updates the body',
() => { expect(req.clone({body: 'changed body'}).body).toBe('changed body'); });
it('and updates the url', () => {
expect(req.clone({url: '/changed'}).url).toBe('/changed');
});
it('and updates the method', () => {
expect(req.clone({method: 'PUT'}).method).toBe('PUT');
});
it('and updates the body', () => {
expect(req.clone({body: 'changed body'}).body).toBe('changed body');
});
});
describe('content type detection', () => {
const baseReq = new HttpRequest('POST', '/test', null);
it('handles a null body', () => { expect(baseReq.detectContentTypeHeader()).toBeNull(); });
it('handles a null body', () => {
expect(baseReq.detectContentTypeHeader()).toBeNull();
});
it('doesn\'t associate a content type with ArrayBuffers', () => {
const req = baseReq.clone({body: new ArrayBuffer(4)});
expect(req.detectContentTypeHeader()).toBeNull();
@ -113,7 +118,9 @@ const TEST_STRING = `I'm a body!`;
});
describe('body serialization', () => {
const baseReq = new HttpRequest('POST', '/test', null);
it('handles a null body', () => { expect(baseReq.serializeBody()).toBeNull(); });
it('handles a null body', () => {
expect(baseReq.serializeBody()).toBeNull();
});
it('passes ArrayBuffers through', () => {
const body = new ArrayBuffer(4);
expect(baseReq.clone({body}).serializeBody()).toBe(body);
@ -125,8 +132,9 @@ const TEST_STRING = `I'm a body!`;
it('serializes arrays as json', () => {
expect(baseReq.clone({body: ['a', 'b']}).serializeBody()).toBe('["a","b"]');
});
it('handles numbers as json',
() => { expect(baseReq.clone({body: 314159}).serializeBody()).toBe('314159'); });
it('handles numbers as json', () => {
expect(baseReq.clone({body: 314159}).serializeBody()).toBe('314159');
});
it('handles objects as json', () => {
const req = baseReq.clone({body: {data: 'test data'}});
expect(req.serializeBody()).toBe('{"data":"test data"}');

View File

@ -11,9 +11,11 @@ import {XhrFactory} from '@angular/common/http/src/xhr';
export class MockXhrFactory implements XhrFactory {
// TODO(issue/24571): remove '!'.
mock !: MockXMLHttpRequest;
mock!: MockXMLHttpRequest;
build(): XMLHttpRequest { return (this.mock = new MockXMLHttpRequest()) as any; }
build(): XMLHttpRequest {
return (this.mock = new MockXMLHttpRequest()) as any;
}
}
export class MockXMLHttpRequestUpload {
@ -32,9 +34,9 @@ export class MockXMLHttpRequest {
// Set by method calls.
body: any;
// TODO(issue/24571): remove '!'.
method !: string;
method!: string;
// TODO(issue/24571): remove '!'.
url !: string;
url!: string;
mockHeaders: {[key: string]: string} = {};
mockAborted: boolean = false;
@ -64,7 +66,9 @@ export class MockXMLHttpRequest {
this.url = url;
}
send(body: any): void { this.body = body; }
send(body: any): void {
this.body = body;
}
addEventListener(event: 'error'|'load'|'progress'|'uploadProgress', handler: Function): void {
this.listeners[event] = handler as any;
@ -74,9 +78,13 @@ export class MockXMLHttpRequest {
delete this.listeners[event];
}
setRequestHeader(name: string, value: string): void { this.mockHeaders[name] = value; }
setRequestHeader(name: string, value: string): void {
this.mockHeaders[name] = value;
}
getAllResponseHeaders(): string { return this.mockResponseHeaders; }
getAllResponseHeaders(): string {
return this.mockResponseHeaders;
}
getResponseHeader(header: string): string|null {
return new HttpHeaders(this.mockResponseHeaders).get(header);
@ -95,14 +103,17 @@ export class MockXMLHttpRequest {
mockDownloadProgressEvent(loaded: number, total?: number): void {
if (this.listeners.progress) {
this.listeners.progress({ lengthComputable: total !== undefined, loaded, total } as any);
this.listeners.progress({lengthComputable: total !== undefined, loaded, total} as any);
}
}
mockUploadProgressEvent(loaded: number, total?: number) {
if (this.listeners.uploadProgress) {
this.listeners.uploadProgress(
{ lengthComputable: total !== undefined, loaded, total, } as any);
this.listeners.uploadProgress({
lengthComputable: total !== undefined,
loaded,
total,
} as any);
}
}
@ -118,5 +129,7 @@ export class MockXMLHttpRequest {
}
}
abort() { this.mockAborted = true; }
abort() {
this.mockAborted = true;
}
}

View File

@ -13,16 +13,22 @@ import {HttpXsrfCookieExtractor, HttpXsrfInterceptor, HttpXsrfTokenExtractor} fr
import {HttpClientTestingBackend} from '@angular/common/http/testing/src/backend';
class SampleTokenExtractor extends HttpXsrfTokenExtractor {
constructor(private token: string|null) { super(); }
constructor(private token: string|null) {
super();
}
getToken(): string|null { return this.token; }
getToken(): string|null {
return this.token;
}
}
{
describe('HttpXsrfInterceptor', () => {
let backend: HttpClientTestingBackend;
const interceptor = new HttpXsrfInterceptor(new SampleTokenExtractor('test'), 'X-XSRF-TOKEN');
beforeEach(() => { backend = new HttpClientTestingBackend(); });
beforeEach(() => {
backend = new HttpClientTestingBackend();
});
it('applies XSRF protection to outgoing requests', () => {
interceptor.intercept(new HttpRequest('POST', '/test', {}), backend).subscribe();
const req = backend.expectOne('/test');
@ -59,7 +65,9 @@ class SampleTokenExtractor extends HttpXsrfTokenExtractor {
expect(req.request.headers.has('X-XSRF-TOKEN')).toEqual(false);
req.flush({});
});
afterEach(() => { backend.verify(); });
afterEach(() => {
backend.verify();
});
});
describe('HttpXsrfCookieExtractor', () => {
let document: {[key: string]: string};
@ -70,8 +78,9 @@ class SampleTokenExtractor extends HttpXsrfTokenExtractor {
};
extractor = new HttpXsrfCookieExtractor(document, 'browser', 'XSRF-TOKEN');
});
it('parses the cookie from document.cookie',
() => { expect(extractor.getToken()).toEqual('test'); });
it('parses the cookie from document.cookie', () => {
expect(extractor.getToken()).toEqual('test');
});
it('does not re-parse if document.cookie has not changed', () => {
expect(extractor.getToken()).toEqual('test');
expect(extractor.getToken()).toEqual('test');

View File

@ -39,8 +39,10 @@ export class HttpClientTestingBackend implements HttpBackend, HttpTestingControl
return new Observable((observer: Observer<any>) => {
const testReq = new TestRequest(req, observer);
this.open.push(testReq);
observer.next({ type: HttpEventType.Sent } as HttpEvent<any>);
return () => { testReq._cancelled = true; };
observer.next({type: HttpEventType.Sent} as HttpEvent<any>);
return () => {
testReq._cancelled = true;
};
});
}
@ -86,8 +88,8 @@ export class HttpClientTestingBackend implements HttpBackend, HttpTestingControl
description = description || this.descriptionFromMatcher(match);
const matches = this.match(match);
if (matches.length > 1) {
throw new Error(
`Expected one matching request for criteria "${description}", found ${matches.length} requests.`);
throw new Error(`Expected one matching request for criteria "${description}", found ${
matches.length} requests.`);
}
if (matches.length === 0) {
let message = `Expected one matching request for criteria "${description}", found none.`;
@ -116,8 +118,8 @@ export class HttpClientTestingBackend implements HttpBackend, HttpTestingControl
description = description || this.descriptionFromMatcher(match);
const matches = this.match(match);
if (matches.length > 0) {
throw new Error(
`Expected zero matching requests for criteria "${description}", found ${matches.length}.`);
throw new Error(`Expected zero matching requests for criteria "${description}", found ${
matches.length}.`);
}
}

View File

@ -21,7 +21,9 @@ export class TestRequest {
/**
* Whether the request was cancelled after it was sent.
*/
get cancelled(): boolean { return this._cancelled; }
get cancelled(): boolean {
return this._cancelled;
}
/**
* @internal set by `HttpClientTestingBackend`
@ -39,7 +41,7 @@ export class TestRequest {
* Both successful and unsuccessful responses can be delivered via `flush()`.
*/
flush(body: ArrayBuffer|Blob|string|number|Object|(string|number|Object|null)[]|null, opts: {
headers?: HttpHeaders | {[name: string]: string | string[]},
headers?: HttpHeaders|{[name: string]: string | string[]},
status?: number,
statusText?: string,
} = {}): void {
@ -75,7 +77,7 @@ export class TestRequest {
* Resolve the request by returning an `ErrorEvent` (e.g. simulating a network failure).
*/
error(error: ErrorEvent, opts: {
headers?: HttpHeaders | {[name: string]: string | string[]},
headers?: HttpHeaders|{[name: string]: string | string[]},
status?: number,
statusText?: string,
} = {}): void {
@ -112,9 +114,8 @@ export class TestRequest {
/**
* Helper function to convert a response body to an ArrayBuffer.
*/
function _toArrayBufferBody(
body: ArrayBuffer | Blob | string | number | Object |
(string | number | Object | null)[]): ArrayBuffer {
function _toArrayBufferBody(body: ArrayBuffer|Blob|string|number|Object|
(string | number | Object | null)[]): ArrayBuffer {
if (typeof ArrayBuffer === 'undefined') {
throw new Error('ArrayBuffer responses are not supported on this platform.');
}
@ -127,9 +128,8 @@ function _toArrayBufferBody(
/**
* Helper function to convert a response body to a Blob.
*/
function _toBlob(
body: ArrayBuffer | Blob | string | number | Object |
(string | number | Object | null)[]): Blob {
function _toBlob(body: ArrayBuffer|Blob|string|number|Object|
(string | number | Object | null)[]): Blob {
if (typeof Blob === 'undefined') {
throw new Error('Blob responses are not supported on this platform.');
}
@ -146,7 +146,7 @@ function _toBlob(
* Helper function to convert a response body to JSON data.
*/
function _toJsonBody(
body: ArrayBuffer | Blob | string | number | Object | (string | number | Object | null)[],
body: ArrayBuffer|Blob|string|number|Object|(string | number | Object | null)[],
format: string = 'JSON'): Object|string|number|(Object | string | number)[] {
if (typeof ArrayBuffer !== 'undefined' && body instanceof ArrayBuffer) {
throw new Error(`Automatic conversion to ${format} is not supported for ArrayBuffers.`);
@ -164,9 +164,8 @@ function _toJsonBody(
/**
* Helper function to convert a response body to a string.
*/
function _toTextBody(
body: ArrayBuffer | Blob | string | number | Object |
(string | number | Object | null)[]): string {
function _toTextBody(body: ArrayBuffer|Blob|string|number|Object|
(string | number | Object | null)[]): string {
if (typeof body === 'string') {
return body;
}
@ -183,9 +182,9 @@ function _toTextBody(
* Convert a response body to the requested type.
*/
function _maybeConvertBody(
responseType: string, body: ArrayBuffer | Blob | string | number | Object |
(string | number | Object | null)[] | null): ArrayBuffer|Blob|string|number|Object|
(string | number | Object | null)[]|null {
responseType: string,
body: ArrayBuffer|Blob|string|number|Object|(string | number | Object | null)[]|
null): ArrayBuffer|Blob|string|number|Object|(string | number | Object | null)[]|null {
if (body === null) {
return null;
}

View File

@ -15,7 +15,9 @@ describe('HttpClient TestRequest', () => {
const client = new HttpClient(mock);
let resp: any;
client.post('/some-url', {test: 'test'}).subscribe(body => { resp = body; });
client.post('/some-url', {test: 'test'}).subscribe(body => {
resp = body;
});
const req = mock.expectOne('/some-url');
req.flush(null);
@ -28,7 +30,9 @@ describe('HttpClient TestRequest', () => {
const client = new HttpClient(mock);
let resp: any;
client.get('/some-other-url').subscribe(body => { resp = body; });
client.get('/some-other-url').subscribe(body => {
resp = body;
});
try {
// expect different URL
@ -48,7 +52,9 @@ describe('HttpClient TestRequest', () => {
let resp: any;
const params = {query: 'hello'};
client.get('/some-url', {params}).subscribe(body => { resp = body; });
client.get('/some-url', {params}).subscribe(body => {
resp = body;
});
try {
// expect different query parameters
@ -67,8 +73,12 @@ describe('HttpClient TestRequest', () => {
const client = new HttpClient(mock);
let resp: any;
client.get('/some-other-url?query=world').subscribe(body => { resp = body; });
client.post('/and-another-url', {}).subscribe(body => { resp = body; });
client.get('/some-other-url?query=world').subscribe(body => {
resp = body;
});
client.post('/and-another-url', {}).subscribe(body => {
resp = body;
});
try {
// expect different URL

View File

@ -7,7 +7,7 @@
*/
import {Directive, DoCheck, ElementRef, Input, IterableChanges, IterableDiffer, IterableDiffers, KeyValueChanges, KeyValueDiffer, KeyValueDiffers, Renderer2, ɵisListLikeIterable as isListLikeIterable, ɵstringify as stringify} from '@angular/core';
type NgClassSupportedTypes = string[] | Set<string>| {[klass: string]: any} | null | undefined;
type NgClassSupportedTypes = string[]|Set<string>|{[klass: string]: any}|null|undefined;
/**
* @ngModule CommonModule
@ -83,7 +83,7 @@ export class NgClass implements DoCheck {
this._applyIterableChanges(iterableChanges);
}
} else if (this._keyValueDiffer) {
const keyValueChanges = this._keyValueDiffer.diff(this._rawClass as{[k: string]: any});
const keyValueChanges = this._keyValueDiffer.diff(this._rawClass as {[k: string]: any});
if (keyValueChanges) {
this._applyKeyValueChanges(keyValueChanges);
}
@ -105,8 +105,8 @@ export class NgClass implements DoCheck {
if (typeof record.item === 'string') {
this._toggleClass(record.item, true);
} else {
throw new Error(
`NgClass can only toggle CSS classes expressed as strings, got ${stringify(record.item)}`);
throw new Error(`NgClass can only toggle CSS classes expressed as strings, got ${
stringify(record.item)}`);
}
});

View File

@ -67,13 +67,13 @@ import {ComponentFactoryResolver, ComponentRef, Directive, Injector, Input, NgMo
@Directive({selector: '[ngComponentOutlet]'})
export class NgComponentOutlet implements OnChanges, OnDestroy {
// TODO(issue/24571): remove '!'.
@Input() ngComponentOutlet !: Type<any>;
@Input() ngComponentOutlet!: Type<any>;
// TODO(issue/24571): remove '!'.
@Input() ngComponentOutletInjector !: Injector;
@Input() ngComponentOutletInjector!: Injector;
// TODO(issue/24571): remove '!'.
@Input() ngComponentOutletContent !: any[][];
@Input() ngComponentOutletContent!: any[][];
// TODO(issue/24571): remove '!'.
@Input() ngComponentOutletNgModuleFactory !: NgModuleFactory<any>;
@Input() ngComponentOutletNgModuleFactory!: NgModuleFactory<any>;
private _componentRef: ComponentRef<any>|null = null;
private _moduleRef: NgModuleRef<any>|null = null;

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Directive, DoCheck, EmbeddedViewRef, Input, IterableChangeRecord, IterableChanges, IterableDiffer, IterableDiffers, NgIterable, TemplateRef, TrackByFunction, ViewContainerRef, isDevMode} from '@angular/core';
import {Directive, DoCheck, EmbeddedViewRef, Input, isDevMode, IterableChangeRecord, IterableChanges, IterableDiffer, IterableDiffers, NgIterable, TemplateRef, TrackByFunction, ViewContainerRef} from '@angular/core';
/**
* @publicApi
@ -14,13 +14,21 @@ import {Directive, DoCheck, EmbeddedViewRef, Input, IterableChangeRecord, Iterab
export class NgForOfContext<T, U extends NgIterable<T> = NgIterable<T>> {
constructor(public $implicit: T, public ngForOf: U, public index: number, public count: number) {}
get first(): boolean { return this.index === 0; }
get first(): boolean {
return this.index === 0;
}
get last(): boolean { return this.index === this.count - 1; }
get last(): boolean {
return this.index === this.count - 1;
}
get even(): boolean { return this.index % 2 === 0; }
get even(): boolean {
return this.index % 2 === 0;
}
get odd(): boolean { return !this.even; }
get odd(): boolean {
return !this.even;
}
}
/**
@ -162,13 +170,15 @@ export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCh
this._trackByFn = fn;
}
get ngForTrackBy(): TrackByFunction<T> { return this._trackByFn; }
get ngForTrackBy(): TrackByFunction<T> {
return this._trackByFn;
}
private _ngForOf: U|undefined|null = null;
private _ngForOfDirty: boolean = true;
private _differ: IterableDiffer<T>|null = null;
// TODO(issue/24571): remove '!'.
private _trackByFn !: TrackByFunction<T>;
private _trackByFn!: TrackByFunction<T>;
constructor(
private _viewContainer: ViewContainerRef,
@ -200,8 +210,8 @@ export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCh
try {
this._differ = this._differs.find(value).create(this.ngForTrackBy);
} catch {
throw new Error(
`Cannot find a differ supporting object '${value}' of type '${getTypeName(value)}'. NgFor only supports binding to Iterables such as Arrays.`);
throw new Error(`Cannot find a differ supporting object '${value}' of type '${
getTypeName(value)}'. NgFor only supports binding to Iterables such as Arrays.`);
}
}
}
@ -214,14 +224,14 @@ export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCh
private _applyChanges(changes: IterableChanges<T>) {
const insertTuples: RecordViewTuple<T, U>[] = [];
changes.forEachOperation(
(item: IterableChangeRecord<any>, adjustedPreviousIndex: number | null,
currentIndex: number | null) => {
(item: IterableChangeRecord<any>, adjustedPreviousIndex: number|null,
currentIndex: number|null) => {
if (item.previousIndex == null) {
// NgForOf is never "null" or "undefined" here because the differ detected
// that a new item needs to be inserted from the iterable. This implies that
// there is an iterable value for "_ngForOf".
const view = this._viewContainer.createEmbeddedView(
this._template, new NgForOfContext<T, U>(null !, this._ngForOf !, -1, -1),
this._template, new NgForOfContext<T, U>(null!, this._ngForOf!, -1, -1),
currentIndex === null ? undefined : currentIndex);
const tuple = new RecordViewTuple<T, U>(item, view);
insertTuples.push(tuple);
@ -229,7 +239,7 @@ export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCh
this._viewContainer.remove(
adjustedPreviousIndex === null ? undefined : adjustedPreviousIndex);
} else if (adjustedPreviousIndex !== null) {
const view = this._viewContainer.get(adjustedPreviousIndex) !;
const view = this._viewContainer.get(adjustedPreviousIndex)!;
this._viewContainer.move(view, currentIndex);
const tuple = new RecordViewTuple(item, <EmbeddedViewRef<NgForOfContext<T, U>>>view);
insertTuples.push(tuple);
@ -244,7 +254,7 @@ export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCh
const viewRef = <EmbeddedViewRef<NgForOfContext<T, U>>>this._viewContainer.get(i);
viewRef.context.index = i;
viewRef.context.count = ilen;
viewRef.context.ngForOf = this._ngForOf !;
viewRef.context.ngForOf = this._ngForOf!;
}
changes.forEachIdentityChange((record: any) => {

View File

@ -241,11 +241,11 @@ export class NgIf<T = unknown> {
* @publicApi
*/
export class NgIfContext<T = unknown> {
public $implicit: T = null !;
public ngIf: T = null !;
public $implicit: T = null!;
public ngIf: T = null!;
}
function assertTemplate(property: string, templateRef: TemplateRef<any>| null): void {
function assertTemplate(property: string, templateRef: TemplateRef<any>|null): void {
const isTemplateRefOrNull = !!(!templateRef || templateRef.createEmbeddedView);
if (!isTemplateRefOrNull) {
throw new Error(`${property} must be a TemplateRef, but received '${stringify(templateRef)}'.`);

View File

@ -8,7 +8,7 @@
import {Attribute, Directive, Host, Input, TemplateRef, ViewContainerRef} from '@angular/core';
import {NgLocalization, getPluralCategory} from '../i18n/localization';
import {getPluralCategory, NgLocalization} from '../i18n/localization';
import {SwitchView} from './ng_switch';
@ -47,9 +47,9 @@ import {SwitchView} from './ng_switch';
@Directive({selector: '[ngPlural]'})
export class NgPlural {
// TODO(issue/24571): remove '!'.
private _switchValue !: number;
private _switchValue!: number;
// TODO(issue/24571): remove '!'.
private _activeView !: SwitchView;
private _activeView!: SwitchView;
private _caseViews: {[k: string]: SwitchView} = {};
constructor(private _localization: NgLocalization) {}
@ -60,7 +60,9 @@ export class NgPlural {
this._updateView();
}
addCase(value: string, switchView: SwitchView): void { this._caseViews[value] = switchView; }
addCase(value: string, switchView: SwitchView): void {
this._caseViews[value] = switchView;
}
private _updateView(): void {
this._clearViews();

View File

@ -62,7 +62,7 @@ export class NgStyle implements DoCheck {
ngDoCheck() {
if (this._differ) {
const changes = this._differ.diff(this._ngStyle !);
const changes = this._differ.diff(this._ngStyle!);
if (changes) {
this._applyChanges(changes);
}

View File

@ -104,7 +104,7 @@ export class SwitchView {
@Directive({selector: '[ngSwitch]'})
export class NgSwitch {
// TODO(issue/24571): remove '!'.
private _defaultViews !: SwitchView[];
private _defaultViews!: SwitchView[];
private _defaultUsed = false;
private _caseCount = 0;
private _lastCaseCheckIndex = 0;
@ -120,7 +120,9 @@ export class NgSwitch {
}
/** @internal */
_addCase(): number { return this._caseCount++; }
_addCase(): number {
return this._caseCount++;
}
/** @internal */
_addDefault(view: SwitchView) {
@ -193,8 +195,7 @@ export class NgSwitchCase implements DoCheck {
/**
* Stores the HTML template to be selected on match.
*/
@Input()
ngSwitchCase: any;
@Input() ngSwitchCase: any;
constructor(
viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>,
@ -206,7 +207,9 @@ export class NgSwitchCase implements DoCheck {
/**
* Performs case matching. For internal use only.
*/
ngDoCheck() { this._view.enforceState(this.ngSwitch._matchCase(this.ngSwitchCase)); }
ngDoCheck() {
this._view.enforceState(this.ngSwitch._matchCase(this.ngSwitchCase));
}
}
/**

View File

@ -101,7 +101,7 @@ export class NgTemplateOutlet implements OnChanges {
private _updateExistingContext(ctx: Object): void {
for (let propName of Object.keys(ctx)) {
(<any>this._viewRef !.context)[propName] = (<any>this.ngTemplateOutletContext)[propName];
(<any>this._viewRef!.context)[propName] = (<any>this.ngTemplateOutletContext)[propName];
}
}
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
let _DOM: DomAdapter = null !;
let _DOM: DomAdapter = null!;
export function getDOM(): DomAdapter {
return _DOM;

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {FormStyle, FormatWidth, NumberSymbol, Time, TranslationWidth, getLocaleDateFormat, getLocaleDateTimeFormat, getLocaleDayNames, getLocaleDayPeriods, getLocaleEraNames, getLocaleExtraDayPeriodRules, getLocaleExtraDayPeriods, getLocaleId, getLocaleMonthNames, getLocaleNumberSymbol, getLocaleTimeFormat} from './locale_data_api';
import {FormatWidth, FormStyle, getLocaleDateFormat, getLocaleDateTimeFormat, getLocaleDayNames, getLocaleDayPeriods, getLocaleEraNames, getLocaleExtraDayPeriodRules, getLocaleExtraDayPeriods, getLocaleId, getLocaleMonthNames, getLocaleNumberSymbol, getLocaleTimeFormat, NumberSymbol, Time, TranslationWidth} from './locale_data_api';
export const ISO8601_DATE_REGEX =
/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
@ -62,7 +62,7 @@ enum TranslationType {
* @publicApi
*/
export function formatDate(
value: string | number | Date, format: string, locale: string, timezone?: string): string {
value: string|number|Date, format: string, locale: string, timezone?: string): string {
let date = toDate(value);
const namedFormat = getNamedFormat(locale, format);
format = namedFormat || format;
@ -278,7 +278,7 @@ function getDateTranslation(
const rules = getLocaleExtraDayPeriodRules(locale);
const dayPeriods = getLocaleExtraDayPeriods(locale, form, width);
let result;
rules.forEach((rule: Time | [Time, Time], index: number) => {
rules.forEach((rule: Time|[Time, Time], index: number) => {
if (Array.isArray(rule)) {
// morning, afternoon, evening, night
const {hours: hoursFrom, minutes: minutesFrom} = rule[0];
@ -652,7 +652,7 @@ function convertTimezoneToLocal(date: Date, timezone: string, reverse: boolean):
*
* Throws if unable to convert to a date.
*/
export function toDate(value: string | number | Date): Date {
export function toDate(value: string|number|Date): Date {
if (isDate(value)) {
return value;
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {NumberFormatStyle, NumberSymbol, getLocaleNumberFormat, getLocaleNumberSymbol, getNumberOfCurrencyDigits} from './locale_data_api';
import {getLocaleNumberFormat, getLocaleNumberSymbol, getNumberOfCurrencyDigits, NumberFormatStyle, NumberSymbol} from './locale_data_api';
export const NUMBER_FORMAT_REGEXP = /^(\d+)?\.((\d+)(-(\d+))?)?$/;
const MAX_DIGITS = 22;
@ -153,7 +153,7 @@ export function formatCurrency(
const format = getLocaleNumberFormat(locale, NumberFormatStyle.Currency);
const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
pattern.minFrac = getNumberOfCurrencyDigits(currencyCode !);
pattern.minFrac = getNumberOfCurrencyDigits(currencyCode!);
pattern.maxFrac = pattern.minFrac;
const res = formatNumberToLocaleString(
@ -392,8 +392,8 @@ function parseNumber(num: number): ParsedNumber {
*/
function roundNumber(parsedNumber: ParsedNumber, minFrac: number, maxFrac: number) {
if (minFrac > maxFrac) {
throw new Error(
`The minimum number of digits after fraction (${minFrac}) is higher than the maximum (${maxFrac}).`);
throw new Error(`The minimum number of digits after fraction (${
minFrac}) is higher than the maximum (${maxFrac}).`);
}
let digits = parsedNumber.digits;

View File

@ -16,6 +16,6 @@ import {ɵregisterLocaleData} from '@angular/core';
*
* @publicApi
*/
export function registerLocaleData(data: any, localeId?: string | any, extraData?: any): void {
export function registerLocaleData(data: any, localeId?: string|any, extraData?: any): void {
return ɵregisterLocaleData(data, localeId, extraData);
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ɵCurrencyIndex, ɵExtraLocaleDataIndex, ɵLocaleDataIndex, ɵfindLocaleData, ɵgetLocaleCurrencyCode, ɵgetLocalePluralCase} from '@angular/core';
import {ɵCurrencyIndex, ɵExtraLocaleDataIndex, ɵfindLocaleData, ɵgetLocaleCurrencyCode, ɵgetLocalePluralCase, ɵLocaleDataIndex} from '@angular/core';
import {CURRENCIES_EN, CurrenciesSymbols} from './currencies';
@ -235,9 +235,9 @@ export function getLocaleId(locale: string): string {
export function getLocaleDayPeriods(
locale: string, formStyle: FormStyle, width: TranslationWidth): [string, string] {
const data = ɵfindLocaleData(locale);
const amPmData = <[
string, string
][][]>[data[ɵLocaleDataIndex.DayPeriodsFormat], data[ɵLocaleDataIndex.DayPeriodsStandalone]];
const amPmData = <[string, string][][]>[
data[ɵLocaleDataIndex.DayPeriodsFormat], data[ɵLocaleDataIndex.DayPeriodsStandalone]
];
const amPm = getLastDefinedValue(amPmData, formStyle);
return getLastDefinedValue(amPm, width);
}
@ -509,8 +509,9 @@ export const getLocalePluralCase: (locale: string) => ((value: number) => Plural
function checkFullData(data: any) {
if (!data[ɵLocaleDataIndex.ExtraData]) {
throw new Error(
`Missing extra locale data for the locale "${data[ɵLocaleDataIndex.LocaleId]}". Use "registerLocaleData" to load new data. See the "I18n guide" on angular.io to know more.`);
throw new Error(`Missing extra locale data for the locale "${
data[ɵLocaleDataIndex
.LocaleId]}". Use "registerLocaleData" to load new data. See the "I18n guide" on angular.io to know more.`);
}
}
@ -536,11 +537,11 @@ function checkFullData(data: any) {
*
* @publicApi
*/
export function getLocaleExtraDayPeriodRules(locale: string): (Time | [Time, Time])[] {
export function getLocaleExtraDayPeriodRules(locale: string): (Time|[Time, Time])[] {
const data = ɵfindLocaleData(locale);
checkFullData(data);
const rules = data[ɵLocaleDataIndex.ExtraData][ɵExtraLocaleDataIndex.ExtraDayPeriodsRules] || [];
return rules.map((rule: string | [string, string]) => {
return rules.map((rule: string|[string, string]) => {
if (typeof rule === 'string') {
return extractTime(rule);
}
@ -570,8 +571,8 @@ export function getLocaleExtraDayPeriods(
const data = ɵfindLocaleData(locale);
checkFullData(data);
const dayPeriodsData = <string[][][]>[
data[ɵLocaleDataIndex.ExtraData][ɵExtraLocaleDataIndex.ExtraDayPeriodFormats],
data[ɵLocaleDataIndex.ExtraData][ɵExtraLocaleDataIndex.ExtraDayPeriodStandalone]
data[ɵLocaleDataIndex.ExtraData][ɵExtraLocaleDataIndex.ExtraDayPeriodFormats],
data[ɵLocaleDataIndex.ExtraData][ɵExtraLocaleDataIndex.ExtraDayPeriodStandalone]
];
const dayPeriods = getLastDefinedValue(dayPeriodsData, formStyle) || [];
return getLastDefinedValue(dayPeriods, width) || [];
@ -646,7 +647,7 @@ function extractTime(time: string): Time {
*
* @publicApi
*/
export function getCurrencySymbol(code: string, format: 'wide' | 'narrow', locale = 'en'): string {
export function getCurrencySymbol(code: string, format: 'wide'|'narrow', locale = 'en'): string {
const currency = getLocaleCurrencies(locale)[code] || CURRENCIES_EN[code] || [];
const symbolNarrow = currency[ɵCurrencyIndex.SymbolNarrow];

View File

@ -7,7 +7,8 @@
*/
import {Inject, Injectable, LOCALE_ID} from '@angular/core';
import {Plural, getLocalePluralCase} from './locale_data_api';
import {getLocalePluralCase, Plural} from './locale_data_api';
/**
@ -51,7 +52,9 @@ export function getPluralCategory(
*/
@Injectable()
export class NgLocaleLocalization extends NgLocalization {
constructor(@Inject(LOCALE_ID) protected locale: string) { super(); }
constructor(@Inject(LOCALE_ID) protected locale: string) {
super();
}
getPluralCategory(value: any, locale?: string): string {
const plural = getLocalePluralCase(locale || this.locale)(value);

View File

@ -48,7 +48,9 @@ export class HashLocationStrategy extends LocationStrategy {
this._platformLocation.onHashChange(fn);
}
getBaseHref(): string { return this._baseHref; }
getBaseHref(): string {
return this._baseHref;
}
path(includeHash: boolean = false): string {
// the hash value is always prefixed with a `#`
@ -80,7 +82,11 @@ export class HashLocationStrategy extends LocationStrategy {
this._platformLocation.replaceState(state, title, url);
}
forward(): void { this._platformLocation.forward(); }
forward(): void {
this._platformLocation.forward();
}
back(): void { this._platformLocation.back(); }
back(): void {
this._platformLocation.back();
}
}

View File

@ -97,7 +97,9 @@ export class Location {
* Reports the current state of the location history.
* @returns The current value of the `history.state` object.
*/
getState(): unknown { return this._platformLocation.getState(); }
getState(): unknown {
return this._platformLocation.getState();
}
/**
* Normalizes the given path and compares to the current normalized path.
@ -173,12 +175,16 @@ export class Location {
/**
* Navigates forward in the platform's history.
*/
forward(): void { this._platformStrategy.forward(); }
forward(): void {
this._platformStrategy.forward();
}
/**
* Navigates back in the platform's history.
*/
back(): void { this._platformStrategy.back(); }
back(): void {
this._platformStrategy.back();
}
/**
* Registers a URL change listener. Use to catch updates performed by the Angular
@ -188,7 +194,9 @@ export class Location {
*/
onUrlChange(fn: (url: string, state: unknown) => void) {
this._urlChangeListeners.push(fn);
this.subscribe(v => { this._notifyUrlChangeListeners(v.url, v.state); });
this.subscribe(v => {
this._notifyUrlChangeListeners(v.url, v.state);
});
}
/** @internal */

View File

@ -126,9 +126,13 @@ export class PathLocationStrategy extends LocationStrategy {
this._platformLocation.onHashChange(fn);
}
getBaseHref(): string { return this._baseHref; }
getBaseHref(): string {
return this._baseHref;
}
prepareExternalUrl(internal: string): string { return joinWithSlash(this._baseHref, internal); }
prepareExternalUrl(internal: string): string {
return joinWithSlash(this._baseHref, internal);
}
path(includeHash: boolean = false): string {
const pathname =
@ -147,7 +151,11 @@ export class PathLocationStrategy extends LocationStrategy {
this._platformLocation.replaceState(state, title, externalUrl);
}
forward(): void { this._platformLocation.forward(); }
forward(): void {
this._platformLocation.forward();
}
back(): void { this._platformLocation.back(); }
back(): void {
this._platformLocation.back();
}
}

View File

@ -86,7 +86,9 @@ export interface LocationChangeEvent {
/**
* @publicApi
*/
export interface LocationChangeListener { (event: LocationChangeEvent): any; }
export interface LocationChangeListener {
(event: LocationChangeEvent): any;
}
@ -101,8 +103,8 @@ export interface LocationChangeListener { (event: LocationChangeEvent): any; }
useFactory: createBrowserPlatformLocation,
})
export class BrowserPlatformLocation extends PlatformLocation {
public readonly location !: Location;
private _history !: History;
public readonly location!: Location;
private _history!: History;
constructor(@Inject(DOCUMENT) private _doc: any) {
super();
@ -112,11 +114,13 @@ export class BrowserPlatformLocation extends PlatformLocation {
// This is moved to its own method so that `MockPlatformLocationStrategy` can overwrite it
/** @internal */
_init() {
(this as{location: Location}).location = getDOM().getLocation();
(this as {location: Location}).location = getDOM().getLocation();
this._history = getDOM().getHistory();
}
getBaseHrefFromDOM(): string { return getDOM().getBaseHref(this._doc) !; }
getBaseHrefFromDOM(): string {
return getDOM().getBaseHref(this._doc)!;
}
onPopState(fn: LocationChangeListener): void {
getDOM().getGlobalEventTarget(this._doc, 'window').addEventListener('popstate', fn, false);
@ -126,14 +130,30 @@ export class BrowserPlatformLocation extends PlatformLocation {
getDOM().getGlobalEventTarget(this._doc, 'window').addEventListener('hashchange', fn, false);
}
get href(): string { return this.location.href; }
get protocol(): string { return this.location.protocol; }
get hostname(): string { return this.location.hostname; }
get port(): string { return this.location.port; }
get pathname(): string { return this.location.pathname; }
get search(): string { return this.location.search; }
get hash(): string { return this.location.hash; }
set pathname(newPath: string) { this.location.pathname = newPath; }
get href(): string {
return this.location.href;
}
get protocol(): string {
return this.location.protocol;
}
get hostname(): string {
return this.location.hostname;
}
get port(): string {
return this.location.port;
}
get pathname(): string {
return this.location.pathname;
}
get search(): string {
return this.location.search;
}
get hash(): string {
return this.location.hash;
}
set pathname(newPath: string) {
this.location.pathname = newPath;
}
pushState(state: any, title: string, url: string): void {
if (supportsState()) {
@ -151,11 +171,17 @@ export class BrowserPlatformLocation extends PlatformLocation {
}
}
forward(): void { this._history.forward(); }
forward(): void {
this._history.forward();
}
back(): void { this._history.back(); }
back(): void {
this._history.back();
}
getState(): unknown { return this._history.state; }
getState(): unknown {
return this._history.state;
}
}
export function supportsState(): boolean {

View File

@ -19,17 +19,28 @@ interface SubscriptionStrategy {
class ObservableStrategy implements SubscriptionStrategy {
createSubscription(async: Observable<any>, updateLatestValue: any): SubscriptionLike {
return async.subscribe({next: updateLatestValue, error: (e: any) => { throw e; }});
return async.subscribe({
next: updateLatestValue,
error: (e: any) => {
throw e;
}
});
}
dispose(subscription: SubscriptionLike): void { subscription.unsubscribe(); }
dispose(subscription: SubscriptionLike): void {
subscription.unsubscribe();
}
onDestroy(subscription: SubscriptionLike): void { subscription.unsubscribe(); }
onDestroy(subscription: SubscriptionLike): void {
subscription.unsubscribe();
}
}
class PromiseStrategy implements SubscriptionStrategy {
createSubscription(async: Promise<any>, updateLatestValue: (v: any) => any): Promise<any> {
return async.then(updateLatestValue, e => { throw e; });
return async.then(updateLatestValue, e => {
throw e;
});
}
dispose(subscription: Promise<any>): void {}
@ -74,7 +85,7 @@ export class AsyncPipe implements OnDestroy, PipeTransform {
private _subscription: SubscriptionLike|Promise<any>|null = null;
private _obj: Observable<any>|Promise<any>|EventEmitter<any>|null = null;
private _strategy: SubscriptionStrategy = null !;
private _strategy: SubscriptionStrategy = null!;
constructor(private _ref: ChangeDetectorRef) {}
@ -130,7 +141,7 @@ export class AsyncPipe implements OnDestroy, PipeTransform {
}
private _dispose(): void {
this._strategy.dispose(this._subscription !);
this._strategy.dispose(this._subscription!);
this._latestValue = null;
this._latestReturnedValue = null;
this._subscription = null;

View File

@ -7,7 +7,9 @@
*/
import {Pipe, PipeTransform} from '@angular/core';
import {NgLocalization, getPluralCategory} from '../i18n/localization';
import {getPluralCategory, NgLocalization} from '../i18n/localization';
import {invalidPipeArgumentError} from './invalid_pipe_argument_error';
const _INTERPOLATION_REGEXP: RegExp = /#/g;

View File

@ -26,11 +26,11 @@ export {
CurrencyPipe,
DatePipe,
DecimalPipe,
KeyValue,
KeyValuePipe,
I18nPluralPipe,
I18nSelectPipe,
JsonPipe,
KeyValue,
KeyValuePipe,
LowerCasePipe,
PercentPipe,
SlicePipe,

View File

@ -28,5 +28,7 @@ export class JsonPipe implements PipeTransform {
/**
* @param value A value of any type to convert into a JSON-format string.
*/
transform(value: any): string { return JSON.stringify(value, null, 2); }
transform(value: any): string {
return JSON.stringify(value, null, 2);
}
}

View File

@ -47,7 +47,7 @@ export interface KeyValue<K, V> {
export class KeyValuePipe implements PipeTransform {
constructor(private readonly differs: KeyValueDiffers) {}
private differ !: KeyValueDiffer<any, any>;
private differ!: KeyValueDiffer<any, any>;
private keyValues: Array<KeyValue<any, any>> = [];
transform<K, V>(input: null, compareFn?: (a: KeyValue<K, V>, b: KeyValue<K, V>) => number): null;
@ -90,7 +90,7 @@ export class KeyValuePipe implements PipeTransform {
if (differChanges) {
this.keyValues = [];
differChanges.forEachItem((r: KeyValueChangeRecord<K, V>) => {
this.keyValues.push(makeKeyValuePair(r.key, r.currentValue !));
this.keyValues.push(makeKeyValuePair(r.key, r.currentValue!));
});
this.keyValues.sort(compareFn);
}

View File

@ -253,7 +253,7 @@ function isEmpty(value: any): boolean {
/**
* Transforms a string into a number (if needed).
*/
function strToNumber(value: number | string): number {
function strToNumber(value: number|string): number {
// Convert strings to numbers
if (typeof value === 'string' && !isNaN(Number(value) - parseFloat(value))) {
return Number(value);

View File

@ -75,5 +75,7 @@ export class SlicePipe implements PipeTransform {
return value.slice(start, end);
}
private supports(obj: any): boolean { return typeof obj === 'string' || Array.isArray(obj); }
private supports(obj: any): boolean {
return typeof obj === 'string' || Array.isArray(obj);
}
}

View File

@ -186,7 +186,9 @@ export class NullViewportScroller implements ViewportScroller {
/**
* Empty implementation
*/
getScrollPosition(): [number, number] { return [0, 0]; }
getScrollPosition(): [number, number] {
return [0, 0];
}
/**
* Empty implementation

View File

@ -9,12 +9,12 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {parseCookieValue} from '@angular/common/src/cookie';
import {describe, expect, it} from '@angular/core/testing/src/testing_internal';

View File

@ -7,7 +7,7 @@
*/
import {Component} from '@angular/core';
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
{
describe('binding to CSS class list', () => {
@ -18,14 +18,18 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
}
function detectChangesAndExpectClassName(classes: string): void {
fixture !.detectChanges();
let nonNormalizedClassName = fixture !.debugElement.children[0].nativeElement.className;
fixture!.detectChanges();
let nonNormalizedClassName = fixture!.debugElement.children[0].nativeElement.className;
expect(normalizeClassNames(nonNormalizedClassName)).toEqual(normalizeClassNames(classes));
}
function getComponent(): TestComponent { return fixture !.debugElement.componentInstance; }
function getComponent(): TestComponent {
return fixture!.debugElement.componentInstance;
}
afterEach(() => { fixture = null; });
afterEach(() => {
fixture = null;
});
beforeEach(() => {
TestBed.configureTestingModule({
@ -43,7 +47,6 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
}));
describe('expressions evaluating to objects', () => {
it('should add classes specified in an object literal', async(() => {
fixture = createTestComponent('<div [ngClass]="{foo: true, bar: false}"></div>');
@ -74,13 +77,13 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
detectChangesAndExpectClassName('foo');
objExpr !['bar'] = true;
objExpr!['bar'] = true;
detectChangesAndExpectClassName('foo bar');
objExpr !['baz'] = true;
objExpr!['baz'] = true;
detectChangesAndExpectClassName('foo bar baz');
delete (objExpr !['bar']);
delete (objExpr!['bar']);
detectChangesAndExpectClassName('foo baz');
}));
@ -129,7 +132,6 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
});
describe('expressions evaluating to lists', () => {
it('should add classes specified in a list literal', async(() => {
fixture =
createTestComponent(`<div [ngClass]="['foo', 'bar', 'foo-bar', 'fooBar']"></div>`);
@ -194,14 +196,13 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
it('should throw with descriptive error message when CSS class is not a string', () => {
fixture = createTestComponent(`<div [ngClass]="['foo', {}]"></div>`);
expect(() => fixture !.detectChanges())
expect(() => fixture!.detectChanges())
.toThrowError(
/NgClass can only toggle CSS classes expressed as strings, got \[object Object\]/);
});
});
describe('expressions evaluating to sets', () => {
it('should add and remove classes if the set instance changed', async(() => {
fixture = createTestComponent('<div [ngClass]="setExpr"></div>');
let setExpr = new Set<string>();
@ -217,7 +218,6 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
});
describe('expressions evaluating to string', () => {
it('should add classes specified in a string literal', async(() => {
fixture = createTestComponent(`<div [ngClass]="'foo bar foo-bar fooBar'"></div>`);
detectChangesAndExpectClassName('foo bar foo-bar fooBar');
@ -257,19 +257,17 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
getComponent().strExpr = '';
detectChangesAndExpectClassName('foo');
}));
});
describe('cooperation with other class-changing constructs', () => {
it('should co-operate with the class attribute', async(() => {
fixture = createTestComponent('<div [ngClass]="objExpr" class="init foo"></div>');
const objExpr = getComponent().objExpr;
objExpr !['bar'] = true;
objExpr!['bar'] = true;
detectChangesAndExpectClassName('init foo bar');
objExpr !['foo'] = false;
objExpr!['foo'] = false;
detectChangesAndExpectClassName('init bar');
getComponent().objExpr = null;
@ -280,10 +278,10 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
fixture = createTestComponent(`<div [ngClass]="objExpr" class="{{'init foo'}}"></div>`);
const objExpr = getComponent().objExpr;
objExpr !['bar'] = true;
objExpr!['bar'] = true;
detectChangesAndExpectClassName(`init foo bar`);
objExpr !['foo'] = false;
objExpr!['foo'] = false;
detectChangesAndExpectClassName(`init bar`);
getComponent().objExpr = null;
@ -306,10 +304,10 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
createTestComponent(`<div [ngClass]="objExpr" class="init" [class]="'foo'"></div>`);
const objExpr = getComponent().objExpr;
objExpr !['bar'] = true;
objExpr!['bar'] = true;
detectChangesAndExpectClassName(`init foo bar`);
objExpr !['foo'] = false;
objExpr!['foo'] = false;
detectChangesAndExpectClassName(`init bar`);
getComponent().objExpr = null;
@ -324,10 +322,10 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
detectChangesAndExpectClassName('init foo baz');
objExpr !['bar'] = true;
objExpr!['bar'] = true;
detectChangesAndExpectClassName('init foo baz bar');
objExpr !['foo'] = false;
objExpr!['foo'] = false;
detectChangesAndExpectClassName('init baz bar');
getComponent().condition = false;
@ -342,7 +340,7 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
detectChangesAndExpectClassName('init foo');
cmp.objExpr !['bar'] = true;
cmp.objExpr!['bar'] = true;
detectChangesAndExpectClassName('init foo bar');
cmp.strExpr = 'baz';
@ -354,7 +352,6 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
});
describe('prevent regressions', () => {
// https://github.com/angular/angular/issues/34336
it('should not write to the native node unless the bound expression has changed', () => {
fixture = createTestComponent(`<div [ngClass]="{'color-red': condition}"></div>`);
@ -392,7 +389,6 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
expect(leading.className).toBe('foo');
expect(trailing.className).toBe('foo');
});
});
});
}
@ -406,7 +402,9 @@ class TestComponent {
objExpr: {[klass: string]: any}|null = {'foo': true, 'bar': false};
strExpr: string|null = 'foo';
constructor() { this.setExpr.add('foo'); }
constructor() {
this.setExpr.add('foo');
}
}
function createTestComponent(template: string): ComponentFixture<TestComponent> {

View File

@ -8,13 +8,14 @@
import {CommonModule} from '@angular/common';
import {NgComponentOutlet} from '@angular/common/src/directives/ng_component_outlet';
import {Compiler, Component, ComponentRef, Inject, InjectionToken, Injector, NO_ERRORS_SCHEMA, NgModule, NgModuleFactory, Optional, QueryList, TemplateRef, Type, ViewChild, ViewChildren, ViewContainerRef} from '@angular/core';
import {TestBed, async} from '@angular/core/testing';
import {Compiler, Component, ComponentRef, Inject, InjectionToken, Injector, NgModule, NgModuleFactory, NO_ERRORS_SCHEMA, Optional, QueryList, TemplateRef, Type, ViewChild, ViewChildren, ViewContainerRef} from '@angular/core';
import {async, TestBed} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers';
describe('insert/remove', () => {
beforeEach(() => { TestBed.configureTestingModule({imports: [TestModule]}); });
beforeEach(() => {
TestBed.configureTestingModule({imports: [TestModule]});
});
it('should do nothing if component is null', async(() => {
const template = `<ng-template *ngComponentOutlet="currentComponent"></ng-template>`;
@ -51,7 +52,7 @@ describe('insert/remove', () => {
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('foo');
expect(fixture.componentInstance.cmpRef).toBeAnInstanceOf(ComponentRef);
expect(fixture.componentInstance.cmpRef !.instance).toBeAnInstanceOf(InjectedComponent);
expect(fixture.componentInstance.cmpRef!.instance).toBeAnInstanceOf(InjectedComponent);
}));
@ -99,11 +100,10 @@ describe('insert/remove', () => {
[{provide: TEST_TOKEN, useValue: uniqueValue}], fixture.componentRef.injector);
fixture.detectChanges();
let cmpRef: ComponentRef<InjectedComponent> = fixture.componentInstance.cmpRef !;
let cmpRef: ComponentRef<InjectedComponent> = fixture.componentInstance.cmpRef!;
expect(cmpRef).toBeAnInstanceOf(ComponentRef);
expect(cmpRef.instance).toBeAnInstanceOf(InjectedComponent);
expect(cmpRef.instance.testToken).toBe(uniqueValue);
}));
@ -114,7 +114,7 @@ describe('insert/remove', () => {
fixture.componentInstance.cmpRef = null;
fixture.componentInstance.currentComponent = InjectedComponent;
fixture.detectChanges();
let cmpRef: ComponentRef<InjectedComponent> = fixture.componentInstance.cmpRef !;
let cmpRef: ComponentRef<InjectedComponent> = fixture.componentInstance.cmpRef!;
expect(cmpRef).toBeAnInstanceOf(ComponentRef);
expect(cmpRef.instance).toBeAnInstanceOf(InjectedComponent);
expect(cmpRef.instance.testToken).toBeNull();
@ -166,7 +166,7 @@ describe('insert/remove', () => {
fixture.componentInstance.currentComponent = Module2InjectedComponent;
fixture.detectChanges();
const moduleRef = fixture.componentInstance.ngComponentOutlet['_moduleRef'] !;
const moduleRef = fixture.componentInstance.ngComponentOutlet['_moduleRef']!;
spyOn(moduleRef, 'destroy').and.callThrough();
expect(moduleRef.destroy).not.toHaveBeenCalled();
@ -224,21 +224,25 @@ const TEST_CMP_TEMPLATE =
@Component({selector: 'test-cmp', template: TEST_CMP_TEMPLATE})
class TestComponent {
// TODO(issue/24571): remove '!'.
currentComponent !: Type<any>| null;
currentComponent!: Type<any>|null;
// TODO(issue/24571): remove '!'.
injector !: Injector;
injector!: Injector;
// TODO(issue/24571): remove '!'.
projectables !: any[][];
projectables!: any[][];
// TODO(issue/24571): remove '!'.
module !: NgModuleFactory<any>;
module!: NgModuleFactory<any>;
get cmpRef(): ComponentRef<any>|null { return this.ngComponentOutlet['_componentRef']; }
set cmpRef(value: ComponentRef<any>|null) { this.ngComponentOutlet['_componentRef'] = value; }
get cmpRef(): ComponentRef<any>|null {
return this.ngComponentOutlet['_componentRef'];
}
set cmpRef(value: ComponentRef<any>|null) {
this.ngComponentOutlet['_componentRef'] = value;
}
// TODO(issue/24571): remove '!'.
@ViewChildren(TemplateRef) tplRefs !: QueryList<TemplateRef<any>>;
@ViewChildren(TemplateRef) tplRefs!: QueryList<TemplateRef<any>>;
// TODO(issue/24571): remove '!'.
@ViewChild(NgComponentOutlet, {static: true}) ngComponentOutlet !: NgComponentOutlet;
@ViewChild(NgComponentOutlet, {static: true}) ngComponentOutlet!: NgComponentOutlet;
constructor(public vcRef: ViewContainerRef) {}
}

View File

@ -8,7 +8,7 @@
import {CommonModule} from '@angular/common';
import {Component} from '@angular/core';
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {expect} from '@angular/platform-browser/testing/src/matchers';
@ -18,14 +18,18 @@ let thisArg: any;
describe('ngFor', () => {
let fixture: ComponentFixture<any>;
function getComponent(): TestComponent { return fixture.componentInstance; }
function getComponent(): TestComponent {
return fixture.componentInstance;
}
function detectChangesAndExpectText(text: string): void {
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText(text);
}
afterEach(() => { fixture = null as any; });
afterEach(() => {
fixture = null as any;
});
beforeEach(() => {
TestBed.configureTestingModule({
@ -103,7 +107,7 @@ let thisArg: any;
detectChangesAndExpectText('1;2;');
getComponent().items = null !;
getComponent().items = null!;
detectChangesAndExpectText('');
getComponent().items = [1, 2, 3];
@ -377,16 +381,24 @@ let thisArg: any;
}
class Foo {
toString() { return 'foo'; }
toString() {
return 'foo';
}
}
@Component({selector: 'test-cmp', template: ''})
class TestComponent {
value: any;
items: any[] = [1, 2];
trackById(index: number, item: any): string { return item['id']; }
trackByIndex(index: number, item: any): number { return index; }
trackByContext(): void { thisArg = this; }
trackById(index: number, item: any): string {
return item['id'];
}
trackByIndex(index: number, item: any): number {
return index;
}
trackByContext(): void {
thisArg = this;
}
}
const TEMPLATE = '<div><span *ngFor="let item of items">{{item.toString()}};</span></div>';

View File

@ -8,7 +8,7 @@
import {CommonModule, ɵgetDOM as getDOM} from '@angular/common';
import {Component} from '@angular/core';
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {expect} from '@angular/platform-browser/testing/src/matchers';
@ -16,9 +16,13 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
describe('ngIf directive', () => {
let fixture: ComponentFixture<any>;
function getComponent(): TestComponent { return fixture.componentInstance; }
function getComponent(): TestComponent {
return fixture.componentInstance;
}
afterEach(() => { fixture = null !; });
afterEach(() => {
fixture = null!;
});
beforeEach(() => {
TestBed.configureTestingModule({

View File

@ -8,21 +8,25 @@
import {CommonModule, NgLocalization} from '@angular/common';
import {Component, Injectable} from '@angular/core';
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers';
{
describe('ngPlural', () => {
let fixture: ComponentFixture<any>;
function getComponent(): TestComponent { return fixture.componentInstance; }
function getComponent(): TestComponent {
return fixture.componentInstance;
}
function detectChangesAndExpectText<T>(text: string): void {
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText(text);
}
afterEach(() => { fixture = null !; });
afterEach(() => {
fixture = null!;
});
beforeEach(() => {
TestBed.configureTestingModule({

View File

@ -8,19 +8,23 @@
import {CommonModule} from '@angular/common';
import {Component} from '@angular/core';
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
{
describe('NgStyle', () => {
let fixture: ComponentFixture<TestComponent>;
function getComponent(): TestComponent { return fixture.componentInstance; }
function getComponent(): TestComponent {
return fixture.componentInstance;
}
function expectNativeEl(fixture: ComponentFixture<any>): any {
return expect(fixture.debugElement.children[0].nativeElement);
}
afterEach(() => { fixture = null !; });
afterEach(() => {
fixture = null!;
});
beforeEach(() => {
TestBed.configureTestingModule({declarations: [TestComponent], imports: [CommonModule]});
@ -159,7 +163,6 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
}));
it('should not write to the native node unless the bound expression has changed', () => {
const template = `<div [ngStyle]="{'color': expr}"></div>`;
fixture = createTestComponent(template);
@ -189,7 +192,6 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
fixture.detectChanges();
expectNativeEl(fixture).toHaveCssStyle({'width': '400px'});
});
});
}

View File

@ -15,14 +15,18 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
describe('NgSwitch', () => {
let fixture: ComponentFixture<any>;
function getComponent(): TestComponent { return fixture.componentInstance; }
function getComponent(): TestComponent {
return fixture.componentInstance;
}
function detectChangesAndExpectText(text: string): void {
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText(text);
}
afterEach(() => { fixture = null !; });
afterEach(() => {
fixture = null!;
});
beforeEach(() => {
TestBed.configureTestingModule({
@ -118,13 +122,14 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
});
describe('corner cases', () => {
it('should not create the default case if another case matches', () => {
const log: string[] = [];
@Directive({selector: '[test]'})
class TestDirective {
constructor(@Attribute('test') test: string) { log.push(test); }
constructor(@Attribute('test') test: string) {
log.push(test);
}
}
const template = '<div [ngSwitch]="switchValue">' +
@ -149,7 +154,6 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
fixture = createTestComponent(template);
detectChangesAndExpectText('when default1;when default2;');
});
it('should allow defaults before cases', () => {
@ -223,8 +227,8 @@ class TestComponent {
`
})
class ComplexComponent {
@ViewChild('foo', {static: true}) foo !: TemplateRef<any>;
@ViewChild('bar', {static: true}) bar !: TemplateRef<any>;
@ViewChild('foo', {static: true}) foo!: TemplateRef<any>;
@ViewChild('bar', {static: true}) bar!: TemplateRef<any>;
state: string = 'case1';
}

View File

@ -8,20 +8,24 @@
import {CommonModule} from '@angular/common';
import {Component, ContentChildren, Directive, Injectable, NO_ERRORS_SCHEMA, OnDestroy, QueryList, TemplateRef} from '@angular/core';
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers';
describe('NgTemplateOutlet', () => {
let fixture: ComponentFixture<any>;
function setTplRef(value: any): void { fixture.componentInstance.currentTplRef = value; }
function setTplRef(value: any): void {
fixture.componentInstance.currentTplRef = value;
}
function detectChangesAndExpectText(text: string): void {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText(text);
}
afterEach(() => { fixture = null as any; });
afterEach(() => {
fixture = null as any;
});
beforeEach(() => {
TestBed.configureTestingModule({
@ -58,7 +62,7 @@ describe('NgTemplateOutlet', () => {
`<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`;
fixture = createTestComponent(template);
fixture.detectChanges();
const refs = fixture.debugElement.children[0].references !['refs'];
const refs = fixture.debugElement.children[0].references!['refs'];
setTplRef(refs.tplRefs.first);
detectChangesAndExpectText('foo');
@ -74,7 +78,7 @@ describe('NgTemplateOutlet', () => {
fixture = createTestComponent(template);
fixture.detectChanges();
const refs = fixture.debugElement.children[0].references !['refs'];
const refs = fixture.debugElement.children[0].references!['refs'];
setTplRef(refs.tplRefs.first);
detectChangesAndExpectText('foo');
@ -223,7 +227,7 @@ describe('NgTemplateOutlet', () => {
`<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`;
fixture = createTestComponent(template);
fixture.detectChanges();
const refs = fixture.debugElement.children[0].references !['refs'];
const refs = fixture.debugElement.children[0].references!['refs'];
setTplRef(refs.tplRefs.first);
detectChangesAndExpectText('foo');
@ -236,7 +240,6 @@ describe('NgTemplateOutlet', () => {
detectChangesAndExpectText('foo');
}).not.toThrow();
}));
});
@Injectable()
@ -248,19 +251,21 @@ class DestroyedSpyService {
class DestroyableCmpt implements OnDestroy {
constructor(private _spyService: DestroyedSpyService) {}
ngOnDestroy(): void { this._spyService.destroyed = true; }
ngOnDestroy(): void {
this._spyService.destroyed = true;
}
}
@Directive({selector: 'tpl-refs', exportAs: 'tplRefs'})
class CaptureTplRefs {
// TODO(issue/24571): remove '!'.
@ContentChildren(TemplateRef) tplRefs !: QueryList<TemplateRef<any>>;
@ContentChildren(TemplateRef) tplRefs!: QueryList<TemplateRef<any>>;
}
@Component({selector: 'test-cmp', template: ''})
class TestComponent {
// TODO(issue/24571): remove '!'.
currentTplRef !: TemplateRef<any>;
currentTplRef!: TemplateRef<any>;
context: any = {foo: 'bar'};
value = 'bar';
}

View File

@ -9,13 +9,12 @@
import {ɵgetDOM as getDOM} from '@angular/common';
import {Component, Directive} from '@angular/core';
import {ElementRef} from '@angular/core/src/linker/element_ref';
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {hasClass} from '@angular/platform-browser/testing/src/browser_util';
import {expect} from '@angular/platform-browser/testing/src/matchers';
{
describe('non-bindable', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestComponent, TestDirective],
@ -53,13 +52,17 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
@Directive({selector: '[test-dec]'})
class TestDirective {
constructor(el: ElementRef) { el.nativeElement.classList.add('compiled'); }
constructor(el: ElementRef) {
el.nativeElement.classList.add('compiled');
}
}
@Component({selector: 'test-cmp', template: ''})
class TestComponent {
text: string;
constructor() { this.text = 'foo'; }
constructor() {
this.text = 'foo';
}
}
function createTestComponent(template: string): ComponentFixture<TestComponent> {

View File

@ -12,35 +12,50 @@ import localeEnExtra from '@angular/common/locales/extra/en';
import localeHu from '@angular/common/locales/hu';
import localeSr from '@angular/common/locales/sr';
import localeTh from '@angular/common/locales/th';
import {isDate, toDate, formatDate} from '@angular/common/src/i18n/format_date';
import {ɵDEFAULT_LOCALE_ID, ɵunregisterLocaleData, ɵregisterLocaleData} from '@angular/core';
import {formatDate, isDate, toDate} from '@angular/common/src/i18n/format_date';
import {ɵDEFAULT_LOCALE_ID, ɵregisterLocaleData, ɵunregisterLocaleData} from '@angular/core';
describe('Format date', () => {
describe('toDate', () => {
it('should support date', () => { expect(isDate(toDate(new Date()))).toBeTruthy(); });
it('should support date', () => {
expect(isDate(toDate(new Date()))).toBeTruthy();
});
it('should support int', () => { expect(isDate(toDate(123456789))).toBeTruthy(); });
it('should support int', () => {
expect(isDate(toDate(123456789))).toBeTruthy();
});
it('should support numeric strings',
() => { expect(isDate(toDate('123456789'))).toBeTruthy(); });
it('should support numeric strings', () => {
expect(isDate(toDate('123456789'))).toBeTruthy();
});
it('should support decimal strings',
() => { expect(isDate(toDate('123456789.11'))).toBeTruthy(); });
it('should support decimal strings', () => {
expect(isDate(toDate('123456789.11'))).toBeTruthy();
});
it('should support ISO string',
() => { expect(isDate(toDate('2015-06-15T21:43:11Z'))).toBeTruthy(); });
it('should support ISO string', () => {
expect(isDate(toDate('2015-06-15T21:43:11Z'))).toBeTruthy();
});
it('should throw for empty string', () => { expect(() => toDate('')).toThrow(); });
it('should throw for empty string', () => {
expect(() => toDate('')).toThrow();
});
it('should throw for alpha numeric strings',
() => { expect(() => toDate('123456789 hello')).toThrow(); });
it('should throw for alpha numeric strings', () => {
expect(() => toDate('123456789 hello')).toThrow();
});
it('should throw for NaN', () => { expect(() => toDate(Number.NaN)).toThrow(); });
it('should throw for NaN', () => {
expect(() => toDate(Number.NaN)).toThrow();
});
it('should support ISO string without time',
() => { expect(isDate(toDate('2015-01-01'))).toBeTruthy(); });
it('should support ISO string without time', () => {
expect(isDate(toDate('2015-01-01'))).toBeTruthy();
});
it('should throw for objects', () => { expect(() => toDate({} as any)).toThrow(); });
it('should throw for objects', () => {
expect(() => toDate({} as any)).toThrow();
});
});
describe('formatDate', () => {
@ -49,7 +64,7 @@ describe('Format date', () => {
let date: Date;
// Check the transformation of a date into a pattern
function expectDateFormatAs(date: Date | string, pattern: any, output: string): void {
function expectDateFormatAs(date: Date|string, pattern: any, output: string): void {
expect(formatDate(date, pattern, ɵDEFAULT_LOCALE_ID))
.toEqual(output, `pattern: "${pattern}"`);
}
@ -65,7 +80,9 @@ describe('Format date', () => {
afterAll(() => ɵunregisterLocaleData());
beforeEach(() => { date = new Date(2015, 5, 15, 9, 3, 1, 550); });
beforeEach(() => {
date = new Date(2015, 5, 15, 9, 3, 1, 550);
});
it('should format each component correctly', () => {
const dateFixtures: any = {
@ -293,7 +310,7 @@ describe('Format date', () => {
});
it('should remove bidi control characters',
() => expect(formatDate(date, 'MM/dd/yyyy', ɵDEFAULT_LOCALE_ID) !.length).toEqual(10));
() => expect(formatDate(date, 'MM/dd/yyyy', ɵDEFAULT_LOCALE_ID)!.length).toEqual(10));
it(`should format the date correctly in various locales`, () => {
expect(formatDate(date, 'short', 'de')).toEqual('15.06.15, 09:03');

View File

@ -6,13 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/
import {formatCurrency, formatNumber, formatPercent} from '@angular/common';
import localeAr from '@angular/common/locales/ar';
import localeEn from '@angular/common/locales/en';
import localeEsUS from '@angular/common/locales/es-US';
import localeFr from '@angular/common/locales/fr';
import localeAr from '@angular/common/locales/ar';
import {formatCurrency, formatNumber, formatPercent} from '@angular/common';
import {ɵDEFAULT_LOCALE_ID, ɵregisterLocaleData, ɵunregisterLocaleData} from '@angular/core';
import {describe, expect, it} from '@angular/core/testing/src/testing_internal';
import {ɵDEFAULT_LOCALE_ID, ɵunregisterLocaleData, ɵregisterLocaleData} from '@angular/core';
describe('Format number', () => {
beforeAll(() => {
@ -44,8 +44,9 @@ describe('Format number', () => {
});
describe('transform with custom locales', () => {
it('should return the correct format for es-US',
() => { expect(formatNumber(9999999.99, 'es-US', '1.2-2')).toEqual('9,999,999.99'); });
it('should return the correct format for es-US', () => {
expect(formatNumber(9999999.99, 'es-US', '1.2-2')).toEqual('9,999,999.99');
});
});
});

View File

@ -6,14 +6,14 @@
* found in the LICENSE file at https://angular.io/license
*/
import localeEn from '@angular/common/locales/en';
import localeEnAU from '@angular/common/locales/en-AU';
import localeFr from '@angular/common/locales/fr';
import localeHe from '@angular/common/locales/he';
import localeZh from '@angular/common/locales/zh';
import {ɵregisterLocaleData, ɵunregisterLocaleData} from '@angular/core';
import localeEn from '@angular/common/locales/en';
import localeFr from '@angular/common/locales/fr';
import localeZh from '@angular/common/locales/zh';
import localeEnAU from '@angular/common/locales/en-AU';
import localeHe from '@angular/common/locales/he';
import {getCurrencySymbol, getLocaleDateFormat, FormatWidth, getNumberOfCurrencyDigits, getLocaleDirection} from '../../src/i18n/locale_data_api';
import {FormatWidth, getCurrencySymbol, getLocaleDateFormat, getLocaleDirection, getNumberOfCurrencyDigits} from '../../src/i18n/locale_data_api';
{
describe('locale data api', () => {
@ -25,7 +25,9 @@ import {getCurrencySymbol, getLocaleDateFormat, FormatWidth, getNumberOfCurrency
ɵregisterLocaleData(localeHe);
});
afterAll(() => { ɵunregisterLocaleData(); });
afterAll(() => {
ɵunregisterLocaleData();
});
describe('getting currency symbol', () => {
it('should return the correct symbol', () => {
@ -55,16 +57,19 @@ import {getCurrencySymbol, getLocaleDateFormat, FormatWidth, getNumberOfCurrency
});
describe('getLastDefinedValue', () => {
it('should find the last defined date format when format not defined',
() => { expect(getLocaleDateFormat('zh', FormatWidth.Long)).toEqual('y年M月d日'); });
it('should find the last defined date format when format not defined', () => {
expect(getLocaleDateFormat('zh', FormatWidth.Long)).toEqual('y年M月d日');
});
});
describe('getDirectionality', () => {
it('should have correct direction for rtl languages',
() => { expect(getLocaleDirection('he')).toEqual('rtl'); });
it('should have correct direction for rtl languages', () => {
expect(getLocaleDirection('he')).toEqual('rtl');
});
it('should have correct direction for ltr languages',
() => { expect(getLocaleDirection('en')).toEqual('ltr'); });
it('should have correct direction for ltr languages', () => {
expect(getLocaleDirection('en')).toEqual('ltr');
});
});
});
}

View File

@ -6,13 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/
import localeFr from '@angular/common/locales/fr';
import localeRo from '@angular/common/locales/ro';
import localeSr from '@angular/common/locales/sr';
import localeZgh from '@angular/common/locales/zgh';
import localeFr from '@angular/common/locales/fr';
import {LOCALE_ID, ɵunregisterLocaleData, ɵregisterLocaleData} from '@angular/core';
import {TestBed, inject} from '@angular/core/testing';
import {NgLocaleLocalization, NgLocalization, getPluralCategory} from '@angular/common/src/i18n/localization';
import {getPluralCategory, NgLocaleLocalization, NgLocalization} from '@angular/common/src/i18n/localization';
import {LOCALE_ID, ɵregisterLocaleData, ɵunregisterLocaleData} from '@angular/core';
import {inject, TestBed} from '@angular/core/testing';
{
describe('l10n', () => {

View File

@ -8,7 +8,7 @@
import {CommonModule, Location, LocationStrategy, PathLocationStrategy, PlatformLocation} from '@angular/common';
import {MockPlatformLocation} from '@angular/common/testing';
import {TestBed, inject} from '@angular/core/testing';
import {inject, TestBed} from '@angular/core/testing';
const baseUrl = '/base';
@ -46,14 +46,18 @@ describe('Location Class', () => {
imports: [CommonModule],
providers: [
{provide: LocationStrategy, useClass: PathLocationStrategy},
{provide: PlatformLocation, useFactory: () => { return new MockPlatformLocation(); }},
{
provide: PlatformLocation,
useFactory: () => {
return new MockPlatformLocation();
}
},
{provide: Location, useClass: Location, deps: [LocationStrategy, PlatformLocation]},
]
});
});
it('should get the state object', inject([Location], (location: Location) => {
expect(location.getState()).toBe(null);
location.go('/test', '', {foo: 'bar'});
@ -62,7 +66,6 @@ describe('Location Class', () => {
}));
it('should work after using back button', inject([Location], (location: Location) => {
expect(location.getState()).toBe(null);
location.go('/test1', '', {url: 'test1'});
@ -74,7 +77,6 @@ describe('Location Class', () => {
expect(location.getState()).toEqual({url: 'test1'});
}));
});
describe('location.onUrlChange()', () => {
@ -83,7 +85,12 @@ describe('Location Class', () => {
imports: [CommonModule],
providers: [
{provide: LocationStrategy, useClass: PathLocationStrategy},
{provide: PlatformLocation, useFactory: () => { return new MockPlatformLocation(); }},
{
provide: PlatformLocation,
useFactory: () => {
return new MockPlatformLocation();
}
},
{provide: Location, useClass: Location, deps: [LocationStrategy, PlatformLocation]},
]
});
@ -95,8 +102,9 @@ describe('Location Class', () => {
it('should add registered functions to urlChangeListeners',
inject([Location], (location: Location) => {
function changeListener(url: string, state: unknown) { return undefined; }
function changeListener(url: string, state: unknown) {
return undefined;
}
expect((location as any)._urlChangeListeners.length).toBe(0);
@ -104,8 +112,6 @@ describe('Location Class', () => {
expect((location as any)._urlChangeListeners.length).toBe(1);
expect((location as any)._urlChangeListeners[0]).toEqual(changeListener);
}));
});
});

View File

@ -15,7 +15,6 @@ import {SpyChangeDetectorRef} from '../spies';
{
describe('AsyncPipe', () => {
describe('Observable', () => {
let emitter: EventEmitter<any>;
let pipe: AsyncPipe;
@ -29,8 +28,9 @@ import {SpyChangeDetectorRef} from '../spies';
});
describe('transform', () => {
it('should return null when subscribing to an observable',
() => { expect(pipe.transform(emitter)).toBe(null); });
it('should return null when subscribing to an observable', () => {
expect(pipe.transform(emitter)).toBe(null);
});
it('should return the latest available value wrapped',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
@ -96,8 +96,9 @@ import {SpyChangeDetectorRef} from '../spies';
});
describe('ngOnDestroy', () => {
it('should do nothing when no subscription',
() => { expect(() => pipe.ngOnDestroy()).not.toThrow(); });
it('should do nothing when no subscription', () => {
expect(() => pipe.ngOnDestroy()).not.toThrow();
});
it('should dispose of the existing subscription',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
@ -133,8 +134,9 @@ import {SpyChangeDetectorRef} from '../spies';
});
describe('transform', () => {
it('should return null when subscribing to a promise',
() => { expect(pipe.transform(promise)).toBe(null); });
it('should return null when subscribing to a promise', () => {
expect(pipe.transform(promise)).toBe(null);
});
it('should return the latest available value',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
@ -189,8 +191,9 @@ import {SpyChangeDetectorRef} from '../spies';
}));
describe('ngOnDestroy', () => {
it('should do nothing when no source',
() => { expect(() => pipe.ngOnDestroy()).not.toThrow(); });
it('should do nothing when no source', () => {
expect(() => pipe.ngOnDestroy()).not.toThrow();
});
it('should dispose of the existing source',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {

View File

@ -12,41 +12,55 @@ import {LowerCasePipe, TitleCasePipe, UpperCasePipe} from '@angular/common';
describe('LowerCasePipe', () => {
let pipe: LowerCasePipe;
beforeEach(() => { pipe = new LowerCasePipe(); });
beforeEach(() => {
pipe = new LowerCasePipe();
});
it('should return lowercase', () => { expect(pipe.transform('FOO')).toEqual('foo'); });
it('should return lowercase', () => {
expect(pipe.transform('FOO')).toEqual('foo');
});
it('should lowercase when there is a new value', () => {
expect(pipe.transform('FOO')).toEqual('foo');
expect(pipe.transform('BAr')).toEqual('bar');
});
it('should not support other objects',
() => { expect(() => pipe.transform(<any>{})).toThrowError(); });
it('should not support other objects', () => {
expect(() => pipe.transform(<any>{})).toThrowError();
});
});
describe('TitleCasePipe', () => {
let pipe: TitleCasePipe;
beforeEach(() => { pipe = new TitleCasePipe(); });
beforeEach(() => {
pipe = new TitleCasePipe();
});
it('should return titlecase', () => { expect(pipe.transform('foo')).toEqual('Foo'); });
it('should return titlecase', () => {
expect(pipe.transform('foo')).toEqual('Foo');
});
it('should return titlecase for subsequent words',
() => { expect(pipe.transform('one TWO Three fouR')).toEqual('One Two Three Four'); });
it('should return titlecase for subsequent words', () => {
expect(pipe.transform('one TWO Three fouR')).toEqual('One Two Three Four');
});
it('should support empty strings', () => { expect(pipe.transform('')).toEqual(''); });
it('should support empty strings', () => {
expect(pipe.transform('')).toEqual('');
});
it('should persist whitespace',
() => { expect(pipe.transform('one two')).toEqual('One Two'); });
it('should persist whitespace', () => {
expect(pipe.transform('one two')).toEqual('One Two');
});
it('should titlecase when there is a new value', () => {
expect(pipe.transform('bar')).toEqual('Bar');
expect(pipe.transform('foo')).toEqual('Foo');
});
it('should not capitalize letter after the quotes',
() => { expect(pipe.transform('it\'s complicated')).toEqual('It\'s Complicated'); });
it('should not capitalize letter after the quotes', () => {
expect(pipe.transform('it\'s complicated')).toEqual('It\'s Complicated');
});
it('should not treat non-space character as a separator', () => {
expect(pipe.transform('one,two,three')).toEqual('One,two,three');
@ -66,23 +80,29 @@ import {LowerCasePipe, TitleCasePipe, UpperCasePipe} from '@angular/common';
expect(pipe.transform('éric')).toEqual('Éric');
});
it('should not support other objects',
() => { expect(() => pipe.transform(<any>{})).toThrowError(); });
it('should not support other objects', () => {
expect(() => pipe.transform(<any>{})).toThrowError();
});
});
describe('UpperCasePipe', () => {
let pipe: UpperCasePipe;
beforeEach(() => { pipe = new UpperCasePipe(); });
beforeEach(() => {
pipe = new UpperCasePipe();
});
it('should return uppercase', () => { expect(pipe.transform('foo')).toEqual('FOO'); });
it('should return uppercase', () => {
expect(pipe.transform('foo')).toEqual('FOO');
});
it('should uppercase when there is a new value', () => {
expect(pipe.transform('foo')).toEqual('FOO');
expect(pipe.transform('bar')).toEqual('BAR');
});
it('should not support other objects',
() => { expect(() => pipe.transform(<any>{})).toThrowError(); });
it('should not support other objects', () => {
expect(() => pipe.transform(<any>{})).toThrowError();
});
});
}

View File

@ -10,8 +10,8 @@ import {DatePipe} from '@angular/common';
import localeEn from '@angular/common/locales/en';
import localeEnExtra from '@angular/common/locales/extra/en';
import {PipeResolver} from '@angular/compiler/src/pipe_resolver';
import {ɵregisterLocaleData, ɵunregisterLocaleData} from '@angular/core';
import {JitReflector} from '@angular/platform-browser-dynamic/src/compiler_reflector';
import {ɵunregisterLocaleData, ɵregisterLocaleData} from '@angular/core';
{
let date: Date;
@ -28,33 +28,44 @@ import {ɵunregisterLocaleData, ɵregisterLocaleData} from '@angular/core';
});
it('should be marked as pure', () => {
expect(new PipeResolver(new JitReflector()).resolve(DatePipe) !.pure).toEqual(true);
expect(new PipeResolver(new JitReflector()).resolve(DatePipe)!.pure).toEqual(true);
});
describe('supports', () => {
it('should support date', () => { expect(() => pipe.transform(date)).not.toThrow(); });
it('should support date', () => {
expect(() => pipe.transform(date)).not.toThrow();
});
it('should support int', () => { expect(() => pipe.transform(123456789)).not.toThrow(); });
it('should support int', () => {
expect(() => pipe.transform(123456789)).not.toThrow();
});
it('should support numeric strings',
() => { expect(() => pipe.transform('123456789')).not.toThrow(); });
it('should support numeric strings', () => {
expect(() => pipe.transform('123456789')).not.toThrow();
});
it('should support decimal strings',
() => { expect(() => pipe.transform('123456789.11')).not.toThrow(); });
it('should support decimal strings', () => {
expect(() => pipe.transform('123456789.11')).not.toThrow();
});
it('should support ISO string',
() => expect(() => pipe.transform('2015-06-15T21:43:11Z')).not.toThrow());
it('should return null for empty string',
() => { expect(pipe.transform('')).toEqual(null); });
it('should return null for empty string', () => {
expect(pipe.transform('')).toEqual(null);
});
it('should return null for NaN', () => { expect(pipe.transform(Number.NaN)).toEqual(null); });
it('should return null for NaN', () => {
expect(pipe.transform(Number.NaN)).toEqual(null);
});
it('should support ISO string without time',
() => { expect(() => pipe.transform(isoStringWithoutTime)).not.toThrow(); });
it('should support ISO string without time', () => {
expect(() => pipe.transform(isoStringWithoutTime)).not.toThrow();
});
it('should not support other objects',
() => { expect(() => pipe.transform({})).toThrowError(/InvalidPipeArgument/); });
it('should not support other objects', () => {
expect(() => pipe.transform({})).toThrowError(/InvalidPipeArgument/);
});
});
describe('transform', () => {

View File

@ -29,7 +29,7 @@ import {JitReflector} from '@angular/platform-browser-dynamic/src/compiler_refle
});
it('should be marked as pure', () => {
expect(new PipeResolver(new JitReflector()).resolve(I18nPluralPipe) !.pure).toEqual(true);
expect(new PipeResolver(new JitReflector()).resolve(I18nPluralPipe)!.pure).toEqual(true);
});
describe('transform', () => {
@ -54,17 +54,19 @@ import {JitReflector} from '@angular/platform-browser-dynamic/src/compiler_refle
});
it('should use "" if value is undefined', () => {
const val = pipe.transform(void(0) as any, mapping);
const val = pipe.transform(void (0) as any, mapping);
expect(val).toEqual('');
});
it('should not support bad arguments',
() => { expect(() => pipe.transform(0, <any>'hey')).toThrowError(); });
it('should not support bad arguments', () => {
expect(() => pipe.transform(0, <any>'hey')).toThrowError();
});
});
});
}
class TestLocalization extends NgLocalization {
getPluralCategory(value: number): string { return value > 1 && value < 6 ? 'many' : 'other'; }
getPluralCategory(value: number): string {
return value > 1 && value < 6 ? 'many' : 'other';
}
}

View File

@ -16,7 +16,7 @@ import {JitReflector} from '@angular/platform-browser-dynamic/src/compiler_refle
const mapping = {'male': 'Invite him.', 'female': 'Invite her.', 'other': 'Invite them.'};
it('should be marked as pure', () => {
expect(new PipeResolver(new JitReflector()).resolve(I18nSelectPipe) !.pure).toEqual(true);
expect(new PipeResolver(new JitReflector()).resolve(I18nSelectPipe)!.pure).toEqual(true);
});
describe('transform', () => {
@ -30,17 +30,18 @@ import {JitReflector} from '@angular/platform-browser-dynamic/src/compiler_refle
expect(val).toEqual('Invite her.');
});
it('should return the "other" text if value is neither "male" nor "female"',
() => { expect(pipe.transform('Anything else', mapping)).toEqual('Invite them.'); });
it('should return the "other" text if value is neither "male" nor "female"', () => {
expect(pipe.transform('Anything else', mapping)).toEqual('Invite them.');
});
it('should return an empty text if value is null or undefined', () => {
expect(pipe.transform(null, mapping)).toEqual('');
expect(pipe.transform(void 0, mapping)).toEqual('');
});
it('should throw on bad arguments',
() => { expect(() => pipe.transform('male', <any>'hey')).toThrowError(); });
it('should throw on bad arguments', () => {
expect(() => pipe.transform('male', <any>'hey')).toThrowError();
});
});
});
}

View File

@ -8,7 +8,7 @@
import {CommonModule, JsonPipe} from '@angular/common';
import {Component} from '@angular/core';
import {TestBed, async} from '@angular/core/testing';
import {async, TestBed} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers';
{
@ -18,7 +18,9 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
let inceptionObjString: string;
let pipe: JsonPipe;
function normalize(obj: string): string { return obj.replace(regNewLine, ''); }
function normalize(obj: string): string {
return obj.replace(regNewLine, '');
}
beforeEach(() => {
inceptionObj = {dream: {dream: {dream: 'Limbo'}}};
@ -35,8 +37,9 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
});
describe('transform', () => {
it('should return JSON-formatted string',
() => { expect(pipe.transform(inceptionObj)).toEqual(inceptionObjString); });
it('should return JSON-formatted string', () => {
expect(pipe.transform(inceptionObj)).toEqual(inceptionObjString);
});
it('should return JSON-formatted string even when normalized', () => {
const dream1 = normalize(pipe.transform(inceptionObj));
@ -52,7 +55,6 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
});
describe('integration', () => {
@Component({selector: 'test-comp', template: '{{data | json}}'})
class TestComp {
data: any;

View File

@ -64,12 +64,12 @@ describe('KeyValuePipe', () => {
expect(transform1 !== transform2).toEqual(true);
});
it('should accept a type union of an object with string keys and null', () => {
let value !: {[key: string]: string} | null;
let value!: {[key: string]: string}|null;
const pipe = new KeyValuePipe(defaultKeyValueDiffers);
expect(pipe.transform(value)).toEqual(null);
});
it('should accept a type union of an object with number keys and null', () => {
let value !: {[key: number]: string} | null;
let value!: {[key: number]: string}|null;
const pipe = new KeyValuePipe(defaultKeyValueDiffers);
expect(pipe.transform(value)).toEqual(null);
});
@ -126,7 +126,7 @@ describe('KeyValuePipe', () => {
expect(transform1 !== transform2).toEqual(true);
});
it('should accept a type union of a Map and null', () => {
let value !: Map<number, number>| null;
let value!: Map<number, number>|null;
const pipe = new KeyValuePipe(defaultKeyValueDiffers);
expect(pipe.transform(value)).toEqual(null);
});

View File

@ -6,14 +6,14 @@
* found in the LICENSE file at https://angular.io/license
*/
import {CurrencyPipe, DecimalPipe, PercentPipe} from '@angular/common';
import localeAr from '@angular/common/locales/ar';
import localeDa from '@angular/common/locales/da';
import localeDeAt from '@angular/common/locales/de-AT';
import localeEn from '@angular/common/locales/en';
import localeEsUS from '@angular/common/locales/es-US';
import localeFr from '@angular/common/locales/fr';
import localeAr from '@angular/common/locales/ar';
import localeDeAt from '@angular/common/locales/de-AT';
import localeDa from '@angular/common/locales/da';
import {ɵunregisterLocaleData, ɵregisterLocaleData} from '@angular/core';
import {CurrencyPipe, DecimalPipe, PercentPipe} from '@angular/common';
import {ɵregisterLocaleData, ɵunregisterLocaleData} from '@angular/core';
import {beforeEach, describe, expect, it} from '@angular/core/testing/src/testing_internal';
{
@ -32,7 +32,9 @@ import {beforeEach, describe, expect, it} from '@angular/core/testing/src/testin
describe('DecimalPipe', () => {
describe('transform', () => {
let pipe: DecimalPipe;
beforeEach(() => { pipe = new DecimalPipe('en-US'); });
beforeEach(() => {
pipe = new DecimalPipe('en-US');
});
it('should return correct value for numbers', () => {
expect(pipe.transform(12345)).toEqual('12,345');
@ -68,7 +70,9 @@ import {beforeEach, describe, expect, it} from '@angular/core/testing/src/testin
describe('PercentPipe', () => {
let pipe: PercentPipe;
beforeEach(() => { pipe = new PercentPipe('en-US'); });
beforeEach(() => {
pipe = new PercentPipe('en-US');
});
describe('transform', () => {
it('should return correct value for numbers', () => {
@ -89,7 +93,9 @@ import {beforeEach, describe, expect, it} from '@angular/core/testing/src/testin
describe('CurrencyPipe', () => {
let pipe: CurrencyPipe;
beforeEach(() => { pipe = new CurrencyPipe('en-US', 'USD'); });
beforeEach(() => {
pipe = new CurrencyPipe('en-US', 'USD');
});
describe('transform', () => {
it('should return correct value for numbers', () => {

View File

@ -8,7 +8,7 @@
import {CommonModule, SlicePipe} from '@angular/common';
import {Component} from '@angular/core';
import {TestBed, async} from '@angular/core/testing';
import {async, TestBed} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers';
{
@ -24,24 +24,32 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
});
describe('supports', () => {
it('should support strings', () => { expect(() => pipe.transform(str, 0)).not.toThrow(); });
it('should support lists', () => { expect(() => pipe.transform(list, 0)).not.toThrow(); });
it('should support readonly lists',
() => { expect(() => pipe.transform(list as ReadonlyArray<number>, 0)).not.toThrow(); });
it('should support strings', () => {
expect(() => pipe.transform(str, 0)).not.toThrow();
});
it('should support lists', () => {
expect(() => pipe.transform(list, 0)).not.toThrow();
});
it('should support readonly lists', () => {
expect(() => pipe.transform(list as ReadonlyArray<number>, 0)).not.toThrow();
});
it('should not support other objects',
// this would not compile
// so we cast as `any` to check that it throws for unsupported objects
() => { expect(() => pipe.transform({} as any, 0)).toThrow(); });
() => {
expect(() => pipe.transform({} as any, 0)).toThrow();
});
});
describe('transform', () => {
it('should return null if the value is null', () => {
expect(pipe.transform(null, 1)).toBe(null);
});
it('should return null if the value is null',
() => { expect(pipe.transform(null, 1)).toBe(null); });
it('should return undefined if the value is undefined',
() => { expect(pipe.transform(undefined, 1)).toBe(undefined); });
it('should return undefined if the value is undefined', () => {
expect(pipe.transform(undefined, 1)).toBe(undefined);
});
it('should return all items after START index when START is positive and END is omitted',
() => {
@ -85,11 +93,9 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
expect(pipe.transform(list, 2)).toEqual([3, 4, 5]);
expect(list).toEqual([1, 2, 3, 4, 5]);
});
});
describe('integration', () => {
@Component({selector: 'test-comp', template: '{{(data | slice:1).join(",") }}'})
class TestComp {
data: any;

View File

@ -18,4 +18,6 @@ export class SpyChangeDetectorRef extends SpyObject {
export class SpyNgControl extends SpyObject {}
export class SpyValueAccessor extends SpyObject { writeValue: any; }
export class SpyValueAccessor extends SpyObject {
writeValue: any;
}

View File

@ -9,12 +9,12 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {describe, expect, it} from '@angular/core/testing/src/testing_internal';
import {BrowserViewportScroller, ViewportScroller} from '../src/viewport_scroller';
@ -25,7 +25,7 @@ import {BrowserViewportScroller, ViewportScroller} from '../src/viewport_scrolle
let documentSpy: any;
beforeEach(() => {
documentSpy = jasmine.createSpyObj('document', ['querySelector']);
scroller = new BrowserViewportScroller(documentSpy, {scrollTo: 1}, null !);
scroller = new BrowserViewportScroller(documentSpy, {scrollTo: 1}, null!);
});
it('escapes invalid characters selectors', () => {
const invalidSelectorChars = `"' :.[],=`;

View File

@ -25,19 +25,27 @@ export class SpyLocation implements Location {
/** @internal */
_baseHref: string = '';
/** @internal */
_platformStrategy: LocationStrategy = null !;
_platformStrategy: LocationStrategy = null!;
/** @internal */
_platformLocation: PlatformLocation = null !;
_platformLocation: PlatformLocation = null!;
/** @internal */
_urlChangeListeners: ((url: string, state: unknown) => void)[] = [];
setInitialPath(url: string) { this._history[this._historyIndex].path = url; }
setInitialPath(url: string) {
this._history[this._historyIndex].path = url;
}
setBaseHref(url: string) { this._baseHref = url; }
setBaseHref(url: string) {
this._baseHref = url;
}
path(): string { return this._history[this._historyIndex].path; }
path(): string {
return this._history[this._historyIndex].path;
}
getState(): unknown { return this._history[this._historyIndex].state; }
getState(): unknown {
return this._history[this._historyIndex].state;
}
isCurrentPathEqualTo(path: string, query: string = ''): boolean {
const givenPath = path.endsWith('/') ? path.substring(0, path.length - 1) : path;
@ -115,7 +123,9 @@ export class SpyLocation implements Location {
}
onUrlChange(fn: (url: string, state: unknown) => void) {
this._urlChangeListeners.push(fn);
this.subscribe(v => { this._notifyUrlChangeListeners(v.url, v.state); });
this.subscribe(v => {
this._notifyUrlChangeListeners(v.url, v.state);
});
}
/** @internal */
@ -129,7 +139,9 @@ export class SpyLocation implements Location {
return this._subject.subscribe({next: onNext, error: onThrow, complete: onReturn});
}
normalize(url: string): string { return null !; }
normalize(url: string): string {
return null!;
}
}
class LocationState {

View File

@ -26,14 +26,18 @@ export class MockLocationStrategy extends LocationStrategy {
/** @internal */
_subject: EventEmitter<any> = new EventEmitter();
private stateChanges: any[] = [];
constructor() { super(); }
constructor() {
super();
}
simulatePopState(url: string): void {
this.internalPath = url;
this._subject.emit(new _MockPopStateEvent(this.path()));
}
path(includeHash: boolean = false): string { return this.internalPath; }
path(includeHash: boolean = false): string {
return this.internalPath;
}
prepareExternalUrl(internal: string): string {
if (internal.startsWith('/') && this.internalBaseHref.endsWith('/')) {
@ -68,9 +72,13 @@ export class MockLocationStrategy extends LocationStrategy {
this.urlChanges.push('replace: ' + externalUrl);
}
onPopState(fn: (value: any) => void): void { this._subject.subscribe({next: fn}); }
onPopState(fn: (value: any) => void): void {
this._subject.subscribe({next: fn});
}
getBaseHref(): string { return this.internalBaseHref; }
getBaseHref(): string {
return this.internalBaseHref;
}
back(): void {
if (this.urlChanges.length > 0) {
@ -81,9 +89,13 @@ export class MockLocationStrategy extends LocationStrategy {
}
}
forward(): void { throw 'not implemented'; }
forward(): void {
throw 'not implemented';
}
getState(): unknown { return this.stateChanges[(this.stateChanges.length || 1) - 1]; }
getState(): unknown {
return this.stateChanges[(this.stateChanges.length || 1) - 1];
}
}
class _MockPopStateEvent {

View File

@ -126,23 +126,41 @@ export class MockPlatformLocation implements PlatformLocation {
}
}
get hostname() { return this.urlChanges[0].hostname; }
get protocol() { return this.urlChanges[0].protocol; }
get port() { return this.urlChanges[0].port; }
get pathname() { return this.urlChanges[0].pathname; }
get search() { return this.urlChanges[0].search; }
get hash() { return this.urlChanges[0].hash; }
get state() { return this.urlChanges[0].state; }
get hostname() {
return this.urlChanges[0].hostname;
}
get protocol() {
return this.urlChanges[0].protocol;
}
get port() {
return this.urlChanges[0].port;
}
get pathname() {
return this.urlChanges[0].pathname;
}
get search() {
return this.urlChanges[0].search;
}
get hash() {
return this.urlChanges[0].hash;
}
get state() {
return this.urlChanges[0].state;
}
getBaseHrefFromDOM(): string { return this.baseHref; }
getBaseHrefFromDOM(): string {
return this.baseHref;
}
onPopState(fn: LocationChangeListener): void {
// No-op: a state stack is not implemented, so
// no events will ever come.
}
onHashChange(fn: LocationChangeListener): void { this.hashUpdate.subscribe(fn); }
onHashChange(fn: LocationChangeListener): void {
this.hashUpdate.subscribe(fn);
}
get href(): string {
let url = `${this.protocol}//${this.hostname}${this.port ? ':' + this.port : ''}`;
@ -150,7 +168,9 @@ export class MockPlatformLocation implements PlatformLocation {
return url;
}
get url(): string { return `${this.pathname}${this.search}${this.hash}`; }
get url(): string {
return `${this.pathname}${this.search}${this.hash}`;
}
private parseChanges(state: unknown, url: string, baseHref: string = '') {
// When the `history.state` value is stored, it is always copied.
@ -169,7 +189,9 @@ export class MockPlatformLocation implements PlatformLocation {
this.urlChanges.unshift({...this.urlChanges[0], pathname, search, hash, state: parsedState});
}
forward(): void { throw new Error('Not implemented'); }
forward(): void {
throw new Error('Not implemented');
}
back(): void {
const oldUrl = this.url;
@ -178,13 +200,15 @@ export class MockPlatformLocation implements PlatformLocation {
const newHash = this.hash;
if (oldHash !== newHash) {
scheduleMicroTask(() => this.hashUpdate.next({
type: 'hashchange', state: null, oldUrl, newUrl: this.url
} as LocationChangeEvent));
scheduleMicroTask(
() => this.hashUpdate.next(
{type: 'hashchange', state: null, oldUrl, newUrl: this.url} as LocationChangeEvent));
}
}
getState(): unknown { return this.state; }
getState(): unknown {
return this.state;
}
}
export function scheduleMicroTask(cb: () => any) {

View File

@ -55,7 +55,7 @@ const APP_BASE_HREF_RESOLVED = new InjectionToken<string>('APP_BASE_HREF_RESOLVE
/**
* `NgModule` used for providing and configuring Angular's Unified Location Service for upgrading.
*
*
* @see [Using the Unified Angular Location Service](guide/upgrade#using-the-unified-angular-location-service)
*
* @publicApi

View File

@ -152,7 +152,9 @@ export class AngularJSUrlCodec implements UrlCodec {
}
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L72
decodeSearch(search: string) { return parseKeyValue(search); }
decodeSearch(search: string) {
return parseKeyValue(search);
}
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L73
decodeHash(hash: string) {
@ -193,7 +195,9 @@ export class AngularJSUrlCodec implements UrlCodec {
}
}
areEqual(valA: string, valB: string) { return this.normalize(valA) === this.normalize(valB); }
areEqual(valA: string, valB: string) {
return this.normalize(valA) === this.normalize(valB);
}
// https://github.com/angular/angular.js/blob/864c7f0/src/ng/urlUtils.js#L60
parse(url: string, base?: string) {

View File

@ -27,7 +27,7 @@ export function deepEqual(a: any, b: any): boolean {
}
}
export function isAnchor(el: (Node & ParentNode) | Element | null): el is HTMLAnchorElement {
export function isAnchor(el: (Node&ParentNode)|Element|null): el is HTMLAnchorElement {
return (<HTMLAnchorElement>el).href !== undefined;
}

View File

@ -7,7 +7,7 @@
*/
import {CommonModule, PathLocationStrategy} from '@angular/common';
import {TestBed, inject} from '@angular/core/testing';
import {inject, TestBed} from '@angular/core/testing';
import {UpgradeModule} from '@angular/upgrade/static';
import {$locationShim} from '../src/location_shim';
@ -43,15 +43,26 @@ export function injectorFactory() {
export class $rootScopeMock {
private watchers: any[] = [];
private events: {[k: string]: any[]} = {};
runWatchers() { this.watchers.forEach(fn => fn()); }
runWatchers() {
this.watchers.forEach(fn => fn());
}
$watch(fn: any) { this.watchers.push(fn); }
$watch(fn: any) {
this.watchers.push(fn);
}
$broadcast(evt: string, ...args: any[]) {
if (this.events[evt]) {
this.events[evt].forEach(fn => { fn.apply(fn, args); });
this.events[evt].forEach(fn => {
fn.apply(fn, args);
});
}
return {defaultPrevented: false, preventDefault() { this.defaultPrevented = true; }};
return {
defaultPrevented: false,
preventDefault() {
this.defaultPrevented = true;
}
};
}
$on(evt: string, fn: any) {
@ -61,7 +72,9 @@ export class $rootScopeMock {
this.events[evt].push(fn);
}
$evalAsync(fn: any) { fn(); }
$evalAsync(fn: any) {
fn();
}
}
describe('LocationProvider', () => {
@ -83,7 +96,6 @@ describe('LocationProvider', () => {
expect($location).toBeDefined();
expect($location instanceof $locationShim).toBe(true);
}));
});
@ -105,7 +117,9 @@ describe('LocationHtml5Url', function() {
upgradeModule.$injector = {get: injectorFactory()};
});
beforeEach(inject([$locationShim], (loc: $locationShim) => { $location = loc; }));
beforeEach(inject([$locationShim], (loc: $locationShim) => {
$location = loc;
}));
it('should set the URL', () => {
@ -158,8 +172,9 @@ describe('LocationHtml5Url', function() {
}).toThrow();
});
it('should support state',
function() { expect($location.state({a: 2}).state()).toEqual({a: 2}); });
it('should support state', function() {
expect($location.state({a: 2}).state()).toEqual({a: 2});
});
});
@ -180,10 +195,14 @@ describe('NewUrl', function() {
upgradeModule.$injector = {get: injectorFactory()};
});
beforeEach(inject([$locationShim], (loc: $locationShim) => { $location = loc; }));
beforeEach(inject([$locationShim], (loc: $locationShim) => {
$location = loc;
}));
// Sets the default most of these tests rely on
function setupUrl(url = '/path/b?search=a&b=c&d#hash') { $location.url(url); }
function setupUrl(url = '/path/b?search=a&b=c&d#hash') {
$location.url(url);
}
it('should provide common getters', function() {
setupUrl();
@ -409,7 +428,6 @@ describe('NewUrl', function() {
});
describe('encoding', function() {
it('should encode special characters', function() {
$location.path('/a <>#');
$location.search({'i j': '<>#'});
@ -455,7 +473,6 @@ describe('NewUrl', function() {
$location.search({'a+b': 'c+d'});
expect($location.search()).toEqual({'a+b': 'c+d'});
});
});
it('should not preserve old properties when parsing new url', function() {
@ -486,7 +503,9 @@ describe('New URL Parsing', () => {
upgradeModule.$injector = {get: injectorFactory()};
});
beforeEach(inject([$locationShim], (loc: $locationShim) => { $location = loc; }));
beforeEach(inject([$locationShim], (loc: $locationShim) => {
$location = loc;
}));
it('should prepend path with basePath', function() {
$location.$$parse('http://server/base/abc?a');
@ -496,7 +515,6 @@ describe('New URL Parsing', () => {
$location.path('/new/path');
expect($location.absUrl()).toBe('http://server/base/new/path?a');
});
});
describe('New URL Parsing', () => {
@ -516,7 +534,9 @@ describe('New URL Parsing', () => {
upgradeModule.$injector = {get: injectorFactory()};
});
beforeEach(inject([$locationShim], (loc: $locationShim) => { $location = loc; }));
beforeEach(inject([$locationShim], (loc: $locationShim) => {
$location = loc;
}));
it('should parse new url', function() {
$location.$$parse('http://host.com/base');
@ -549,8 +569,9 @@ describe('New URL Parsing', () => {
});
it('should throw error when invalid server url given', function() {
expect(function() { $location.$$parse('http://other.server.org/path#/path'); })
expect(function() {
$location.$$parse('http://other.server.org/path#/path');
})
.toThrowError(
'Invalid url "http://other.server.org/path#/path", missing path prefix "http://host.com/".');
});
@ -620,12 +641,10 @@ describe('New URL Parsing', () => {
// After watchers have been run, location should be updated and `state` should change
expect($location.state()).toBe(null);
});
});
});
describe('$location.onChange()', () => {
let $location: $locationShim;
let upgradeModule: UpgradeModule;
let mock$rootScope: $rootScopeMock;
@ -644,13 +663,18 @@ describe('$location.onChange()', () => {
mock$rootScope = upgradeModule.$injector.get('$rootScope');
});
beforeEach(inject([$locationShim], (loc: $locationShim) => { $location = loc; }));
beforeEach(inject([$locationShim], (loc: $locationShim) => {
$location = loc;
}));
it('should have onChange method', () => { expect(typeof $location.onChange).toBe('function'); });
it('should have onChange method', () => {
expect(typeof $location.onChange).toBe('function');
});
it('should add registered functions to changeListeners', () => {
function changeListener(url: string, state: unknown) { return undefined; }
function changeListener(url: string, state: unknown) {
return undefined;
}
function errorHandler(e: Error) {}
expect(($location as any).$$changeListeners.length).toBe(0);
@ -663,7 +687,6 @@ describe('$location.onChange()', () => {
});
it('should call changeListeners when URL is updated', () => {
const onChangeVals =
{url: 'url', state: 'state' as unknown, oldUrl: 'oldUrl', oldState: 'oldState' as unknown};
@ -688,7 +711,6 @@ describe('$location.onChange()', () => {
});
it('should call changeListeners after $locationChangeSuccess', () => {
let changeListenerCalled = false;
let locationChangeSuccessEmitted = false;
@ -715,13 +737,14 @@ describe('$location.onChange()', () => {
});
it('should call forward errors to error handler', () => {
let error !: Error;
let error!: Error;
function changeListener(url: string, state: unknown, oldUrl: string, oldState: unknown) {
throw new Error('Handle error');
}
function errorHandler(e: Error) { error = e; }
function errorHandler(e: Error) {
error = e;
}
$location.onChange(changeListener, errorHandler);
@ -729,7 +752,6 @@ describe('$location.onChange()', () => {
mock$rootScope.runWatchers();
expect(error.message).toBe('Handle error');
});
});
function parseLinkAndReturn(location: $locationShim, toUrl: string, relHref?: string) {

View File

@ -72,7 +72,7 @@ export class LocationUpgradeTestModule {
appBaseHref: config && config.appBaseHref,
useHash: config && config.useHash || false
})
.providers !
.providers!
],
};
}