UNPKG

11.1 kBJavaScriptView Raw
1import { extendObject, applyCssPrefixes } from '@angular/flex-layout/_private-utils';
2import { TestBed } from '@angular/core/testing';
3import { By } from '@angular/platform-browser';
4
5/**
6 * @license
7 * Copyright Google LLC All Rights Reserved.
8 *
9 * Use of this source code is governed by an MIT-style license that can be
10 * found in the LICENSE file at https://angular.io/license
11 */
12/**
13 * Exported DOM accessor utility functions
14 */
15const _dom = {
16 hasStyle,
17 getDistributedNodes,
18 getShadowRoot,
19 getText,
20 getStyle,
21 childNodes,
22 childNodesAsList,
23 hasClass,
24 hasAttribute,
25 getAttribute,
26 hasShadowRoot,
27 isCommentNode,
28 isElementNode,
29 isPresent,
30 isShadowRoot,
31 tagName,
32 lastElementChild
33};
34// ******************************************************************************************
35// These functions are cloned from
36// * @angular/platform-browser/src/browser/GenericBrowserDomAdapter
37// and are to be used ONLY internally in custom-matchers.ts and Unit Tests
38// ******************************************************************************************
39function getStyle(element, stylename) {
40 return element.style[stylename];
41}
42function hasStyle(element, styleName, styleValue = '', inlineOnly = true) {
43 let value = getStyle(element, styleName) || '';
44 if (!value && !inlineOnly) {
45 // Search stylesheets
46 value = typeof getComputedStyle === 'function' &&
47 getComputedStyle(element).getPropertyValue(styleName) || '';
48 }
49 return styleValue ? value == styleValue : value.length > 0;
50}
51function getDistributedNodes(el) {
52 return el.getDistributedNodes();
53}
54function getShadowRoot(el) {
55 return el.shadowRoot;
56}
57function getText(el) {
58 return el.textContent || '';
59}
60function childNodesAsList(el) {
61 const list = el.childNodes;
62 const res = new Array(list.length);
63 for (let i = 0; i < list.length; i++) {
64 res[i] = list[i];
65 }
66 return res;
67}
68function hasClass(element, className) {
69 return element.classList.contains(className);
70}
71function hasAttribute(element, attributeName) {
72 return element.hasAttribute(attributeName);
73}
74function getAttribute(element, attributeName) {
75 return element.getAttribute(attributeName);
76}
77function childNodes(el) {
78 return el.childNodes;
79}
80function hasShadowRoot(node) {
81 return isPresent(node.shadowRoot) && node instanceof HTMLElement;
82}
83function isCommentNode(node) {
84 return node.nodeType === Node.COMMENT_NODE;
85}
86function isElementNode(node) {
87 return node.nodeType === Node.ELEMENT_NODE;
88}
89function isShadowRoot(node) {
90 return node instanceof DocumentFragment;
91}
92function isPresent(obj) {
93 return obj != null;
94}
95function tagName(element) {
96 return element.tagName;
97}
98// ******************************************************************************************
99// These functions are part of the DOM API
100// and are to be used ONLY internally in custom-matchers.ts and Unit Tests
101// ******************************************************************************************
102function lastElementChild(element) {
103 return element.lastElementChild;
104}
105
106const _global = (typeof window === 'undefined' ? global : window);
107const expect$1 = _global.expect;
108/**
109 * NOTE: These custom JASMINE Matchers are used only
110 * in the Karma/Jasmine testing for the Layout Directives
111 * in `src/lib/flex/api`
112 */
113const customMatchers = {
114 toEqual: function (util) {
115 return {
116 compare: function (actual, expected) {
117 return { pass: util.equals(actual, expected) };
118 }
119 };
120 },
121 toHaveText: function () {
122 return {
123 compare: function (actual, expectedText) {
124 const actualText = elementText(actual);
125 return {
126 pass: actualText == expectedText,
127 get message() {
128 return 'Expected ' + actualText + ' to be equal to ' + expectedText;
129 }
130 };
131 }
132 };
133 },
134 toHaveCssClass: function () {
135 return { compare: buildError(false), negativeCompare: buildError(true) };
136 function buildError(isNot) {
137 return function (actual, className) {
138 return {
139 pass: _dom.hasClass(actual, className) == !isNot,
140 get message() {
141 return `
142 Expected ${actual.outerHTML} ${isNot ? 'not ' : ''}
143 to contain the CSS class '${className}'
144 `;
145 }
146 };
147 };
148 }
149 },
150 toHaveMap: function () {
151 return {
152 compare: function (actual, map) {
153 let allPassed;
154 allPassed = Object.keys(map).length !== 0;
155 Object.keys(map).forEach(key => {
156 allPassed = allPassed && (actual[key] === map[key]);
157 });
158 return {
159 pass: allPassed,
160 get message() {
161 return `
162 Expected ${JSON.stringify(actual)} ${!allPassed ? ' ' : 'not '} to contain the
163 '${JSON.stringify(map)}'
164 `;
165 }
166 };
167 }
168 };
169 },
170 toHaveAttributes: function () {
171 return {
172 compare: function (actual, map) {
173 let allPassed;
174 let attributeNames = Object.keys(map);
175 allPassed = attributeNames.length !== 0;
176 attributeNames.forEach(name => {
177 allPassed = allPassed && _dom.hasAttribute(actual, name)
178 && _dom.getAttribute(actual, name) === map[name];
179 });
180 return {
181 pass: allPassed,
182 get message() {
183 return `
184 Expected ${actual.outerHTML} ${allPassed ? 'not ' : ''} attributes to contain
185 '${JSON.stringify(map)}'
186 `;
187 }
188 };
189 }
190 };
191 },
192 /**
193 * Check element's inline styles only
194 */
195 toHaveStyle: function () {
196 return {
197 compare: buildCompareStyleFunction(true)
198 };
199 },
200 /**
201 * Check element's css stylesheet only (if not present inline)
202 */
203 toHaveCSS: function () {
204 return {
205 compare: buildCompareStyleFunction(false)
206 };
207 }
208};
209/**
210 * Curried value to function to check styles that are inline or in a stylesheet for the
211 * specified DOM element.
212 */
213function buildCompareStyleFunction(inlineOnly = true) {
214 return function (actual, styles, styler) {
215 const found = {};
216 const styleMap = {};
217 if (typeof styles === 'string') {
218 styleMap[styles] = '';
219 }
220 else {
221 Object.assign(styleMap, styles);
222 }
223 let allPassed = Object.keys(styleMap).length !== 0;
224 Object.keys(styleMap).forEach(prop => {
225 let { elHasStyle, current } = hasPrefixedStyles(actual, prop, styleMap[prop], inlineOnly, styler);
226 allPassed = allPassed && elHasStyle;
227 if (!elHasStyle) {
228 extendObject(found, current);
229 }
230 });
231 return {
232 pass: allPassed,
233 get message() {
234 const expectedValueStr = (typeof styles === 'string') ? styleMap :
235 JSON.stringify(styleMap, null, 2);
236 const foundValueStr = inlineOnly ? actual.outerHTML : JSON.stringify(found);
237 return `
238 Expected ${foundValueStr}${!allPassed ? '' : ' not'} to contain the
239 CSS ${typeof styles === 'string' ? 'property' : 'styles'} '${expectedValueStr}'
240 `;
241 }
242 };
243 };
244}
245/**
246 * Validate presence of requested style or use fallback
247 * to possible `prefixed` styles. Useful when some browsers
248 * (Safari, IE, etc) will use prefixed style instead of defaults.
249 */
250function hasPrefixedStyles(actual, key, value, inlineOnly, styler) {
251 const current = {};
252 if (value === '*') {
253 return { elHasStyle: styler.lookupStyle(actual, key, inlineOnly) !== '', current };
254 }
255 value = value.trim();
256 let elHasStyle = styler.lookupStyle(actual, key, inlineOnly) === value;
257 if (!elHasStyle) {
258 let prefixedStyles = applyCssPrefixes({ [key]: value });
259 Object.keys(prefixedStyles).forEach(prop => {
260 // Search for optional prefixed values
261 elHasStyle = elHasStyle ||
262 styler.lookupStyle(actual, prop, inlineOnly) === prefixedStyles[prop];
263 });
264 }
265 // Return BOTH confirmation and current computed key values (if confirmation == false)
266 return { elHasStyle, current };
267}
268function elementText(n) {
269 const hasNodes = (m) => {
270 const children = _dom.childNodes(m);
271 return children && children['length'];
272 };
273 if (n instanceof Array) {
274 return n.map(elementText).join('');
275 }
276 if (_dom.isCommentNode(n)) {
277 return '';
278 }
279 if (_dom.isElementNode(n) && _dom.tagName(n) == 'CONTENT') {
280 return elementText(Array.prototype.slice.apply(_dom.getDistributedNodes(n)));
281 }
282 if (_dom.hasShadowRoot(n)) {
283 return elementText(_dom.childNodesAsList(_dom.getShadowRoot(n)));
284 }
285 if (hasNodes(n)) {
286 return elementText(_dom.childNodesAsList(n));
287 }
288 return _dom.getText(n);
289}
290
291/**
292 * Function generator that captures a Component Type accessor and enables
293 * `createTestComponent()` to be reusable for *any* captured Component class.
294 */
295function makeCreateTestComponent(getClass) {
296 let componentAny;
297 // Return actual `createTestComponent()` function
298 return function createTestComponent(template, styles) {
299 if (!componentAny) {
300 // Defer access to Component class to enable metadata to be configured properly...
301 componentAny = getClass();
302 }
303 return TestBed
304 .overrideComponent(componentAny, {
305 set: {
306 template: template,
307 styles: styles || [],
308 }
309 })
310 .createComponent(componentAny);
311 };
312}
313/**
314 *
315 */
316function expectNativeEl(fixture, instanceOptions) {
317 extendObject(fixture.componentInstance, instanceOptions || {});
318 fixture.detectChanges();
319 return expect(fixture.debugElement.children[0].nativeElement);
320}
321/**
322 *
323 */
324function expectEl(debugEl) {
325 return expect(debugEl.nativeElement);
326}
327function queryFor(fixture, selector) {
328 return fixture.debugElement.queryAll(By.css(selector));
329}
330
331/**
332 * @license
333 * Copyright Google LLC All Rights Reserved.
334 *
335 * Use of this source code is governed by an MIT-style license that can be
336 * found in the LICENSE file at https://angular.io/license
337 */
338
339/**
340 * Generated bundle index. Do not edit.
341 */
342
343export { _dom, customMatchers, expect$1 as expect, expectEl, expectNativeEl, makeCreateTestComponent, queryFor };
344//# sourceMappingURL=angular-flex-layout-_private-utils-testing.mjs.map