Skip to content

Commit

Permalink
fix(build): remove use of Angular private API (#195)
Browse files Browse the repository at this point in the history
**flex-layout** uses private APIs from @angular/core. These apis are no longer available in A4.

NOTE: `custom-matchers.ts` still uses the private API for Angular 2.x unit testing. Further work is need to identify a reasonable work-around for all versions of Angular.

Fixes #193.
  • Loading branch information
ThomasBurleson authored and mmalerba committed Feb 22, 2017
1 parent f9f16f5 commit d95cb09
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 33 deletions.
5 changes: 1 addition & 4 deletions src/lib/flexbox/api/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
*/
import {ElementRef, Renderer, OnDestroy} from '@angular/core';

import {__platform_browser_private__} from '@angular/platform-browser';
const getDOM = __platform_browser_private__.getDOM;

import {applyCssPrefixes} from '../../utils/auto-prefixer';

import {ResponsiveActivation, KeyOptions} from '../responsive/responsive-activation';
Expand Down Expand Up @@ -92,7 +89,7 @@ export abstract class BaseFxDirective implements OnDestroy {
*/
protected _getDisplayStyle(source?: HTMLElement): string {
let element: HTMLElement = source || this._elementRef.nativeElement;
let value = (element.style as any)['display'] || getDOM().getComputedStyle(element)['display'];
let value = (element.style as any)['display'] || getComputedStyle(element)['display'];
return value.trim();
}

Expand Down
20 changes: 10 additions & 10 deletions src/lib/flexbox/api/flex.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ import {MockMatchMedia} from '../../media-query/mock/mock-match-media';
import {MatchMedia} from '../../media-query/match-media';
import {FlexLayoutModule} from '../_module';

import {__platform_browser_private__} from '@angular/platform-browser';
import {customMatchers, expect} from '../../utils/testing/custom-matchers';
import {customMatchers, expect } from '../../utils/testing/custom-matchers';
import { _dom as _ } from '../../utils/testing/dom-tools';

import {
makeExpectDOMFrom,
makeExpectDOMForQuery,
Expand All @@ -25,7 +26,6 @@ import {
queryFor
} from '../../utils/testing/helpers';

const getDOM = __platform_browser_private__.getDOM;
const isIE = !!document["documentMode"];

describe('flex directive', () => {
Expand Down Expand Up @@ -65,11 +65,11 @@ describe('flex directive', () => {
fRef.detectChanges();

let dom = fRef.debugElement.children[0].nativeElement;
let isBox = getDOM().hasStyle(dom, 'box-sizing', 'border-box');
let hasFlex = getDOM().hasStyle(dom, 'flex', '1 1 1e-09px') || // IE
getDOM().hasStyle(dom, 'flex', '1 1 1e-9px') || // Chrome
getDOM().hasStyle(dom, 'flex', '1 1 0.000000001px') || // Safari
getDOM().hasStyle(dom, 'flex', '1 1 0px');
let isBox = _.hasStyle(dom, 'box-sizing', 'border-box');
let hasFlex = _.hasStyle(dom, 'flex', '1 1 1e-09px') || // IE
_.hasStyle(dom, 'flex', '1 1 1e-9px') || // Chrome
_.hasStyle(dom, 'flex', '1 1 0.000000001px') || // Safari
_.hasStyle(dom, 'flex', '1 1 0px');

expect(isBox).toBeTruthy();
expect(hasFlex).toBeTruthy();
Expand Down Expand Up @@ -182,7 +182,7 @@ describe('flex directive', () => {
fRef.detectChanges();

let dom = fRef.debugElement.children[0].nativeElement;
let maxWidthStyle = getDOM().getStyle(dom, 'max-width');
let maxWidthStyle = _.getStyle(dom, 'max-width');

expect(maxWidthStyle).toBeFalsy();
});
Expand All @@ -198,7 +198,7 @@ describe('flex directive', () => {
fRef.detectChanges();

let dom = fRef.debugElement.children[0].nativeElement;
let minWidthStyle = getDOM().getStyle(dom, 'min-width');
let minWidthStyle = _.getStyle(dom, 'min-width');

expect(minWidthStyle).toBeFalsy();
});
Expand Down
36 changes: 17 additions & 19 deletions src/lib/utils/testing/custom-matchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/

import {__platform_browser_private__} from '@angular/platform-browser';
import {applyCssPrefixes} from '../auto-prefixer';

declare var global: any;

const getDOM = __platform_browser_private__.getDOM;
const _global = <any>(typeof window === 'undefined' ? global : window);

import {_dom as _} from './dom-tools';
import {applyCssPrefixes} from '../auto-prefixer';

export const expect: (actual: any) => NgMatchers = <any> _global.expect;

/**
Expand Down Expand Up @@ -101,7 +99,7 @@ export const customMatchers: jasmine.CustomMatcherFactories = {
function buildError(isNot: boolean) {
return function (actual: any, className: string) {
return {
pass: getDOM().hasClass(actual, className) == !isNot,
pass: _.hasClass(actual, className) == !isNot,
get message() {
return `
Expected ${actual.outerHTML} ${isNot ? 'not ' : ''}
Expand All @@ -118,7 +116,7 @@ export const customMatchers: jasmine.CustomMatcherFactories = {
compare: function (actual: any, styles: {[k: string]: string}|string) {
let allPassed: boolean;
if (typeof styles === 'string') {
allPassed = getDOM().hasStyle(actual, styles);
allPassed = _.hasStyle(actual, styles);
} else {
allPassed = Object.keys(styles).length !== 0;
Object.keys(styles).forEach(prop => {
Expand Down Expand Up @@ -149,43 +147,43 @@ export const customMatchers: jasmine.CustomMatcherFactories = {
*/
function hasPrefixedStyles(actual, key, value) {
value = value !== "*" ? value.trim() : undefined;
let hasStyle = getDOM().hasStyle(actual, key, value);
if (!hasStyle) {
let elHasStyle = _.hasStyle(actual, key, value);
if (!elHasStyle) {
let prefixedStyles = applyCssPrefixes({[key]: value});
Object.keys(prefixedStyles).forEach(prop => {
// Search for optional prefixed values
hasStyle = hasStyle || getDOM().hasStyle(actual, prop, prefixedStyles[prop]);
elHasStyle = elHasStyle || _.hasStyle(actual, prop, prefixedStyles[prop]);
});
}
return hasStyle;
return elHasStyle;
}

function elementText(n: any): string {
const hasNodes = (m: any) => {
const children = getDOM().childNodes(m);
const children = _.childNodes(m);
return children && children["length"];
};

if (n instanceof Array) {
return n.map(elementText).join('');
}

if (getDOM().isCommentNode(n)) {
if (_.isCommentNode(n)) {
return '';
}

if (getDOM().isElementNode(n) && getDOM().tagName(n) == 'CONTENT') {
return elementText(Array.prototype.slice.apply(getDOM().getDistributedNodes(n)));
if (_.isElementNode(n) && _.tagName(n) == 'CONTENT') {
return elementText(Array.prototype.slice.apply(_.getDistributedNodes(n)));
}

if (getDOM().hasShadowRoot(n)) {
return elementText(getDOM().childNodesAsList(getDOM().getShadowRoot(n)));
if (_.hasShadowRoot(n)) {
return elementText(_.childNodesAsList(_.getShadowRoot(n)));
}

if (hasNodes(n)) {
return elementText(getDOM().childNodesAsList(n));
return elementText(_.childNodesAsList(n));
}

return getDOM().getText(n);
return _.getText(n);
}

94 changes: 94 additions & 0 deletions src/lib/utils/testing/dom-tools.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* @license
* Copyright Google Inc. 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
*/

/**
* Exported DOM accessor utility functions
*/
export const _dom = {
hasStyle,
getDistributedNodes,
getShadowRoot,
getText,
getStyle,
childNodes,
childNodesAsList,
hasClass,
hasShadowRoot,
isCommentNode,
isElementNode,
isPresent,
isShadowRoot,
tagName
};

// ******************************************************************************************
// These functions are cloned from
// * @angular/platform-browser/src/browser/GenericBrowserDomAdapter
// and are to be used ONLY internally in custom-matchers.ts and Unit Tests
// ******************************************************************************************

function getStyle(element: any, stylename: string): string {
return element.style[stylename];
}

function hasStyle(element: any, styleName: string, styleValue: string = null): boolean {
const value = this.getStyle(element, styleName) || '';
return styleValue ? value == styleValue : value.length > 0;
}

function getDistributedNodes(el: HTMLElement): Node[] {
return (<any>el).getDistributedNodes();
}

function getShadowRoot(el: HTMLElement): DocumentFragment {
return (<any>el).shadowRoot;
}

function getText(el: Node): string {
return el.textContent;
}

function childNodesAsList(el: Node): any[] {
const childNodes = el.childNodes;
const res = new Array(childNodes.length);
for (let i = 0; i < childNodes.length; i++) {
res[i] = childNodes[i];
}
return res;
}

function hasClass(element: any, className: string): boolean {
return element.classList.contains(className);
}

function childNodes(el: any): Node[] {
return el.childNodes;
}

function hasShadowRoot(node: any): boolean {
return isPresent(node.shadowRoot) && node instanceof HTMLElement;
}

function isCommentNode(node: Node): boolean {
return node.nodeType === Node.COMMENT_NODE;
}

function isElementNode(node: Node): boolean {
return node.nodeType === Node.ELEMENT_NODE;
}

function isShadowRoot(node: any): boolean {
return node instanceof DocumentFragment;
}

function isPresent(obj: any): boolean {
return obj != null;
}
function tagName(element: any): string {
return element.tagName;
}

0 comments on commit d95cb09

Please sign in to comment.