refactor(render): move services to render folder
property_setter_factory selector style_inliner style_url_resolver shadow_css
This commit is contained in:
@ -28,7 +28,7 @@ import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
|
||||
import {TemplateResolver} from 'angular2/src/core/compiler/template_resolver';
|
||||
import {ComponentUrlMapper, RuntimeComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
|
||||
import {UrlResolver} from 'angular2/src/services/url_resolver';
|
||||
import {StyleUrlResolver} from 'angular2/src/core/compiler/style_url_resolver';
|
||||
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
|
||||
import {CssProcessor} from 'angular2/src/core/compiler/css_processor';
|
||||
|
||||
import {Lexer, Parser, dynamicChangeDetection} from 'angular2/change_detection';
|
||||
|
@ -29,7 +29,7 @@ import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
|
||||
import {MockTemplateResolver} from 'angular2/src/mock/template_resolver_mock';
|
||||
import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
|
||||
import {UrlResolver} from 'angular2/src/services/url_resolver';
|
||||
import {StyleUrlResolver} from 'angular2/src/core/compiler/style_url_resolver';
|
||||
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
|
||||
import {CssProcessor} from 'angular2/src/core/compiler/css_processor';
|
||||
import {EventManager} from 'angular2/src/render/dom/events/event_manager';
|
||||
|
||||
|
@ -1,78 +0,0 @@
|
||||
import {describe, ddescribe, it, iit, xit, xdescribe, expect, beforeEach, el} from 'angular2/test_lib';
|
||||
import {setterFactory} from 'angular2/src/core/compiler/property_setter_factory';
|
||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||
|
||||
export function main() {
|
||||
var div;
|
||||
beforeEach( () => {
|
||||
div = el('<div></div>');
|
||||
});
|
||||
describe('property setter factory', () => {
|
||||
|
||||
it('should return a setter for a property', () => {
|
||||
var setterFn = setterFactory('title');
|
||||
setterFn(div, 'Hello');
|
||||
expect(div.title).toEqual('Hello');
|
||||
|
||||
var otherSetterFn = setterFactory('title');
|
||||
expect(setterFn).toBe(otherSetterFn);
|
||||
});
|
||||
|
||||
it('should return a setter for an attribute', () => {
|
||||
var setterFn = setterFactory('attr.role');
|
||||
setterFn(div, 'button');
|
||||
expect(DOM.getAttribute(div, 'role')).toEqual('button');
|
||||
setterFn(div, null);
|
||||
expect(DOM.getAttribute(div, 'role')).toEqual(null);
|
||||
expect(() => {
|
||||
setterFn(div, 4);
|
||||
}).toThrowError("Invalid role attribute, only string values are allowed, got '4'");
|
||||
|
||||
var otherSetterFn = setterFactory('attr.role');
|
||||
expect(setterFn).toBe(otherSetterFn);
|
||||
});
|
||||
|
||||
it('should return a setter for a class', () => {
|
||||
var setterFn = setterFactory('class.active');
|
||||
setterFn(div, true);
|
||||
expect(DOM.hasClass(div, 'active')).toEqual(true);
|
||||
setterFn(div, false);
|
||||
expect(DOM.hasClass(div, 'active')).toEqual(false);
|
||||
|
||||
var otherSetterFn = setterFactory('class.active');
|
||||
expect(setterFn).toBe(otherSetterFn);
|
||||
});
|
||||
|
||||
it('should return a setter for a style', () => {
|
||||
var setterFn = setterFactory('style.width');
|
||||
setterFn(div, '40px');
|
||||
expect(DOM.getStyle(div, 'width')).toEqual('40px');
|
||||
setterFn(div, null);
|
||||
expect(DOM.getStyle(div, 'width')).toEqual('');
|
||||
|
||||
var otherSetterFn = setterFactory('style.width');
|
||||
expect(setterFn).toBe(otherSetterFn);
|
||||
});
|
||||
|
||||
it('should return a setter for a style with a unit', () => {
|
||||
var setterFn = setterFactory('style.height.px');
|
||||
setterFn(div, 40);
|
||||
expect(DOM.getStyle(div, 'height')).toEqual('40px');
|
||||
setterFn(div, null);
|
||||
expect(DOM.getStyle(div, 'height')).toEqual('');
|
||||
|
||||
var otherSetterFn = setterFactory('style.height.px');
|
||||
expect(setterFn).toBe(otherSetterFn);
|
||||
});
|
||||
|
||||
it('should return a setter for innerHtml', () => {
|
||||
var setterFn = setterFactory('innerHtml');
|
||||
setterFn(div, '<span></span>');
|
||||
expect(DOM.getInnerHTML(div)).toEqual('<span></span>');
|
||||
|
||||
var otherSetterFn = setterFactory('innerHtml');
|
||||
expect(setterFn).toBe(otherSetterFn);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
282
modules/angular2/test/core/compiler/selector_spec.js
vendored
282
modules/angular2/test/core/compiler/selector_spec.js
vendored
@ -1,282 +0,0 @@
|
||||
import {describe, it, expect, beforeEach, ddescribe, iit, xit, el} from 'angular2/test_lib';
|
||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||
import {SelectorMatcher} from 'angular2/src/core/compiler/selector';
|
||||
import {CssSelector} from 'angular2/src/core/compiler/selector';
|
||||
import {List, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
export function main() {
|
||||
describe('SelectorMatcher', () => {
|
||||
var matcher, matched, selectableCollector, s1, s2, s3, s4;
|
||||
|
||||
function reset() {
|
||||
matched = ListWrapper.create();
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
reset();
|
||||
s1 = s2 = s3 = s4 = null;
|
||||
selectableCollector = (selector, context) => {
|
||||
ListWrapper.push(matched, selector);
|
||||
ListWrapper.push(matched, context);
|
||||
}
|
||||
matcher = new SelectorMatcher();
|
||||
});
|
||||
|
||||
it('should select by element name case insensitive', () => {
|
||||
matcher.addSelectables(s1 = CssSelector.parse('someTag'), 1);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('SOMEOTHERTAG')[0], selectableCollector)).toEqual(false);
|
||||
expect(matched).toEqual([]);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('SOMETAG')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
});
|
||||
|
||||
it('should select by class name case insensitive', () => {
|
||||
matcher.addSelectables(s1 = CssSelector.parse('.someClass'), 1);
|
||||
matcher.addSelectables(s2 = CssSelector.parse('.someClass.class2'), 2);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('.SOMEOTHERCLASS')[0], selectableCollector)).toEqual(false);
|
||||
expect(matched).toEqual([]);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('.SOMECLASS')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
|
||||
reset();
|
||||
expect(matcher.match(CssSelector.parse('.someClass.class2')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1,s2[0],2]);
|
||||
});
|
||||
|
||||
it('should select by attr name case insensitive independent of the value', () => {
|
||||
matcher.addSelectables(s1 = CssSelector.parse('[someAttr]'), 1);
|
||||
matcher.addSelectables(s2 = CssSelector.parse('[someAttr][someAttr2]'), 2);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('[SOMEOTHERATTR]')[0], selectableCollector)).toEqual(false);
|
||||
expect(matched).toEqual([]);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('[SOMEATTR]')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
|
||||
reset();
|
||||
expect(matcher.match(CssSelector.parse('[SOMEATTR=someValue]')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
|
||||
reset();
|
||||
expect(matcher.match(CssSelector.parse('[someAttr][someAttr2]')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1,s2[0],2]);
|
||||
});
|
||||
|
||||
it('should select by attr name only once if the value is from the DOM', () => {
|
||||
matcher.addSelectables(s1 = CssSelector.parse('[some-decor]'), 1);
|
||||
|
||||
var elementSelector = new CssSelector();
|
||||
var element = el('<div attr></div>');
|
||||
var empty = DOM.getAttribute(element, 'attr');
|
||||
elementSelector.addAttribute('some-decor', empty);
|
||||
matcher.match(elementSelector, selectableCollector);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
});
|
||||
|
||||
it('should select by attr name and value case insensitive', () => {
|
||||
matcher.addSelectables(s1 = CssSelector.parse('[someAttr=someValue]'), 1);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('[SOMEATTR=SOMEOTHERATTR]')[0], selectableCollector)).toEqual(false);
|
||||
expect(matched).toEqual([]);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('[SOMEATTR=SOMEVALUE]')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
});
|
||||
|
||||
it('should select by element name, class name and attribute name with value', () => {
|
||||
matcher.addSelectables(s1 = CssSelector.parse('someTag.someClass[someAttr=someValue]'), 1);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('someOtherTag.someOtherClass[someOtherAttr]')[0], selectableCollector)).toEqual(false);
|
||||
expect(matched).toEqual([]);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('someTag.someOtherClass[someOtherAttr]')[0], selectableCollector)).toEqual(false);
|
||||
expect(matched).toEqual([]);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('someTag.someClass[someOtherAttr]')[0], selectableCollector)).toEqual(false);
|
||||
expect(matched).toEqual([]);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('someTag.someClass[someAttr]')[0], selectableCollector)).toEqual(false);
|
||||
expect(matched).toEqual([]);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('someTag.someClass[someAttr=someValue]')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
});
|
||||
|
||||
it('should select by many attributes and independent of the value', () => {
|
||||
matcher.addSelectables(s1 = CssSelector.parse('input[type=text][control]'), 1);
|
||||
|
||||
var cssSelector = new CssSelector();
|
||||
cssSelector.setElement('input');
|
||||
cssSelector.addAttribute('type', 'text');
|
||||
cssSelector.addAttribute('control', 'one');
|
||||
|
||||
expect(matcher.match(cssSelector, selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0], 1]);
|
||||
});
|
||||
|
||||
it('should select independent of the order in the css selector', () => {
|
||||
matcher.addSelectables(s1 = CssSelector.parse('[someAttr].someClass'), 1);
|
||||
matcher.addSelectables(s2 = CssSelector.parse('.someClass[someAttr]'), 2);
|
||||
matcher.addSelectables(s3 = CssSelector.parse('.class1.class2'), 3);
|
||||
matcher.addSelectables(s4 = CssSelector.parse('.class2.class1'), 4);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('[someAttr].someClass')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1,s2[0],2]);
|
||||
|
||||
reset();
|
||||
expect(matcher.match(CssSelector.parse('.someClass[someAttr]')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1,s2[0],2]);
|
||||
|
||||
reset();
|
||||
expect(matcher.match(CssSelector.parse('.class1.class2')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s3[0],3,s4[0],4]);
|
||||
|
||||
reset();
|
||||
expect(matcher.match(CssSelector.parse('.class2.class1')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s4[0],4,s3[0],3]);
|
||||
});
|
||||
|
||||
it('should not select with a matching :not selector', () => {
|
||||
matcher.addSelectables(CssSelector.parse('p:not(.someClass)'), 1);
|
||||
matcher.addSelectables(CssSelector.parse('p:not([someAttr])'), 2);
|
||||
matcher.addSelectables(CssSelector.parse(':not(.someClass)'), 3);
|
||||
matcher.addSelectables(CssSelector.parse(':not(p)'), 4);
|
||||
matcher.addSelectables(CssSelector.parse(':not(p[someAttr])'), 5);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('p.someClass[someAttr]')[0], selectableCollector)).toEqual(false);
|
||||
expect(matched).toEqual([]);
|
||||
});
|
||||
|
||||
it('should select with a non matching :not selector', () => {
|
||||
matcher.addSelectables(s1 = CssSelector.parse('p:not(.someClass)'), 1);
|
||||
matcher.addSelectables(s2 = CssSelector.parse('p:not(.someOtherClass[someAttr])'), 2);
|
||||
matcher.addSelectables(s3 = CssSelector.parse(':not(.someClass)'), 3);
|
||||
matcher.addSelectables(s4 = CssSelector.parse(':not(.someOtherClass[someAttr])'), 4);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('p[someOtherAttr].someOtherClass')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1,s2[0],2,s3[0],3,s4[0],4]);
|
||||
});
|
||||
|
||||
it('should select with one match in a list', () => {
|
||||
matcher.addSelectables(s1 = CssSelector.parse('input[type=text], textbox'), 1);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('textbox')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[1],1]);
|
||||
|
||||
reset();
|
||||
expect(matcher.match(CssSelector.parse('input[type=text]')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
});
|
||||
|
||||
it('should not select twice with two matches in a list', () => {
|
||||
matcher.addSelectables(s1 = CssSelector.parse('input, .someClass'), 1);
|
||||
|
||||
expect(matcher.match(CssSelector.parse('input.someclass')[0], selectableCollector)).toEqual(true);
|
||||
expect(matched.length).toEqual(2);
|
||||
expect(matched).toEqual([s1[0],1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('CssSelector.parse', () => {
|
||||
it('should detect element names', () => {
|
||||
var cssSelector = CssSelector.parse('sometag')[0];
|
||||
expect(cssSelector.element).toEqual('sometag');
|
||||
expect(cssSelector.toString()).toEqual('sometag');
|
||||
});
|
||||
|
||||
it('should detect class names', () => {
|
||||
var cssSelector = CssSelector.parse('.someClass')[0];
|
||||
expect(cssSelector.classNames).toEqual(['someclass']);
|
||||
|
||||
expect(cssSelector.toString()).toEqual('.someclass');
|
||||
});
|
||||
|
||||
it('should detect attr names', () => {
|
||||
var cssSelector = CssSelector.parse('[attrname]')[0];
|
||||
expect(cssSelector.attrs).toEqual(['attrname', '']);
|
||||
|
||||
expect(cssSelector.toString()).toEqual('[attrname]');
|
||||
});
|
||||
|
||||
it('should detect attr values', () => {
|
||||
var cssSelector = CssSelector.parse('[attrname=attrvalue]')[0];
|
||||
expect(cssSelector.attrs).toEqual(['attrname', 'attrvalue']);
|
||||
expect(cssSelector.toString()).toEqual('[attrname=attrvalue]');
|
||||
});
|
||||
|
||||
it('should detect multiple parts', () => {
|
||||
var cssSelector = CssSelector.parse('sometag[attrname=attrvalue].someclass')[0];
|
||||
expect(cssSelector.element).toEqual('sometag');
|
||||
expect(cssSelector.attrs).toEqual(['attrname', 'attrvalue']);
|
||||
expect(cssSelector.classNames).toEqual(['someclass']);
|
||||
|
||||
expect(cssSelector.toString()).toEqual('sometag.someclass[attrname=attrvalue]');
|
||||
});
|
||||
|
||||
it('should detect multiple attributes', () => {
|
||||
var cssSelector = CssSelector.parse('input[type=text][control]')[0];
|
||||
expect(cssSelector.element).toEqual('input');
|
||||
expect(cssSelector.attrs).toEqual(['type', 'text', 'control', '']);
|
||||
|
||||
expect(cssSelector.toString()).toEqual('input[type=text][control]');
|
||||
});
|
||||
|
||||
it('should detect :not', () => {
|
||||
var cssSelector = CssSelector.parse('sometag:not([attrname=attrvalue].someclass)')[0];
|
||||
expect(cssSelector.element).toEqual('sometag');
|
||||
expect(cssSelector.attrs.length).toEqual(0);
|
||||
expect(cssSelector.classNames.length).toEqual(0);
|
||||
|
||||
var notSelector = cssSelector.notSelector;
|
||||
expect(notSelector.element).toEqual(null);
|
||||
expect(notSelector.attrs).toEqual(['attrname', 'attrvalue']);
|
||||
expect(notSelector.classNames).toEqual(['someclass']);
|
||||
|
||||
expect(cssSelector.toString()).toEqual('sometag:not(.someclass[attrname=attrvalue])');
|
||||
});
|
||||
|
||||
it('should detect :not without truthy', () => {
|
||||
var cssSelector = CssSelector.parse(':not([attrname=attrvalue].someclass)')[0];
|
||||
expect(cssSelector.element).toEqual("*");
|
||||
|
||||
var notSelector = cssSelector.notSelector;
|
||||
expect(notSelector.attrs).toEqual(['attrname', 'attrvalue']);
|
||||
expect(notSelector.classNames).toEqual(['someclass']);
|
||||
|
||||
expect(cssSelector.toString()).toEqual('*:not(.someclass[attrname=attrvalue])');
|
||||
});
|
||||
|
||||
it('should throw when nested :not', () => {
|
||||
expect(() => {
|
||||
CssSelector.parse('sometag:not(:not([attrname=attrvalue].someclass))')[0];
|
||||
}).toThrowError('Nesting :not is not allowed in a selector');
|
||||
});
|
||||
|
||||
it('should detect lists of selectors', () => {
|
||||
var cssSelectors = CssSelector.parse('.someclass,[attrname=attrvalue], sometag');
|
||||
expect(cssSelectors.length).toEqual(3);
|
||||
|
||||
expect(cssSelectors[0].classNames).toEqual(['someclass']);
|
||||
expect(cssSelectors[1].attrs).toEqual(['attrname', 'attrvalue']);
|
||||
expect(cssSelectors[2].element).toEqual('sometag');
|
||||
});
|
||||
|
||||
it('should detect lists of selectors with :not', () => {
|
||||
var cssSelectors = CssSelector.parse('input[type=text], :not(textarea), textbox:not(.special)');
|
||||
expect(cssSelectors.length).toEqual(3);
|
||||
|
||||
expect(cssSelectors[0].element).toEqual('input');
|
||||
expect(cssSelectors[0].attrs).toEqual(['type', 'text']);
|
||||
|
||||
expect(cssSelectors[1].element).toEqual('*');
|
||||
expect(cssSelectors[1].notSelector.element).toEqual('textarea');
|
||||
|
||||
expect(cssSelectors[2].element).toEqual('textbox');
|
||||
expect(cssSelectors[2].notSelector.classNames).toEqual(['special']);
|
||||
});
|
||||
});
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
import {describe, beforeEach, it, expect, ddescribe, iit, SpyObject, el} from 'angular2/test_lib';
|
||||
import {ShadowCss} from 'angular2/src/core/compiler/shadow_dom_emulation/shadow_css';
|
||||
|
||||
import {RegExpWrapper, StringWrapper} from 'angular2/src/facade/lang';
|
||||
|
||||
export function main() {
|
||||
describe('ShadowCss', function() {
|
||||
|
||||
function s(css: string, contentAttr:string, hostAttr:string = '') {
|
||||
var shadowCss = new ShadowCss();
|
||||
var shim = shadowCss.shimCssText(css, contentAttr, hostAttr);
|
||||
var nlRegexp = RegExpWrapper.create('\\n');
|
||||
return StringWrapper.replaceAll(shim, nlRegexp, '');
|
||||
}
|
||||
|
||||
it('should handle empty string', () => {
|
||||
expect(s('', 'a')).toEqual('');
|
||||
});
|
||||
|
||||
it('should add an attribute to every rule', () => {
|
||||
var css = 'one {color: red;}two {color: red;}';
|
||||
var expected = 'one[a] {color: red;}two[a] {color: red;}';
|
||||
expect(s(css, 'a')).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should hanlde invalid css', () => {
|
||||
var css = 'one {color: red;}garbage';
|
||||
var expected = 'one[a] {color: red;}';
|
||||
expect(s(css, 'a')).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should add an attribute to every selector', () => {
|
||||
var css = 'one, two {color: red;}';
|
||||
var expected = 'one[a], two[a] {color: red;}';
|
||||
expect(s(css, 'a')).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should handle media rules', () => {
|
||||
var css = '@media screen and (max-width: 800px) {div {font-size: 50px;}}';
|
||||
var expected = '@media screen and (max-width: 800px) {div[a] {font-size: 50px;}}';
|
||||
expect(s(css, 'a')).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should handle media rules with simple rules', () => {
|
||||
var css = '@media screen and (max-width: 800px) {div {font-size: 50px;}} div {}';
|
||||
var expected = '@media screen and (max-width: 800px) {div[a] {font-size: 50px;}}div[a] {}';
|
||||
expect(s(css, 'a')).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should handle complicated selectors', () => {
|
||||
expect(s('one::before {}', 'a')).toEqual('one[a]::before {}');
|
||||
expect(s('one two {}', 'a')).toEqual('one[a] two[a] {}');
|
||||
expect(s('one>two {}', 'a')).toEqual('one[a] > two[a] {}');
|
||||
expect(s('one+two {}', 'a')).toEqual('one[a] + two[a] {}');
|
||||
expect(s('one~two {}', 'a')).toEqual('one[a] ~ two[a] {}');
|
||||
expect(s('.one.two > three {}', 'a')).toEqual('.one.two[a] > three[a] {}');
|
||||
expect(s('one[attr="value"] {}', 'a')).toEqual('one[attr="value"][a] {}');
|
||||
expect(s('one[attr=value] {}', 'a')).toEqual('one[attr="value"][a] {}');
|
||||
expect(s('one[attr^="value"] {}', 'a')).toEqual('one[attr^="value"][a] {}');
|
||||
expect(s('one[attr$="value"] {}', 'a')).toEqual('one[attr$="value"][a] {}');
|
||||
expect(s('one[attr*="value"] {}', 'a')).toEqual('one[attr*="value"][a] {}');
|
||||
expect(s('one[attr|="value"] {}', 'a')).toEqual('one[attr|="value"][a] {}');
|
||||
expect(s('one[attr] {}', 'a')).toEqual('one[attr][a] {}');
|
||||
expect(s('[is="one"] {}', 'a')).toEqual('[is="one"][a] {}');
|
||||
});
|
||||
|
||||
it('should handle :host', () => {
|
||||
expect(s(':host {}', 'a', 'a-host')).toEqual('[a-host] {}');
|
||||
expect(s(':host(.x,.y) {}', 'a', 'a-host')).toEqual('[a-host].x, [a-host].y {}');
|
||||
expect(s(':host(.x,.y) > .z {}', 'a', 'a-host')).toEqual('[a-host].x > .z, [a-host].y > .z {}');
|
||||
});
|
||||
|
||||
it('should handle :host-context', () => {
|
||||
expect(s(':host-context(.x) {}', 'a', 'a-host')).toEqual('[a-host].x, .x [a-host] {}');
|
||||
expect(s(':host-context(.x) > .y {}', 'a', 'a-host')).toEqual('[a-host].x > .y, .x [a-host] > .y {}');
|
||||
});
|
||||
|
||||
it('should support polyfill-next-selector', () => {
|
||||
var css = s("polyfill-next-selector {content: 'x > y'} z {}", 'a');
|
||||
expect(css).toEqual('x[a] > y[a] {}');
|
||||
|
||||
css = s('polyfill-next-selector {content: "x > y"} z {}', 'a');
|
||||
expect(css).toEqual('x[a] > y[a] {}');
|
||||
});
|
||||
|
||||
it('should support polyfill-unscoped-rule', () => {
|
||||
var css = s("polyfill-unscoped-rule {content: '#menu > .bar';background: blue;}", 'a');
|
||||
expect(StringWrapper.contains(css, '#menu > .bar {;background: blue;}')).toBeTruthy();
|
||||
|
||||
css = s('polyfill-unscoped-rule {content: "#menu > .bar";background: blue;}', 'a');
|
||||
expect(StringWrapper.contains(css, '#menu > .bar {;background: blue;}')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should support polyfill-rule', () => {
|
||||
var css = s("polyfill-rule {content: ':host.foo .bar';background: blue;}", 'a', 'a-host');
|
||||
expect(css).toEqual('[a-host].foo .bar {background: blue;}');
|
||||
|
||||
css = s('polyfill-rule {content: ":host.foo .bar";background: blue;}', 'a', 'a-host');
|
||||
expect(css).toEqual('[a-host].foo .bar {background: blue;}');
|
||||
});
|
||||
|
||||
it('should handle ::shadow', () => {
|
||||
var css = s('x::shadow > y {}', 'a');
|
||||
expect(css).toEqual('x[a] > y[a] {}');
|
||||
});
|
||||
|
||||
it('should handle /deep/', () => {
|
||||
var css = s('x /deep/ y {}', 'a');
|
||||
expect(css).toEqual('x[a] y[a] {}');
|
||||
});
|
||||
|
||||
it('should handle >>>', () => {
|
||||
var css = s('x >>> y {}', 'a');
|
||||
expect(css).toEqual('x[a] y[a] {}');
|
||||
});
|
||||
});
|
||||
}
|
@ -30,8 +30,8 @@ import {ShadowDomStrategy,
|
||||
import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
|
||||
import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
|
||||
import {UrlResolver} from 'angular2/src/services/url_resolver';
|
||||
import {StyleUrlResolver} from 'angular2/src/core/compiler/style_url_resolver';
|
||||
import {StyleInliner} from 'angular2/src/core/compiler/style_inliner';
|
||||
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
|
||||
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
|
||||
import {CssProcessor} from 'angular2/src/core/compiler/css_processor';
|
||||
|
||||
import {MockTemplateResolver} from 'angular2/src/mock/template_resolver_mock';
|
||||
|
@ -18,8 +18,8 @@ import {
|
||||
resetShadowDomCache,
|
||||
} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||
import {UrlResolver} from 'angular2/src/services/url_resolver';
|
||||
import {StyleUrlResolver} from 'angular2/src/core/compiler/style_url_resolver';
|
||||
import {StyleInliner} from 'angular2/src/core/compiler/style_inliner';
|
||||
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
|
||||
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
|
||||
import {ProtoView} from 'angular2/src/core/compiler/view';
|
||||
import {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
|
||||
|
||||
|
@ -1,235 +0,0 @@
|
||||
import {
|
||||
AsyncTestCompleter,
|
||||
beforeEach,
|
||||
beforeEachBindings,
|
||||
ddescribe,
|
||||
describe,
|
||||
el,
|
||||
expect,
|
||||
iit,
|
||||
inject,
|
||||
it,
|
||||
xit,
|
||||
} from 'angular2/test_lib';
|
||||
import {StyleInliner} from 'angular2/src/core/compiler/style_inliner';
|
||||
|
||||
import {isBlank} from 'angular2/src/facade/lang';
|
||||
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
||||
import {Map, MapWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
import {XHR} from 'angular2/src/services/xhr';
|
||||
|
||||
import {bind} from 'angular2/di';
|
||||
|
||||
export function main() {
|
||||
describe('StyleInliner', () => {
|
||||
beforeEachBindings(() => [
|
||||
bind(XHR).toClass(FakeXHR),
|
||||
]);
|
||||
|
||||
describe('loading', () => {
|
||||
|
||||
it('should return a string when there is no import statement', inject([StyleInliner], (inliner) => {
|
||||
var css = '.main {}';
|
||||
var loadedCss = inliner.inlineImports(css, 'http://base');
|
||||
expect(loadedCss).not.toBePromise();
|
||||
expect(loadedCss).toEqual(css);
|
||||
}));
|
||||
|
||||
it('should inline @import rules',
|
||||
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
||||
xhr.reply('http://base/one.css', '.one {}');
|
||||
var css = '@import url("one.css");.main {}';
|
||||
var loadedCss = inliner.inlineImports(css, 'http://base');
|
||||
expect(loadedCss).toBePromise();
|
||||
PromiseWrapper.then(
|
||||
loadedCss,
|
||||
function(css) {
|
||||
expect(css).toEqual('.one {}\n.main {}');
|
||||
async.done();
|
||||
},
|
||||
function(e) {
|
||||
throw 'fail;'
|
||||
}
|
||||
);
|
||||
}));
|
||||
|
||||
it('should support url([unquoted url]) in @import rules',
|
||||
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
||||
xhr.reply('http://base/one.css', '.one {}');
|
||||
var css = '@import url(one.css);.main {}';
|
||||
var loadedCss = inliner.inlineImports(css, 'http://base');
|
||||
expect(loadedCss).toBePromise();
|
||||
PromiseWrapper.then(
|
||||
loadedCss,
|
||||
function(css) {
|
||||
expect(css).toEqual('.one {}\n.main {}');
|
||||
async.done();
|
||||
},
|
||||
function(e) {
|
||||
throw 'fail;'
|
||||
}
|
||||
);
|
||||
}));
|
||||
|
||||
it('should handle @import error gracefuly',
|
||||
inject([StyleInliner, AsyncTestCompleter], (inliner, async) => {
|
||||
var css = '@import "one.css";.main {}';
|
||||
var loadedCss = inliner.inlineImports(css, 'http://base');
|
||||
expect(loadedCss).toBePromise();
|
||||
PromiseWrapper.then(
|
||||
loadedCss,
|
||||
function(css) {
|
||||
expect(css).toEqual('/* failed to import http://base/one.css */\n.main {}');
|
||||
async.done();
|
||||
},
|
||||
function(e) {
|
||||
throw 'fail;'
|
||||
}
|
||||
);
|
||||
}));
|
||||
|
||||
it('should inline multiple @import rules',
|
||||
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
||||
xhr.reply('http://base/one.css', '.one {}');
|
||||
xhr.reply('http://base/two.css', '.two {}');
|
||||
var css = '@import "one.css";@import "two.css";.main {}';
|
||||
var loadedCss = inliner.inlineImports(css, 'http://base');
|
||||
expect(loadedCss).toBePromise();
|
||||
PromiseWrapper.then(
|
||||
loadedCss,
|
||||
function(css) {
|
||||
expect(css).toEqual('.one {}\n.two {}\n.main {}');
|
||||
async.done();
|
||||
},
|
||||
function(e) {
|
||||
throw 'fail;'
|
||||
}
|
||||
);
|
||||
}));
|
||||
|
||||
it('should inline nested @import rules',
|
||||
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
||||
xhr.reply('http://base/one.css', '@import "two.css";.one {}');
|
||||
xhr.reply('http://base/two.css', '.two {}');
|
||||
var css = '@import "one.css";.main {}';
|
||||
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
||||
expect(loadedCss).toBePromise();
|
||||
PromiseWrapper.then(
|
||||
loadedCss,
|
||||
function(css) {
|
||||
expect(css).toEqual('.two {}\n.one {}\n.main {}');
|
||||
async.done();
|
||||
},
|
||||
function(e) {
|
||||
throw 'fail;'
|
||||
}
|
||||
);
|
||||
}));
|
||||
|
||||
it('should handle circular dependencies gracefuly',
|
||||
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
||||
xhr.reply('http://base/one.css', '@import "two.css";.one {}');
|
||||
xhr.reply('http://base/two.css', '@import "one.css";.two {}');
|
||||
var css = '@import "one.css";.main {}';
|
||||
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
||||
expect(loadedCss).toBePromise();
|
||||
PromiseWrapper.then(
|
||||
loadedCss,
|
||||
function(css) {
|
||||
expect(css).toEqual('.two {}\n.one {}\n.main {}');
|
||||
async.done();
|
||||
},
|
||||
function(e) {
|
||||
throw 'fail;'
|
||||
}
|
||||
);
|
||||
}));
|
||||
|
||||
it('should handle invalid @import fracefuly',
|
||||
inject([StyleInliner, AsyncTestCompleter], (inliner, async) => {
|
||||
// Invalid rule: the url is not quoted
|
||||
var css = '@import one.css;.main {}';
|
||||
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
||||
expect(loadedCss).toBePromise();
|
||||
PromiseWrapper.then(
|
||||
loadedCss,
|
||||
function(css) {
|
||||
expect(css).toEqual('/* Invalid import rule: "@import one.css;" */.main {}');
|
||||
async.done();
|
||||
},
|
||||
function(e) {
|
||||
throw 'fail;'
|
||||
}
|
||||
);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('media query', () => {
|
||||
it('should wrap inlined content in media query',
|
||||
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
||||
xhr.reply('http://base/one.css', '.one {}');
|
||||
var css = '@import "one.css" (min-width: 700px) and (orientation: landscape);';
|
||||
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
||||
expect(loadedCss).toBePromise();
|
||||
PromiseWrapper.then(
|
||||
loadedCss,
|
||||
function(css) {
|
||||
expect(css).toEqual('@media (min-width: 700px) and (orientation: landscape) {\n.one {}\n}\n');
|
||||
async.done();
|
||||
},
|
||||
function(e) {
|
||||
throw 'fail;'
|
||||
}
|
||||
);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('url rewritting', () => {
|
||||
it('should rewrite url in inlined content',
|
||||
inject([XHR, StyleInliner, AsyncTestCompleter], (xhr, inliner, async) => {
|
||||
// it should rewrite both '@import' and 'url()'
|
||||
xhr.reply('http://base/one.css', '@import "./nested/two.css";.one {background-image: url("one.jpg");}');
|
||||
xhr.reply('http://base/nested/two.css', '.two {background-image: url("../img/two.jpg");}');
|
||||
var css = '@import "one.css";'
|
||||
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
||||
expect(loadedCss).toBePromise();
|
||||
PromiseWrapper.then(
|
||||
loadedCss,
|
||||
function(css) {
|
||||
expect(css).toEqual(
|
||||
".two {background-image: url('http://base/img/two.jpg');}\n" +
|
||||
".one {background-image: url('http://base/one.jpg');}\n"
|
||||
);
|
||||
async.done();
|
||||
},
|
||||
function(e) {
|
||||
throw 'fail;'
|
||||
}
|
||||
);
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class FakeXHR extends XHR {
|
||||
_responses: Map;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._responses = MapWrapper.create();
|
||||
}
|
||||
|
||||
get(url: string): Promise<string> {
|
||||
var response = MapWrapper.get(this._responses, url);
|
||||
if (isBlank(response)) {
|
||||
return PromiseWrapper.reject('xhr error');
|
||||
}
|
||||
|
||||
return PromiseWrapper.resolve(response);
|
||||
}
|
||||
|
||||
reply(url: string, response: string) {
|
||||
MapWrapper.set(this._responses, url, response);
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
import {describe, it, expect, beforeEach, ddescribe, iit, xit, el} from 'angular2/test_lib';
|
||||
import {StyleUrlResolver} from 'angular2/src/core/compiler/style_url_resolver';
|
||||
|
||||
import {UrlResolver} from 'angular2/src/services/url_resolver';
|
||||
|
||||
export function main() {
|
||||
describe('StyleUrlResolver', () => {
|
||||
it('should resolve "url()" urls', () => {
|
||||
var styleUrlResolver = new StyleUrlResolver(new FakeUrlResolver());
|
||||
var css = `
|
||||
.foo {
|
||||
background-image: url("double.jpg");
|
||||
background-image: url('simple.jpg');
|
||||
background-image: url(noquote.jpg);
|
||||
}`;
|
||||
var expectedCss = `
|
||||
.foo {
|
||||
background-image: url('base/double.jpg');
|
||||
background-image: url('base/simple.jpg');
|
||||
background-image: url('base/noquote.jpg');
|
||||
}`;
|
||||
|
||||
var resolvedCss = styleUrlResolver.resolveUrls(css, 'base');
|
||||
expect(resolvedCss).toEqual(expectedCss);
|
||||
});
|
||||
|
||||
it('should resolve "@import" urls', () => {
|
||||
var styleUrlResolver = new StyleUrlResolver(new FakeUrlResolver());
|
||||
var css = `
|
||||
@import '1.css';
|
||||
@import "2.css";
|
||||
`;
|
||||
var expectedCss = `
|
||||
@import 'base/1.css';
|
||||
@import 'base/2.css';
|
||||
`;
|
||||
|
||||
var resolvedCss = styleUrlResolver.resolveUrls(css, 'base');
|
||||
expect(resolvedCss).toEqual(expectedCss);
|
||||
});
|
||||
|
||||
it('should resolve "@import url()" urls', () => {
|
||||
var styleUrlResolver = new StyleUrlResolver(new FakeUrlResolver());
|
||||
var css = `
|
||||
@import url('3.css');
|
||||
@import url("4.css");
|
||||
@import url(5.css);
|
||||
`;
|
||||
var expectedCss = `
|
||||
@import url('base/3.css');
|
||||
@import url('base/4.css');
|
||||
@import url('base/5.css');
|
||||
`;
|
||||
|
||||
var resolvedCss = styleUrlResolver.resolveUrls(css, 'base');
|
||||
expect(resolvedCss).toEqual(expectedCss);
|
||||
});
|
||||
|
||||
it('should support media query in "@import"', () => {
|
||||
var styleUrlResolver = new StyleUrlResolver(new FakeUrlResolver());
|
||||
var css = `
|
||||
@import 'print.css' print;
|
||||
@import url(print.css) print;
|
||||
`;
|
||||
var expectedCss = `
|
||||
@import 'base/print.css' print;
|
||||
@import url('base/print.css') print;
|
||||
`;
|
||||
|
||||
var resolvedCss = styleUrlResolver.resolveUrls(css, 'base');
|
||||
expect(resolvedCss).toEqual(expectedCss);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class FakeUrlResolver extends UrlResolver {
|
||||
resolve(baseUrl: string, url: string): string {
|
||||
return baseUrl + '/' + url;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user