mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
Updates us to version 4.0 of Jasmine and fixes some errors that were the result of us depending upon deprecated APIs. We need to do this both to stay up to date and because it was going to break eventually, because one of the Bazel packages was logging a deprecation warning that version 4.0 was required. There were also some cases where the state of `ngDevMode` had started leaking out between tests. PR Close #45558
258 lines
7.5 KiB
TypeScript
258 lines
7.5 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.io/license
|
|
*/
|
|
|
|
import {I18nDebug, IcuCreateOpCodes, TI18n, TIcu} from '@angular/core/src/render3/interfaces/i18n';
|
|
import {TNode} from '@angular/core/src/render3/interfaces/node';
|
|
import {TView} from '@angular/core/src/render3/interfaces/view';
|
|
|
|
import {isDOMElement, isDOMText, isTI18n, isTIcu, isTNode, isTView} from './is_shape_of';
|
|
|
|
|
|
/**
|
|
* Generic matcher which asserts that an object is of a given shape (`shapePredicate`) and that it
|
|
* contains a subset of properties.
|
|
*
|
|
* @param name Name of `shapePredicate` to display when assertion fails.
|
|
* @param shapePredicate Predicate which verifies that the object is of correct shape.
|
|
* @param expected Expected set of properties to be found on the object.
|
|
*/
|
|
export function matchObjectShape<T>(
|
|
name: string, shapePredicate: (obj: any) => obj is T,
|
|
expected: Partial<T> = {}): jasmine.AsymmetricMatcher<T> {
|
|
const matcher = function() {};
|
|
let _actual: any = null;
|
|
let _matcherUtils: jasmine.MatchersUtil = null!;
|
|
|
|
matcher.asymmetricMatch = function(actual: any, matcherUtils: jasmine.MatchersUtil) {
|
|
_actual = actual;
|
|
_matcherUtils = matcherUtils;
|
|
if (!shapePredicate(actual)) return false;
|
|
for (const key in expected) {
|
|
if (expected.hasOwnProperty(key) && !matcherUtils.equals(actual[key], expected[key])) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
matcher.jasmineToString = function(pp: (value: any) => string) {
|
|
let errors: string[] = [];
|
|
if (!_actual || typeof _actual !== 'object') {
|
|
return `Expecting ${pp(expect)} got ${pp(_actual)}`;
|
|
}
|
|
for (const key in expected) {
|
|
if (expected.hasOwnProperty(key) && !_matcherUtils.equals(_actual[key], expected[key]))
|
|
errors.push(`\n property obj.${key} to equal ${expected[key]} but got ${_actual[key]}`);
|
|
}
|
|
return errors.join('\n');
|
|
};
|
|
|
|
return matcher;
|
|
}
|
|
|
|
|
|
/**
|
|
* Asymmetric matcher which matches a `TView` of a given shape.
|
|
*
|
|
* Expected usage:
|
|
* ```
|
|
* expect(tNode).toEqual(matchTView({type: TViewType.Root}));
|
|
* expect({
|
|
* node: tNode
|
|
* }).toEqual({
|
|
* node: matchTNode({type: TViewType.Root})
|
|
* });
|
|
* ```
|
|
*
|
|
* @param expected optional properties which the `TView` must contain.
|
|
*/
|
|
export function matchTView(expected?: Partial<TView>): jasmine.AsymmetricMatcher<TView> {
|
|
return matchObjectShape('TView', isTView, expected);
|
|
}
|
|
|
|
/**
|
|
* Asymmetric matcher which matches a `TNode` of a given shape.
|
|
*
|
|
* Expected usage:
|
|
* ```
|
|
* expect(tNode).toEqual(matchTNode({type: TNodeType.Element}));
|
|
* expect({
|
|
* node: tNode
|
|
* }).toEqual({
|
|
* node: matchTNode({type: TNodeType.Element})
|
|
* });
|
|
* ```
|
|
*
|
|
* @param expected optional properties which the `TNode` must contain.
|
|
*/
|
|
export function matchTNode(expected?: Partial<TNode>): jasmine.AsymmetricMatcher<TNode> {
|
|
return matchObjectShape('TNode', isTNode, expected);
|
|
}
|
|
|
|
|
|
/**
|
|
* Asymmetric matcher which matches a `T18n` of a given shape.
|
|
*
|
|
* Expected usage:
|
|
* ```
|
|
* expect(tNode).toEqual(matchT18n({vars: 0}));
|
|
* expect({
|
|
* node: tNode
|
|
* }).toEqual({
|
|
* node: matchT18n({vars: 0})
|
|
* });
|
|
* ```
|
|
*
|
|
* @param expected optional properties which the `TI18n` must contain.
|
|
*/
|
|
export function matchTI18n(expected?: Partial<TI18n>): jasmine.AsymmetricMatcher<TI18n> {
|
|
return matchObjectShape('TI18n', isTI18n, expected);
|
|
}
|
|
|
|
|
|
/**
|
|
* Asymmetric matcher which matches a `T1cu` of a given shape.
|
|
*
|
|
* Expected usage:
|
|
* ```
|
|
* expect(tNode).toEqual(matchTIcu({type: TIcuType.select}));
|
|
* expect({
|
|
* type: TIcuType.select
|
|
* }).toEqual({
|
|
* node: matchT18n({type: TIcuType.select})
|
|
* });
|
|
* ```
|
|
*
|
|
* @param expected optional properties which the `TIcu` must contain.
|
|
*/
|
|
export function matchTIcu(expected?: Partial<TIcu>): jasmine.AsymmetricMatcher<TIcu> {
|
|
return matchObjectShape('TIcu', isTIcu, expected);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Asymmetric matcher which matches a DOM Element.
|
|
*
|
|
* Expected usage:
|
|
* ```
|
|
* expect(div).toEqual(matchT18n('div', {id: '123'}));
|
|
* expect({
|
|
* node: div
|
|
* }).toEqual({
|
|
* node: matchT18n('div', {id: '123'})
|
|
* });
|
|
* ```
|
|
*
|
|
* @param expectedTagName optional DOM tag name.
|
|
* @param expectedAttributes optional DOM element properties.
|
|
*/
|
|
export function matchDomElement(
|
|
expectedTagName: string|undefined = undefined,
|
|
expectedAttrs: {[key: string]: string|null} = {}): jasmine.AsymmetricMatcher<Element> {
|
|
const matcher = function() {};
|
|
let _actual: any = null;
|
|
|
|
matcher.asymmetricMatch = function(actual: any) {
|
|
_actual = actual;
|
|
if (!isDOMElement(actual)) return false;
|
|
if (expectedTagName && (expectedTagName.toUpperCase() !== actual.tagName.toUpperCase())) {
|
|
return false;
|
|
}
|
|
if (expectedAttrs) {
|
|
for (const attrName in expectedAttrs) {
|
|
if (expectedAttrs.hasOwnProperty(attrName)) {
|
|
const expectedAttrValue = expectedAttrs[attrName];
|
|
const actualAttrValue = actual.getAttribute(attrName);
|
|
if (expectedAttrValue !== actualAttrValue) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
matcher.jasmineToString = function() {
|
|
let actualStr = isDOMElement(_actual) ? `<${_actual.tagName}${toString(_actual.attributes)}>` :
|
|
JSON.stringify(_actual);
|
|
let expectedStr = `<${expectedTagName || '*'}${
|
|
Object.keys(expectedAttrs).map(key => ` ${key}=${JSON.stringify(expectedAttrs[key])}`)}>`;
|
|
return `[${actualStr} != ${expectedStr}]`;
|
|
};
|
|
|
|
function toString(attrs: NamedNodeMap) {
|
|
let text = '';
|
|
for (let i = 0; i < attrs.length; i++) {
|
|
const attr = attrs[i];
|
|
text += ` ${attr.name}=${JSON.stringify(attr.value)}`;
|
|
}
|
|
return text;
|
|
}
|
|
|
|
|
|
return matcher;
|
|
}
|
|
|
|
/**
|
|
* Asymmetric matcher which matches DOM text node.
|
|
*
|
|
* Expected usage:
|
|
* ```
|
|
* expect(div).toEqual(matchDomText('text'));
|
|
* expect({
|
|
* node: div
|
|
* }).toEqual({
|
|
* node: matchDomText('text')
|
|
* });
|
|
* ```
|
|
*
|
|
* @param expectedText optional DOM text.
|
|
*/
|
|
export function matchDomText(expectedText: string|undefined = undefined):
|
|
jasmine.AsymmetricMatcher<Text> {
|
|
const matcher = function() {};
|
|
let _actual: any = null;
|
|
|
|
matcher.asymmetricMatch = function(actual: any) {
|
|
_actual = actual;
|
|
if (!isDOMText(actual)) return false;
|
|
if (expectedText && (expectedText !== actual.textContent)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
matcher.jasmineToString = function() {
|
|
let actualStr = isDOMText(_actual) ? `#TEXT: ${JSON.stringify(_actual.textContent)}` :
|
|
JSON.stringify(_actual);
|
|
let expectedStr = `#TEXT: ${JSON.stringify(expectedText)}`;
|
|
return `[${actualStr} != ${expectedStr}]`;
|
|
};
|
|
|
|
return matcher;
|
|
}
|
|
|
|
export function matchI18nMutableOpCodes(expectedMutableOpCodes: string[]):
|
|
jasmine.AsymmetricMatcher<IcuCreateOpCodes> {
|
|
const matcher = function() {};
|
|
let _actual: any = null;
|
|
|
|
matcher.asymmetricMatch = function(actual: any, matchersUtil: jasmine.MatchersUtil) {
|
|
_actual = actual;
|
|
if (!Array.isArray(actual)) return false;
|
|
const debug = (actual as I18nDebug).debug as undefined | string[];
|
|
if (expectedMutableOpCodes && (!matchersUtil.equals(debug, expectedMutableOpCodes))) {
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
matcher.jasmineToString = function() {
|
|
const debug = (_actual as I18nDebug).debug as undefined | string[];
|
|
return `[${JSON.stringify(debug)} != ${expectedMutableOpCodes}]`;
|
|
};
|
|
|
|
return matcher;
|
|
}
|