如何在Chutzpah的无头浏览器中使用templateUrl测试指令

时间:2013-10-11 08:29:43

标签: angularjs jasmine chutzpah

有谁知道如何让像Chutzpah的Visual Studio测试适配器这样的无头浏览器允许指令访问其.html模板文件? Chutzpah使用PhantomJS作为无头浏览器,似乎限制了我的选择。

我正在使用Chutzpah Test Adapter 2.5和AngularJS 1.2.0-r.2。

我收到错误:

  

意外请求:获取myApp / directives / template.html

这是由Angular尝试使用$ http服务访问我的指令模板引起的。

我找到了一些不同的解决方法:

  1. Manually using XMLHttpRequest to import the templates.
  2. Using a utility like Grunt to inline the template into your directive's JS code.
  3. $httpBackend.when('GET', 'myApp/directives/template.html').passThrough() - 这仅适用于e2e测试,而不适用于单元测试。
  4. Put the template directly into the test code.
  5. 这些选项都不能让我满意。我希望能够让指令透明地加载它的模板,这样我就可以将它作为一个组件进行测试。有没有办法让这个场景有效?

    示例代码:

    angular.module('myDirective', []).directive('myDirective', function() {
        return {
            restrict: 'E',
            transclude: true,
            templateUrl: 'myApp/directives/template.html',
            // Some other options, omitted for brevity.
        };
    });
    

    template.html:

    <div><div ng-transclude></div></div>
    

    茉莉花测试示例:

    describe('myDirective', function() {
        // Assign $scope using inject(), load module etc.
        // Insert workaround for $httpBackend loading my templateUrl here.
        it('should transclude content', function() {
            var element = $compile("<my-directive>Look Mom, I'm in my directive!</my-directive>")($scope);
            $scope.$digest();
    
            expect(element.text().trim()).toBe("Look Mom, I'm in my directive!");
        });
    }
    

6 个答案:

答案 0 :(得分:5)

我设法使用Chutzpah的编译选项让它工作。我将karma-ng-html2js-preprocessor移植到PowerShell脚本中,然后从Chutzpah调用它将HTML编译成JS文件。

在chutzpah.json设置文件旁边添加了PowerShell脚本(以下脚本包含对PreprendPrefix和StripSuffix的未经测试的支持)

# PowerShell port of https://github.com/karma-runner/karma-ng-html2js-preprocessor

Param (
    [parameter(Mandatory=$true)] [string] $Path,
    [string] $Module = '',
    [string] $StripPrefix = '',
    [string] $PrependPrefix = '',
    [string] $StripSuffix = ''
)

Function EscapeContent($content) {
    $content -replace "\\", "\\\\" -replace "'", "\'" -replace  "`r?`n", "\n' +`n    '"
}

Function Rename($fileName) {
    "$PrependPrefix" + ("$fileName" -replace "$StripPrefix", '' -replace "$StripSuffix", '' -replace "\\", "/")
}

$Template = If ("$Module" -eq "") {
    "angular.module('{0}', []).run(function(`$templateCache) {{`n" `
      + "  `$templateCache.put('{0}',`n    '{2}');`n" `
      + "}});`n"
  } Else {
    "(function(module) {{`n" `
        + "try {{`n" `
        + "  module = angular.module('{1}');`n" `
        + "}} catch (e) {{`n" `
        + "  module = angular.module('{1}', []);`n" `
        + "}}`n" `
        + "module.run(function(`$templateCache) {{`n" `
        + "  `$templateCache.put('{0}',`n    '{2}');`n" `
        + "}});`n" `
        + "}})();`n"
  }

Get-ChildItem $Path -Recurse -Filter *.html | Foreach-Object {
    $content = Get-Content $_.FullName | Out-String
    $content = EscapeContent $content
    $fileName = Rename "$($_.FullName)"
    ("$Template" -f "$fileName", "$Module", "$content") | Set-Content "$($_.FullName).js"
}

编译配置添加到chutzpah.json并将“已编译”的JS文件添加到References(可以从测试文件中添加引用,但我更喜欢使用chutzpah.json来管理所有引用)

{
    "References": [
        { "Path": "./path/to/templates/", "Include": "*.html.js" },
    ],
    "Compile": {
        "Extensions": [".html"],
        "ExtensionsWithNoOutput": [".html.js"],
        "SourceDirectory": "./path/to/templates",
        "OutDirectory": "./path/to/templates",
        "Executable": "%powershellexe%",
        "Arguments": "-NoProfile %chutzpahsettingsdir%\\chutzpah-ng-html2js-compiler.ps1 -Path '/path/to/templates/' -Module 'templates' -StripPrefix '.+(?=\\\\templates)'"
    }
}

在测试文件中,加载模块,在我的情况下,它们都在“模板”模块中

beforeEach(module('templates'));
// or alternatively
beforeEach(module('/path/to/templates/foo.html'));

答案 1 :(得分:5)

您可以使用Chutzpah的“模板”参考

http://matthewmanela.com/blog/chutzpah-2-4-2/

/// <template path="../../MvcAngularJs1_3/ScriptsApp/directives/Templates/testTemplate.html" />
/// <reference path="../../mvcangularjs1_3/scripts/jquery-2.1.1.js" />
/// <reference path="../../mvcangularjs1_3/scripts/angular.js" />
/// <reference path="../../mvcangularjs1_3/scripts/angular-mocks.js" />
...

在引用下,然后Chutzpah直接在测试HTML文件中包含HTML。我已经为我的模板提供了一个独特的css类来查找它们并将它们手工放入模板AngularJS模板缓存中。

我的HTML模板

<div class="row templateTestTemplate">
   <div class="col-lg-12">
       <h1>Tempalte Test</h1>
   </div>
</div>

指令

angular.module("testTemplateDirective", [])
    .directive("testTemplate", function() {
        return {
           restrict: 'A',
           replace: true,
           templateUrl: 'ScriptsApp/directives/Templates/testTemplate.html'
       }
});

在我的单元中测试我使用jQuery查找模板并将其添加到模板缓存中。 Angular第一次在模板缓存中查找并且不进行HTTP调用。

var template = jQuery(".templateTestTemplate")[0].outerHTML;
$templateCache.put("ScriptsApp/directives/Templates/testTemplate.html", template);

到目前为止效果很好,但只适用于chutzpah,当您使用Resharper运行此测试时,测试将失败,因为resharper不会将模板复制到测试HTML中。

我还在Chutzpah GitHub页面上打开一个请求,用脚本标签和ID包围HTML,这样您就不需要扩展模板了 https://github.com/mmanela/chutzpah/issues/330

答案 2 :(得分:2)

我有一个类似的问题试图测试我的指令。我找到了使用该模式的解决方案 https://github.com/vojtajina/ng-directive-testing

步骤1:使用ng-html2js插件将角度模板编译成javascript 第2步:像之前的回答一样回答,并将其作为模块包含在您之前的每个模块中。

ng-html2js还允许您对&#39; url&#39;进行自定义操作。如果您的测试目录与您的app目录不同,它预计哪些可能会有所帮助。

答案 3 :(得分:0)

使用ng-html2js这是一个很棒的视频,展示如何让它全部设置以测试templateUrl指令。我不确定这对于Chutzpah有多适用,因为这是一个Karma的例子,但它可能会让你朝着正确的方向前进!

https://vimeo.com/90876119

答案 4 :(得分:0)

您可以使用jasmine-jquery将文件或http中的内容加载到$ templateCache中。它在Chutzpah没有任何修改。

首先将jasmine-jquery添加到您的项目并添加chutzpah.json参考:

(来自我的代码)

"References" : [
    {"Path" : "vendor/jasmine-jquery-2.1.0.js"}
]

然后在你的测试中,注入$ templateCache并加载&#34; live&#34;内容通过jasmine.getFixtures()如下:

beforeEach(inject(function ($templateCache) {
    //Loading template from live develop server
    jasmine.getFixtures().fixturesPath = "http://localhost:47152";
    var templateUrl = "/myApp/directives/template.html";
    $templateCache.put(templateUrl, jasmine.getFixtures()  
        .getFixtureHtml_(templateUrl));
}));

如果您通过http加载并使用Chrome进行测试,则必须在服务器上添加CORS支持。

答案 5 :(得分:-1)

确保在创建之前将模板包含在进样器中。所以试试,

beforeEach(module('myApp/directives/template.html');