mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
141 lines
3.9 KiB
TypeScript
141 lines
3.9 KiB
TypeScript
/**
|
|
* @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.dev/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.
|
|
*
|
|
* ```ts
|
|
* 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, matchersUtil: jasmine.MatchersUtil) {
|
|
return matchersUtil.equals((actual = objectWithDebug.debug), expected);
|
|
};
|
|
matcher.jasmineToString = function (pp: (value: any) => string) {
|
|
if (actual === matchDebug) {
|
|
// `asymmetricMatch` never got called hence no error to display
|
|
return '';
|
|
}
|
|
return buildFailureMessage(actual, expected, pp);
|
|
};
|
|
return matcher;
|
|
}
|
|
|
|
export function buildFailureMessage(
|
|
actual: any,
|
|
expected: any,
|
|
pp: (value: any) => string,
|
|
): string {
|
|
const diffs: string[] = [];
|
|
listPropertyDifferences(diffs, '', actual, expected, 5, pp);
|
|
return '\n ' + diffs.join('\n ');
|
|
}
|
|
|
|
function listPropertyDifferences(
|
|
diffs: string[],
|
|
path: string,
|
|
actual: any,
|
|
expected: any,
|
|
depth: number,
|
|
pp: (value: any) => string,
|
|
) {
|
|
if (actual === expected) return;
|
|
if (typeof actual !== typeof expected) {
|
|
diffs.push(`${path}: Expected ${pp(actual)} to be ${pp(expected)}`);
|
|
} else if (depth && Array.isArray(expected)) {
|
|
if (!Array.isArray(actual)) {
|
|
diffs.push(`${path}: Expected ${pp(expected)} but was ${pp(actual)}`);
|
|
} else {
|
|
const maxLength = Math.max(actual.length, expected.length);
|
|
listPropertyDifferences(
|
|
diffs,
|
|
path + '.length',
|
|
expected.length,
|
|
actual.length,
|
|
depth - 1,
|
|
pp,
|
|
);
|
|
for (let i = 0; i < maxLength; i++) {
|
|
const actualItem = actual[i];
|
|
const expectedItem = expected[i];
|
|
listPropertyDifferences(
|
|
diffs,
|
|
path + '[' + i + ']',
|
|
actualItem,
|
|
expectedItem,
|
|
depth - 1,
|
|
pp,
|
|
);
|
|
}
|
|
}
|
|
} 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, pp);
|
|
});
|
|
} else {
|
|
diffs.push(`${path}: Expected ${pp(actual)} to be ${pp(expected)}`);
|
|
}
|
|
}
|