简体   繁体   English

Angular2:具有缓存模板的单元测试路由器

[英]Angular2: Unit-test router with cached template

I'm dealing with some problems doing test on different environments: 我正在处理在不同环境中进行测试的一些问题:

  • SRC : unminified components, using both .js and .html/.css template files SRC :使用.js和.html / .css模板文件的未组合的组件
  • DIST : minified components (only .js, no templates) DIST :缩小组件(仅限.js,无模板)

I made two different karma-conf and karma-test-shim, one for SRC and one for DIST. 我做了两个不同的karma-conf和karma-test-shim,一个用于SRC,一个用于DIST。 In the SRC's one, since i mostly execute tests on components in fakeAsync contexts, i'm caching all my templates and .css at karma's startup, as shown in the following karma-test-shim, to avoid XHR errors. 在SRC的一个,因为我主要在fakeAsync上下文中对组件执行测试,我在karma的启动时缓存我的所有模板和.css,如下面的karma-test-shim所示,以避免XHR错误。

karma-test-shim.src.js 卡玛-测试shim.src.js

// Turn on full stack traces in errors to help debugging
Error.stackTraceLimit = Infinity;

jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;

var karmaFiles = Object.keys(window.__karma__.files); // All files served by Karma.

window.$templateCache = {}; // deckaring Window template cache for caching .html template and .css

// Cancel Karma's synchronous start,
// we will call `__karma__.start()` later, once all the specs are loaded.
__karma__.loaded = function () { };

// Just a special configuration for Karma and coverage
System.config({
    packages: {
        "@angular/core/testing": { main: "../../../../../../node_modules/@angular/core/bundles/core-testing.umd.js" },
        "@angular/compiler/testing": { main: "../../../../base/node_modules/@angular/compiler/bundles/compiler-testing.umd.js" },
        "@angular/common/testing": { main: "../../../../base/node_modules/@angular/common/bundles/common-testing.umd.js" },
        "@angular/http/testing": { main: "../../../../base/node_modules/@angular/http/bundles/http-testing.umd.js" },
        "@angular/router/testing": { main: "../../../../../../node_modules/@angular/router/bundles/router-testing.umd.js" },
        "@angular/platform-browser/testing": { main: "../../../../base/node_modules/@angular/platform-browser/bundles/platform-browser-testing.umd.js" },
        "@angular/platform-browser-dynamic/testing": { main: "../../../../base/node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js" }
    },
    meta: {
        "src/*": { format: "register" }, // Where covered files located
        "packages/*": { format: "register" } // Where covered files located
    }
});

Promise.all([
  System.import('@angular/core/testing'),
  System.import('@angular/platform-browser-dynamic/testing'),
  System.import('@angular/platform-browser-dynamic') // Contains RESOURCE_CACHE_PROVIDER
]).then(function (providers) {
        var testing = providers[0];
        var testingBrowserDynamic = providers[1];
        var browserDynamic = providers[2];

        testing.TestBed.initTestEnvironment(
          testingBrowserDynamic.BrowserDynamicTestingModule,
          testingBrowserDynamic.platformBrowserDynamicTesting()
        );

         testing.TestBed.configureCompiler({
             providers: [
                 browserDynamic.RESOURCE_CACHE_PROVIDER
             ]
         })

    // Import main module
    }).then(function () {
        return Promise.all(
            karmaFiles 
            .filter(onlySpecFiles)
            .map(file2moduleName)
            .map(function (path) {
                return System.import(path).then(function (module) {
                    if (module.hasOwnProperty('main')) {
                        module.main();
                    } else {
                        throw new Error('Module ' + path + ' does not implement main() method.');
                    }
                });
            }));

    })
    // Caching all component's templates files (.html/.css)
    .then(function () {
        return Promise.all(
            karmaFiles
            .filter(function (filename) {
                var template = filename.endsWith('.html');
                var css = filename.endsWith('.css');
                return template || css;
            })
            .map(function (filename) {
                return new Promise(function(resolve, reject) {
                    $.ajax({
                        type: 'GET',
                        url: filename,
                        dataType: 'text',
                        success: function (contents) {
                            filename = filename.replace("/base", "..");
                            window.$templateCache[filename] = contents;
                            resolve();
                        }
                    })
                })
            })
        )
    })
    .then(function () {
      __karma__.start();
  }, function (error) {
      console.error(error.stack || error);
      __karma__.start();
  });

