| 
									
										
										
										
											2020-07-20 22:06:09 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google LLC 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
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-25 15:01:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 22:06:09 -07:00
										 |  |  | /** Template string function that can be used to strip indentation from a given string literal. */ | 
					
						
							|  |  |  | export function dedent(strings: TemplateStringsArray, ...values: any[]) { | 
					
						
							|  |  |  |   let joinedString = ''; | 
					
						
							|  |  |  |   for (let i = 0; i < values.length; i++) { | 
					
						
							|  |  |  |     joinedString += `${strings[i]}${values[i]}`; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   joinedString += strings[strings.length - 1]; | 
					
						
							|  |  |  |   const lines = joinedString.split('\n'); | 
					
						
							|  |  |  |   while (isBlank(lines[0])) { | 
					
						
							|  |  |  |     lines.shift(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   while (isBlank(lines[lines.length - 1])) { | 
					
						
							|  |  |  |     lines.pop(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   let minWhitespacePrefix = lines.reduce( | 
					
						
							|  |  |  |       (min, line) => Math.min(min, numOfWhiteSpaceLeadingChars(line)), Number.MAX_SAFE_INTEGER); | 
					
						
							|  |  |  |   return lines.map((line) => line.substring(minWhitespacePrefix)).join('\n'); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Tests to see if the line is blank. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * A blank line is such which contains only whitespace. | 
					
						
							|  |  |  |  * @param text string to test for blank-ness. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function isBlank(text: string): boolean { | 
					
						
							|  |  |  |   return /^\s*$/.test(text); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Returns number of whitespace leading characters. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param text | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function numOfWhiteSpaceLeadingChars(text: string): number { | 
					
						
							|  |  |  |   return text.match(/^\s*/)![0].length; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Jasmine AsymmetricMatcher which can be used to assert `.debug` properties. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * expect(obj).toEqual({ | 
					
						
							| 
									
										
										
										
											2020-10-12 22:09:57 -07:00
										 |  |  |  *   create: matchDebug('someValue') | 
					
						
							| 
									
										
										
										
											2020-07-20 22:06:09 -07:00
										 |  |  |  * }) | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * In the above example it will assert that `obj.create.debug === 'someValue'`. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param expected Expected value. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-10-12 22:09:57 -07:00
										 |  |  | export function matchDebug<T>(expected: T): any { | 
					
						
							| 
									
										
										
										
											2020-07-20 22:06:09 -07:00
										 |  |  |   const matcher = function() {}; | 
					
						
							| 
									
										
										
										
											2020-10-12 22:09:57 -07:00
										 |  |  |   let actual: any = matchDebug; | 
					
						
							| 
									
										
										
										
											2020-07-20 22:06:09 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   matcher.asymmetricMatch = function(objectWithDebug: any) { | 
					
						
							|  |  |  |     return jasmine.matchersUtil.equals(actual = objectWithDebug.debug, expected); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   matcher.jasmineToString = function() { | 
					
						
							| 
									
										
										
										
											2020-10-12 22:09:57 -07:00
										 |  |  |     if (actual === matchDebug) { | 
					
						
							| 
									
										
										
										
											2020-09-25 15:01:56 -07:00
										 |  |  |       // `asymmetricMatch` never got called hence no error to display
 | 
					
						
							|  |  |  |       return ''; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return buildFailureMessage(actual, expected); | 
					
						
							| 
									
										
										
										
											2020-07-20 22:06:09 -07:00
										 |  |  |   }; | 
					
						
							|  |  |  |   return matcher; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-09-25 15:01:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | export function buildFailureMessage(actual: any, expected: any): string { | 
					
						
							|  |  |  |   const diffs: string[] = []; | 
					
						
							|  |  |  |   listPropertyDifferences(diffs, '', actual, expected, 5); | 
					
						
							|  |  |  |   return '\n  ' + diffs.join('\n  '); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function listPropertyDifferences( | 
					
						
							|  |  |  |     diffs: string[], path: string, actual: any, expected: any, depth: number) { | 
					
						
							|  |  |  |   if (actual === expected) return; | 
					
						
							|  |  |  |   if (typeof actual !== typeof expected) { | 
					
						
							|  |  |  |     diffs.push(`${path}: Expected ${jasmine.pp(actual)} to be ${jasmine.pp(expected)}`); | 
					
						
							|  |  |  |   } else if (depth && Array.isArray(expected)) { | 
					
						
							|  |  |  |     if (!Array.isArray(actual)) { | 
					
						
							|  |  |  |       diffs.push(`${path}: Expected ${jasmine.pp(expected)} but was ${jasmine.pp(actual)}`); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       const maxLength = Math.max(actual.length, expected.length); | 
					
						
							|  |  |  |       listPropertyDifferences(diffs, path + '.length', expected.length, actual.length, depth - 1); | 
					
						
							|  |  |  |       for (let i = 0; i < maxLength; i++) { | 
					
						
							|  |  |  |         const actualItem = actual[i]; | 
					
						
							|  |  |  |         const expectedItem = expected[i]; | 
					
						
							|  |  |  |         listPropertyDifferences(diffs, path + '[' + i + ']', actualItem, expectedItem, depth - 1); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } else if ( | 
					
						
							|  |  |  |       depth && expected && typeof expected === 'object' && actual && typeof actual === 'object') { | 
					
						
							|  |  |  |     new Set(Object.keys(expected).concat(Object.keys(actual))).forEach((key) => { | 
					
						
							|  |  |  |       const actualItem = actual[key]; | 
					
						
							|  |  |  |       const expectedItem = expected[key]; | 
					
						
							|  |  |  |       listPropertyDifferences(diffs, path + '.' + key, actualItem, expectedItem, depth - 1); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     diffs.push(`${path}: Expected ${jasmine.pp(actual)} to be ${jasmine.pp(expected)}`); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |