无法测试 ng-template 中的输入

Posted

技术标签:

【中文标题】无法测试 ng-template 中的输入【英文标题】:Unable to test an input which is in ng-template 【发布时间】:2019-05-18 15:50:59 【问题描述】:

正如标题中所说,我正在尝试测试 ng 模板中的输入。问题是,我无法访问输入。如果我从 ng-template 中取出输入,它可以工作,但我需要在 ng-template 中使用它。

emp.html 的代码来自 primefaces 文档。 链接:https://www.primefaces.org/primeng/#/table过滤版块

emp.html

<ng-template pTemplate="caption">         
 <div style="text-align: right">
  <i class="fa fa-search" style="margin:4px 4px 0 0"></i>
   <input type="text" pInputText size="50" placeholder="Global Filter" 
   (input)="dt.filterGlobal($event.target.value, 'contains')"
   style="width:auto">
 </div>
</ng-template>

emp.component.spec.ts

describe('EmpComponent', () => 
let component: EmpComponent;
let fixture: ComponentFixture<EmpComponent>;

beforeEach(async(() => 
  TestBed.configureTestingModule(
    imports: [SharedModule, HttpClientTestingModule],
    declarations: [ EmpComponent, TestTableComponent ],
    schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA],
    providers: [
      provide: EmpService, useClass: MockEmpService,
    ]
  )
  .compileComponents();
));

beforeEach(() => 
  fixture = TestBed.createComponent(EmpComponent);
  component = fixture.componentInstance;

  fixture.detectChanges();
);

it('should create', () => 
  expect(component).toBeDefined();
);

it('check input', fakeAsync(() => 

  tick();
  fixture.detectChanges();

  const inputElement = 
  fixture.debugElement.query(By.css('input')).nativeElement;// Here it fails

  inputElement.value = 'some value';
  inputElement.dispatchEvent(new Event('input'));

  fixture.whenStable().then(() => 
    fixture.detectChanges();
    expect(inputElement.value).toEqual('some value');
  );  
))

它给出了以下错误:Cannot read property 'nativeElement' of null

【问题讨论】:

你想测试ng-template是否有pTemplate="caption" 不,我想测试 ng-template 中的输入,基本上,给该输入一个值,然后检查该值是否在输入中,问题是我不能如果输入元素在 ng-template 中,则访问它 【参考方案1】:

您可以编写一个 TestComponent 来模拟模板周围的表格(这意味着它具有相同的选择器),它只输出其中的模板。

在您的测试中,您可以像以前一样测试所有内容。

更新 1

只是为了让我之前的意思更清楚一点。下面是一个关于 TestTableComponent 外观的示例。我没有用编辑器写过这个,所以这只是一个例子,可能无法开箱即用,但只是为了让你明白我的意思:

@Component(
 selector: 'p-table',
 template: `<ng-content></ng-content>`
)
class TestTableComponent 
  // I haven't worked with PrimeNG before, not sure whether this type gets exported
  @ContentChildren(PrimeTemplate) templates: QueryList<PrimeTemplate>;

&lt;ng-content&gt;&lt;/ng-content&gt; 应该显示所有 PrimeTemplate 类型的内容子项。不过,我还没有尝试过。可能有必要像 PrimeNG 那样从 PrimeTemplate 元素中获取 templateRef。如果是这种情况,您的 TestTableComponent 将如下所示:

@Component(
 selector: 'p-table',
 template: `<ng-container *ngFor="let template of templates"><ng-container *ngTemplateOutlet="template"></ng-container></ng-container>`
)
class TestTableComponent implements NgAfterContentInit
  // I haven't worked with PrimeNG before, not sure whether this type gets exported
  @ContentChildren(PrimeTemplate) primeTemplates: QueryList<PrimeTemplate>;

  templates: TemplateRef<any>[] = [];

  ngAfterContentInit() 
    this.templates.forEach((item) => 
      this.templates.push(item.template);
    );

查看here 了解有关内容投影的更多详细信息 它可能有助于了解 PrimeNG 本身如何使用内容投影,使用您提供的模板来生成表格here。

更新 2

这是一个stackblitz,它说明了我的意思。我不想添加 PrimeNG 模块,因为我不知道您使用的是哪个模块,并且不需要掌握我所做的事情。因此,我将 PrimeNG 的指令(PrimeTemplate)复制到 stackblitz 中。该指令用于确定所有内容子项。在您的情况下,PrimeNG 组件中的所有 ng 模板都有此指令。

剩下的唯一问题是,PrimeTemplate 是否可以从 PrimeNG 中导入。你需要试试那个。如果 PimeNG 不导出 PrimeTemplate,您可能需要编写自己的指令并将其添加到您要测试的所有模板中。您可以使用自己的指令来收集 ng 模板。这不会那么好,因为您将添加仅用于测试目的的指令。所以我希望 PrimeNG 导出这个指令。

【讨论】:

你的意思是这样的吗? ***.com/questions/40166854/… 是的。我会使用 在 TestComponent 的模板中输出 ViewChilds。所以你可以测试你的输入和文本。稍后我将使用示例 TestComponent 更新我的答案。我没有电脑自动取款机,尝试在手机上编写代码也不是很有趣。 好的,非常感谢。 所以我已经添加了你的代码的第一部分,但错误仍然存​​在,我是否必须在测试部分进行更改?此外,在代码的第二部分中,方法 add 和 .template 在 TemplateRef 类型上无法识别 我为你做了一个stackblitz。我用链接更新了答案。您是否将您的 TestTableComponent 添加到您的 TestBed 的声明中?

以上是关于无法测试 ng-template 中的输入的主要内容,如果未能解决你的问题,请参考以下文章

ng-template中的剑道角度网格列传递数据项

everything无法打开数据库路径

ng-template

PYTHON 中判断大于小于时为啥在判断输入数字大于需要的数字时其之后的代码无法运行?

使用 @ContentChildren() 访问每个 ng-template 名称

在哪里放置检查:Visual Studio中的noarg_temp_created选项?