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

时间:2017-03-01 08:43:36

标签: unit-testing angular

我正在处理在不同环境下进行测试的一些问题:

  • SRC :使用.js和.html / .css模板文件的未分类组件
  • DIST :缩小的组件(仅限.js,无模板)

我做了两个不同的karma-conf和karma-test-shim,一个用于SRC,另一个用于DIST。 在SRC中,因为我主要在fakeAsync上下文中对组件执行测试,所以我在karma的启动时缓存我的所有模板和.css,如下面的karma-test-shim所示,以避免XHR错误。

果报测试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\//, '');
}

到目前为止一直很好,但我开始在以下规范中遇到问题:

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(); 
                    });
            }));
    });
}

在SRC上我收到此错误:

  

Chrome 56.0.2924(Windows 10 0.0.0)LoginPageComponent应该可以使用   FAILED错误:无法在假异步测试中制作XHR。

如果我手动将RESOURCE_CACHED_PROVIDER提供给它可以运行的规范:

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

但它在DIST上失败,因为没有为loginPage加载缓存模板。

1 个答案:

答案 0 :(得分:0)

请参阅:Angular2 tests and RESOURCE_CACHE_PROVIDER global

我们找到了一个解决方案,但不是基于Angular提供商。

我们开发了一个简单的业力预处理器,仅用于测试:

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

然后预处理器只使用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);
                    });
                }
            }]
        },