2015-09-02 18:07:31 -04:00
|
|
|
import {
|
|
|
|
ddescribe,
|
|
|
|
describe,
|
|
|
|
xdescribe,
|
|
|
|
it,
|
|
|
|
iit,
|
|
|
|
xit,
|
|
|
|
expect,
|
|
|
|
beforeEach,
|
|
|
|
afterEach,
|
|
|
|
AsyncTestCompleter,
|
2015-09-14 18:59:09 -04:00
|
|
|
inject,
|
|
|
|
beforeEachBindings
|
2015-09-02 18:07:31 -04:00
|
|
|
} from 'angular2/test_lib';
|
2015-09-14 18:59:09 -04:00
|
|
|
import {bind} from 'angular2/src/core/di';
|
2015-09-02 18:07:31 -04:00
|
|
|
import {SpyXHR} from '../core/spies';
|
2015-09-14 18:59:09 -04:00
|
|
|
import {XHR} from 'angular2/src/core/render/xhr';
|
2015-09-10 18:25:36 -04:00
|
|
|
import {BaseException, WrappedException} from 'angular2/src/core/facade/exceptions';
|
2015-09-02 18:07:31 -04:00
|
|
|
|
2015-09-08 11:36:59 -04:00
|
|
|
import {CONST_EXPR, isPresent, StringWrapper} from 'angular2/src/core/facade/lang';
|
2015-09-02 18:07:31 -04:00
|
|
|
import {PromiseWrapper, Promise} from 'angular2/src/core/facade/async';
|
|
|
|
import {evalModule} from './eval_module';
|
|
|
|
import {StyleCompiler} from 'angular2/src/compiler/style_compiler';
|
2015-09-14 18:59:09 -04:00
|
|
|
import {
|
|
|
|
NormalizedDirectiveMetadata,
|
|
|
|
NormalizedTemplateMetadata,
|
|
|
|
TypeMetadata
|
|
|
|
} from 'angular2/src/compiler/directive_metadata';
|
|
|
|
import {SourceExpression, SourceModule} from 'angular2/src/compiler/source_module';
|
2015-09-11 16:37:05 -04:00
|
|
|
import {ViewEncapsulation} from 'angular2/src/core/render/api';
|
2015-09-14 18:59:09 -04:00
|
|
|
import {TEST_BINDINGS} from './test_bindings';
|
|
|
|
import {codeGenValueFn, codeGenExportVariable} from 'angular2/src/compiler/util';
|
2015-09-02 18:07:31 -04:00
|
|
|
|
|
|
|
// Attention: These module names have to correspond to real modules!
|
|
|
|
const MODULE_NAME = 'angular2/test/compiler/style_compiler_spec';
|
|
|
|
const IMPORT_ABS_MODULE_NAME = 'angular2/test/compiler/style_compiler_import';
|
|
|
|
const IMPORT_REL_MODULE_NAME = './style_compiler_import';
|
|
|
|
// Note: Not a real module, only used via mocks.
|
|
|
|
const IMPORT_ABS_MODULE_NAME_WITH_IMPORT =
|
|
|
|
'angular2/test/compiler/style_compiler_transitive_import';
|
|
|
|
|
|
|
|
export function main() {
|
|
|
|
describe('StyleCompiler', () => {
|
2015-09-14 18:59:09 -04:00
|
|
|
var xhr: SpyXHR;
|
|
|
|
beforeEachBindings(() => {
|
2015-09-02 18:07:31 -04:00
|
|
|
xhr = <any>new SpyXHR();
|
2015-09-14 18:59:09 -04:00
|
|
|
return [TEST_BINDINGS, bind(XHR).toValue(xhr)];
|
2015-09-02 18:07:31 -04:00
|
|
|
});
|
|
|
|
|
2015-09-14 18:59:09 -04:00
|
|
|
var compiler: StyleCompiler;
|
|
|
|
|
|
|
|
beforeEach(inject([StyleCompiler], (_compiler) => { compiler = _compiler; }));
|
|
|
|
|
2015-09-02 18:07:31 -04:00
|
|
|
function comp(styles: string[], styleAbsUrls: string[], encapsulation: ViewEncapsulation):
|
2015-09-14 18:59:09 -04:00
|
|
|
NormalizedDirectiveMetadata {
|
|
|
|
return new NormalizedDirectiveMetadata({
|
|
|
|
type: new TypeMetadata({id: 23, moduleId: 'someUrl'}),
|
|
|
|
template: new NormalizedTemplateMetadata(
|
2015-09-02 18:07:31 -04:00
|
|
|
{styles: styles, styleAbsUrls: styleAbsUrls, encapsulation: encapsulation})
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
describe('compileComponentRuntime', () => {
|
|
|
|
function runTest(styles: string[], styleAbsUrls: string[], encapsulation: ViewEncapsulation,
|
|
|
|
expectedStyles: string[]) {
|
|
|
|
return inject([AsyncTestCompleter], (async) => {
|
|
|
|
// Note: Can't use MockXHR as the xhr is called recursively,
|
|
|
|
// so we can't trigger flush.
|
|
|
|
xhr.spy('get').andCallFake((url) => {
|
|
|
|
var response;
|
|
|
|
if (url == IMPORT_ABS_MODULE_NAME) {
|
|
|
|
response = 'span {color: blue}';
|
|
|
|
} else if (url == IMPORT_ABS_MODULE_NAME_WITH_IMPORT) {
|
|
|
|
response = `a {color: green}@import ${IMPORT_REL_MODULE_NAME};`;
|
|
|
|
} else {
|
|
|
|
throw new BaseException(`Unexpected url ${url}`);
|
|
|
|
}
|
|
|
|
return PromiseWrapper.resolve(response);
|
|
|
|
});
|
|
|
|
compiler.compileComponentRuntime(comp(styles, styleAbsUrls, encapsulation))
|
|
|
|
.then((value) => {
|
2015-09-08 11:36:59 -04:00
|
|
|
compareStyles(value, expectedStyles);
|
2015-09-02 18:07:31 -04:00
|
|
|
async.done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
describe('no shim', () => {
|
|
|
|
var encapsulation = ViewEncapsulation.None;
|
|
|
|
|
|
|
|
it('should compile plain css rules',
|
|
|
|
runTest(['div {color: red}', 'span {color: blue}'], [], encapsulation,
|
|
|
|
['div {color: red}', 'span {color: blue}']));
|
|
|
|
|
|
|
|
it('should allow to import rules',
|
|
|
|
runTest(['div {color: red}'], [IMPORT_ABS_MODULE_NAME], encapsulation,
|
|
|
|
['div {color: red}', 'span {color: blue}']));
|
|
|
|
|
|
|
|
it('should allow to import rules transitively',
|
|
|
|
runTest(['div {color: red}'], [IMPORT_ABS_MODULE_NAME_WITH_IMPORT], encapsulation,
|
|
|
|
['div {color: red}', 'a {color: green}', 'span {color: blue}']));
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('with shim', () => {
|
|
|
|
var encapsulation = ViewEncapsulation.Emulated;
|
|
|
|
|
|
|
|
it('should compile plain css rules',
|
|
|
|
runTest(
|
|
|
|
['div {\ncolor: red;\n}', 'span {\ncolor: blue;\n}'], [], encapsulation,
|
|
|
|
['div[_ngcontent-23] {\ncolor: red;\n}', 'span[_ngcontent-23] {\ncolor: blue;\n}']));
|
|
|
|
|
|
|
|
it('should allow to import rules',
|
|
|
|
runTest(
|
|
|
|
['div {\ncolor: red;\n}'], [IMPORT_ABS_MODULE_NAME], encapsulation,
|
|
|
|
['div[_ngcontent-23] {\ncolor: red;\n}', 'span[_ngcontent-23] {\ncolor: blue;\n}']));
|
|
|
|
|
|
|
|
it('should allow to import rules transitively',
|
|
|
|
runTest(['div {\ncolor: red;\n}'], [IMPORT_ABS_MODULE_NAME_WITH_IMPORT], encapsulation, [
|
|
|
|
'div[_ngcontent-23] {\ncolor: red;\n}',
|
|
|
|
'a[_ngcontent-23] {\ncolor: green;\n}',
|
|
|
|
'span[_ngcontent-23] {\ncolor: blue;\n}'
|
|
|
|
]));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('compileComponentCodeGen', () => {
|
|
|
|
function runTest(styles: string[], styleAbsUrls: string[], encapsulation: ViewEncapsulation,
|
|
|
|
expectedStyles: string[]) {
|
|
|
|
return inject([AsyncTestCompleter], (async) => {
|
2015-09-14 18:59:09 -04:00
|
|
|
var sourceExpression =
|
2015-09-02 18:07:31 -04:00
|
|
|
compiler.compileComponentCodeGen(comp(styles, styleAbsUrls, encapsulation));
|
2015-09-14 18:59:09 -04:00
|
|
|
var sourceWithImports = testableExpression(sourceExpression).getSourceWithImports();
|
|
|
|
evalModule(sourceWithImports.source, sourceWithImports.imports, null)
|
2015-09-02 18:07:31 -04:00
|
|
|
.then((value) => {
|
2015-09-08 11:36:59 -04:00
|
|
|
compareStyles(value, expectedStyles);
|
2015-09-02 18:07:31 -04:00
|
|
|
async.done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
describe('no shim', () => {
|
|
|
|
var encapsulation = ViewEncapsulation.None;
|
|
|
|
|
|
|
|
it('should compile plain css ruless',
|
|
|
|
runTest(['div {color: red}', 'span {color: blue}'], [], encapsulation,
|
|
|
|
['div {color: red}', 'span {color: blue}']));
|
|
|
|
|
|
|
|
it('should compile css rules with newlines and quotes',
|
|
|
|
runTest(['div\n{"color": \'red\'}'], [], encapsulation, ['div\n{"color": \'red\'}']));
|
|
|
|
|
|
|
|
it('should allow to import rules',
|
|
|
|
runTest(['div {color: red}'], [IMPORT_ABS_MODULE_NAME], encapsulation,
|
2015-09-08 11:36:59 -04:00
|
|
|
['div {color: red}', 'span {color: blue}']),
|
|
|
|
1000);
|
2015-09-02 18:07:31 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('with shim', () => {
|
|
|
|
var encapsulation = ViewEncapsulation.Emulated;
|
|
|
|
|
|
|
|
it('should compile plain css ruless',
|
|
|
|
runTest(
|
|
|
|
['div {\ncolor: red;\n}', 'span {\ncolor: blue;\n}'], [], encapsulation,
|
|
|
|
['div[_ngcontent-23] {\ncolor: red;\n}', 'span[_ngcontent-23] {\ncolor: blue;\n}']));
|
|
|
|
|
|
|
|
it('should allow to import rules',
|
|
|
|
runTest(
|
|
|
|
['div {color: red}'], [IMPORT_ABS_MODULE_NAME], encapsulation,
|
2015-09-08 11:36:59 -04:00
|
|
|
['div[_ngcontent-23] {\ncolor: red;\n}', 'span[_ngcontent-23] {\ncolor: blue;\n}']),
|
|
|
|
1000);
|
2015-09-02 18:07:31 -04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('compileStylesheetCodeGen', () => {
|
|
|
|
function runTest(style: string, expectedStyles: string[], expectedShimStyles: string[]) {
|
|
|
|
return inject([AsyncTestCompleter], (async) => {
|
|
|
|
var sourceModules = compiler.compileStylesheetCodeGen(MODULE_NAME, style);
|
2015-09-14 18:59:09 -04:00
|
|
|
PromiseWrapper.all(sourceModules.map(sourceModule => {
|
|
|
|
var sourceWithImports =
|
|
|
|
testableModule(sourceModule).getSourceWithImports();
|
|
|
|
return evalModule(sourceWithImports.source, sourceWithImports.imports,
|
|
|
|
null);
|
|
|
|
}))
|
2015-09-02 18:07:31 -04:00
|
|
|
.then((values) => {
|
2015-09-08 11:36:59 -04:00
|
|
|
compareStyles(values[0], expectedStyles);
|
|
|
|
compareStyles(values[1], expectedShimStyles);
|
|
|
|
|
2015-09-02 18:07:31 -04:00
|
|
|
async.done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
it('should compile plain css rules', runTest('div {color: red;}', ['div {color: red;}'],
|
|
|
|
['div[_ngcontent-%COMP%] {\ncolor: red;\n}']));
|
|
|
|
|
|
|
|
it('should allow to import rules with relative paths',
|
|
|
|
runTest(`div {color: red}@import ${IMPORT_REL_MODULE_NAME};`,
|
2015-09-09 10:41:11 -04:00
|
|
|
['div {color: red}', 'span {color: blue}'], [
|
2015-09-02 18:07:31 -04:00
|
|
|
'div[_ngcontent-%COMP%] {\ncolor: red;\n}',
|
|
|
|
'span[_ngcontent-%COMP%] {\ncolor: blue;\n}'
|
2015-09-09 10:41:11 -04:00
|
|
|
]));
|
2015-09-02 18:07:31 -04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-09-14 18:59:09 -04:00
|
|
|
|
|
|
|
function testableExpression(source: SourceExpression): SourceModule {
|
|
|
|
var testableSource = `${source.declarations.join('\n')}
|
|
|
|
${codeGenExportVariable('run')}${codeGenValueFn(['_'], source.expression)};`;
|
|
|
|
return new SourceModule(null, testableSource);
|
|
|
|
}
|
|
|
|
|
|
|
|
function testableModule(sourceModule: SourceModule): SourceModule {
|
2015-09-17 12:58:18 -04:00
|
|
|
var testableSource = `${sourceModule.sourceWithModuleRefs}
|
2015-09-14 18:59:09 -04:00
|
|
|
${codeGenExportVariable('run')}${codeGenValueFn(['_'], 'STYLES')};`;
|
|
|
|
return new SourceModule(sourceModule.moduleId, testableSource);
|
2015-09-02 18:07:31 -04:00
|
|
|
}
|
2015-09-08 11:36:59 -04:00
|
|
|
|
|
|
|
// Needed for Android browsers which add an extra space at the end of some lines
|
|
|
|
function compareStyles(styles: string[], expectedStyles: string[]) {
|
|
|
|
expect(styles.length).toEqual(expectedStyles.length);
|
|
|
|
for (var i = 0; i < styles.length; i++) {
|
|
|
|
expect(StringWrapper.replaceAll(styles[i], /\s+\n/g, '\n')).toEqual(expectedStyles[i]);
|
|
|
|
}
|
|
|
|
}
|