angular-cn/packages/core/test/render3/utils.ts

114 lines
3.6 KiB
TypeScript
Raw Normal View History

/**
* @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
*/
/** 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({
* create: matchDebug('someValue')
* })
* ```
*
* In the above example it will assert that `obj.create.debug === 'someValue'`.
*
* @param expected Expected value.
*/
export function matchDebug<T>(expected: T): any {
const matcher = function() {};
let actual: any = matchDebug;
matcher.asymmetricMatch = function(objectWithDebug: any) {
return jasmine.matchersUtil.equals(actual = objectWithDebug.debug, expected);
};
matcher.jasmineToString = function() {
if (actual === matchDebug) {
// `asymmetricMatch` never got called hence no error to display
return '';
}
return buildFailureMessage(actual, expected);
};
return matcher;
}
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)}`);
}
}