// Filter spec files
function onlySpecFiles(path) {
    return /\.spec\.js$/.test(path);
}

// Normalize paths to module names.
function file2moduleName(filePath) {
    return filePath.replace(/\\/g, '/')
      .replace(/^\/base\//, '');
}

So far so good but i started getting problems on the following spec: 到目前为止这么好,但我开始遇到以下规范的问题:

loginPage.spec.js loginPage.spec.js

[...]

import { LoginPageComponent } from "loginPage";

import { RESOURCE_CACHE_PROVIDER } from "@angular/platform-browser-dynamic";


@Component({
    selector: "loginpage-host",
    template: "<loginPage></loginPage>"
})
export class LoginPageHostComponent {
    @ViewChild(LoginPageComponent)
    public loginPageComponent;
}

export function main() {
    describe('LoginPageComponent', () => {

        beforeEach(()  => {
            TestBed.configureTestingModule({
                imports: [RouterTestingModule.withRoutes([]),CommonModule, HttpModule, CoreModule, ComponentsModule, GlobalizationModule],
                declarations: [LoginPageHostComponent, LoginPageComponent],
                providers: [
                    MockBackend,
                    BaseRequestOptions,
                    {
                        provide: AuthHttp,
                        useFactory: (backend: ConnectionBackend, options: BaseRequestOptions) => new Http(backend, options),
                        deps: [MockBackend, BaseRequestOptions]
                    },
                    {
                        provide: Http,
                        useFactory: (backend: ConnectionBackend, options: BaseRequestOptions) => new Http(backend, options),
                        deps: [MockBackend, BaseRequestOptions]
                    },
                    {
                        provide: Configuration,
                        useFactory: () => new Configuration()
                    }
                ]
            })

             // TestBed.configureCompiler({
             //     providers: [RESOURCE_CACHE_PROVIDER]
             // });
        });

        it('should work',
            fakeAsync(() => {
                TestBed
                    .compileComponents()
                    .then(() => {
                        let fixture = TestBed.createComponent(LoginPageHostComponent);

                        let logPageHostComponentInstance = fixture.debugElement.componentInstance;
                        expect(logPageHostComponentInstance).toEqual(jasmine.any(LoginPageHostComponent));
                        expect(logPageHostComponentInstance.loginPageComponent).toEqual(jasmine.any(LoginPageComponent));
                        fixture.destroy();
                        discardPeriodicTasks(); 
                    });
            }));
    });
}

On SRC i get this error: 在SRC上,我收到此错误:

Chrome 56.0.2924 (Windows 10 0.0.0) LoginPageComponent should work FAILED Error: Cannot make XHRs from within a fake async test. Chrome 56.0.2924(Windows 10 0.0.0)LoginPageComponent应该工作失败错误:无法在假异步测试中制作XHR。

If i manually provide the RESOURCE_CACHED_PROVIDER to the spec it works: 如果我手动提供RESOURCE_CACHED_PROVIDER它的工作原理:

TestBed.configureCompiler({
      providers: [RESOURCE_CACHE_PROVIDER]
});

but it fails on DIST due to the fact that there's no cached template to load for loginPage. 但它在DIST上失败,因为没有为loginPage加载缓存模板。

See: Angular2 tests and RESOURCE_CACHE_PROVIDER global 请参阅: Angular2测试和RESOURCE_CACHE_PROVIDER全局

We have found a solution but not based on Angular provider. 我们找到了一个解决方案但不是基于Angular提供商。

We developed a simple karma preprocessor just for test as: 我们开发了一个简单的业力预处理器,仅用于测试:

  preprocessors: {
            "**/*.component.js": ["generic"]
        },

Then preprocessor just uses gulp-inline-ng2-template parser 然后预处理器只使用gulp-inline-ng2-template解析器

genericPreprocessor: {
            rules: [{
                process: function (content, file, done, log) {
                    // Prepare content for parser
                    file.contents = new Buffer(content);
                    // Every file has a parser
                    var parse = require('gulp-inline-ng2-template/parser')(file, { base: "packages/", useRelativePaths: false });
                    // Call real parse function
                    parse(function (err, contents) {
                        // Callback with content with template and style inline
                        done(contents);
                    });
                }
            }]
        },

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM