尝试在组件测试中使用 `angular_components` 的 `material-dropdown-select`

Trying to use `material-dropdown-select` of `angular_components` in component tests

我正在使用最新的 angular_components-0.6.0-alpha+2 包进行一些测试,因为我想在我的 Angular 应用程序中对我的 <material-dropdown-select> 组件进行单元测试。我基本上想使用 pageloader 包在测试期间单击并打开下拉菜单 select 以单击一个选项。

现在我正在尝试在我的自定义 <div id="my-container">

中安装 <div id="default-acx-overlay-container">(由 angular_components 生成)
    <my-app>Loading...</my-app>
    <div id="my-container"></div>
  </body>
</html>

因为 <div id="default-acx-overlay-container"> 默认情况下是 <body> 的直接子代(我无法使用 pageloader@ByCSS select或)。因此,我重写 overlayContainerParent Angular 提供程序以更改它(注意 providers: 部分):

HtmlElement getOverlayContainerParent(Document doc) =>
    doc.querySelector('#my-container');

@Component(
  selector: 'material-select-demo',
  styleUrls: const ['material_select_demo.css'],
  templateUrl: 'material_select_demo.html',
  directives: const [
    CORE_DIRECTIVES,
    DisplayNameRendererDirective,
    ExampleRendererComponent,
    MaterialCheckboxComponent,
    MaterialDropdownSelectComponent,
    MaterialSelectComponent,
    MaterialSelectItemComponent,
  ],
  providers: const [
    const Provider(overlayContainerParent,
        useFactory: getOverlayContainerParent, deps: const [Document]),
  ],
)
class MaterialSelectDemoComponent {

但是我的问题是,由于某种原因,提供程序没有被覆盖。

我创建了一个示例应用程序,它是 angular_components_example 应用程序的简化版本来演示我的问题。如果你 运行 应用程序,然后打开下拉菜单 select,然后检查 DOM 你会看到 angular_components_example<div id="default-acx-overlay-container"> 没有安装在我的 <div id="my-container"> 如我所愿。这是我的示例应用程序:ben4ever-archive/angular_components_example

你们很亲近。我们通过指定不同的 overlayContainerParent 来做一些非常相似的事情,问题是顶级注射剂不是 overlayContainerParent。依赖树如下所示: OverlayService -> OverlayDomRenderService -> overlayContainerToken -> overlayContainerParent

angular 注入的工作方式是,当请求 OverlayService 的实例时,它将沿着注入树向上移动,直到找到该绑定。然后在树中的那个级别,它将在同一级别和更高级别获得它的依赖项。因此,在这种情况下,您在注入树中指定了一个不同的 overlayContainerParent 实现,因此它永远不会被使用,除非您要求直接注入该令牌。

在我们的测试中,我们的提供商看起来像这样:

const [popupBindings, const Provider(overlayContainerParent, useFactory: getOverlayContainerParent, deps: const [Document])

这将确保覆盖绑定在树中的同一级别指定,并且您的值将覆盖 popupBindings 中的值。

请注意,如果您将其直接放在组件上,您将收到有关嵌套覆盖绑定的日志记录错误。这是因为工程师直接在组件上指定弹出绑定并且无法使用不同的容器进行测试,因为他们无法覆盖测试中的值(非测试绑定在注入树中总是低于我们可以提供的任何地方测试绑定。)

更好的解决方案是使用 angular_test 中的 NgTestBed 并使用 addProviders.

在顶层指定这些提供程序