16

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

我正在使用 Chutzpah 测试适配器 2.5 和 AngularJS 1.2.0-r.2。

我得到错误:

意外请求:GET myApp/directives/template.html

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

我发现了一些不同的解决方法:

  1. 手动使用 XMLHttpRequest 导入模板。
  2. 使用像 Grunt 这样的实用程序将模板内联到指令的 JS 代码中。
  3. $httpBackend.when('GET', 'myApp/directives/template.html').passThrough()- 这仅适用于 e2e 测试,不适用于单元测试。
  4. 将模板直接放入测试代码中。

这些选项都没有让我特别满意。我希望能够让指令透明地加载其模板,以便我可以将其作为组件进行测试。有没有办法让这个场景工作?

示例代码:

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

模板.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!");
    });
}
4

6 回答 6

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'));
于 2015-02-17T04:10:28.130 回答
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 first 在模板缓存中查找并且不进行 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

于 2015-03-05T18:21:18.347 回答
2

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

第 1 步:使用 ng-html2js 插件将 Angular 模板编译成 javascript 第 2 步:像前面回答的那样做,并将其作为一个模块包含在你的每个之前。

ng-html2js 还允许您执行它期望的“url”的自定义操作,如果您的测试目录与您的应用程序目录不同,这可能会有所帮助。

于 2013-12-11T23:17:03.540 回答
0

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

https://vimeo.com/90876119

于 2014-06-10T08:13:03.763 回答
0

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

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

(来自我的代码)

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

然后在您的测试中,注入 $templateCache 并通过 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 支持。

于 2015-09-03T09:09:12.943 回答
-1

确保在创建模板之前将其包含在注入器中。所以试试,

beforeEach(module('myApp/directives/template.html');
于 2013-11-21T15:19:50.250 回答