![](/img/trans.png)
[英]Angular/ Protractor E2E Test fails when run in Azure DevOps Pipeline. Passes locally
[英]Running Angular tests in GitHub Actions fails when reading inner text (passes locally)
我有一个 GitHub 操作工作流,它为 Angular 项目运行 Karma。 当测试尝试读取本机元素的“innerText”时。 抛出错误“TypeError: Cannot read properties of null (reading 'innerText')”,我认为这是因为查询选择器无法找到元素。 但是,测试在本地通过。 此外,还有其他在虚拟环境中传递的查询选择器测试。
HTML:
<mat-tab-group>
<mat-tab>
<ng-template mat-tab-label>
<mat-icon
[matTooltipDisabled]="(isWeb | async)!.matches"
[matTooltipShowDelay]="0"
matTooltip="Membership"
matTooltipPosition="after"
>groups
</mat-icon>
<mat-label *ngIf="(isWeb | async)?.matches" class="tab-mat-label">Membership</mat-label>
</ng-template>
Content 1
</mat-tab>
<mat-tab>
<ng-template mat-tab-label>
<mat-icon
[matTooltipDisabled]="(isWeb | async)!.matches"
[matTooltipShowDelay]="0"
matTooltip="Rosters"
matTooltipPosition="after">calendar_month
</mat-icon>
<mat-label *ngIf="(isWeb | async)?.matches" class="tab-mat-label">Rosters</mat-label>
</ng-template>
Content 2
</mat-tab>
<mat-tab>
<ng-template mat-tab-label>
<mat-icon
[matTooltipDisabled]="(isWeb | async)!.matches"
[matTooltipShowDelay]="0"
matTooltip="Notifications"
matTooltipPosition="after">edit_notifications
</mat-icon>
<mat-label *ngIf="(isWeb | async)?.matches" class="tab-mat-label">Notifications</mat-label>
</ng-template>
Content 3
</mat-tab>
<mat-tab>
<ng-template mat-tab-label>
<mat-icon
[matTooltipDisabled]="(isWeb | async)!.matches"
[matTooltipShowDelay]="0"
matTooltip="Security"
matTooltipPosition="after">shields
</mat-icon>
<mat-label *ngIf="(isWeb | async)?.matches" class="tab-mat-label">Security</mat-label>
</ng-template>
Content 3
</mat-tab>
</mat-tab-group>
组件代码:
import { Component, OnInit } from '@angular/core';
import {BreakpointObserver, Breakpoints, BreakpointState} from "@angular/cdk/layout";
import {Observable} from "rxjs";
@Component({
selector: 'racs-admin',
templateUrl: './admin.component.html',
styleUrls: ['./admin.component.scss']
})
export class AdminComponent implements OnInit {
constructor(private _breakpointObserver: BreakpointObserver) { }
public get isWeb(): Observable<BreakpointState> {
return this._breakpointObserver.observe(Breakpoints.Web);
}
ngOnInit(): void {
}
}
测试代码:
import {AdminComponent} from './admin.component';
import {RacsAdminModule} from "./racs-admin.module";
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
import {BreakpointObserver} from "@angular/cdk/layout";
describe('AdminComponent', () => {
let component: AdminComponent;
let fixture: ComponentFixture<AdminComponent>;
let compiled: any;
const tabLabelIconPairs: { [key: string]: string; } = {
Membership: 'groups',
Rosters: 'calendar_month',
Notifications: 'edit_notifications',
Security: 'shields',
}
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [AdminComponent],
imports: [RacsAdminModule, BrowserAnimationsModule],
providers: [BreakpointObserver]
})
.compileComponents();
fixture = TestBed.createComponent(AdminComponent);
compiled = fixture.nativeElement;
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create and show tabs with labels in Web View', () => {
expect(component).toBeTruthy();
});
it('should show tab labels and icons', function () {
let tabGroup = compiled.querySelector('mat-tab-group');
let tabs: any[] = compiled.querySelectorAll('[role="tab"]');
expect(component).toBeTruthy();
expect(tabGroup).toBeTruthy();
expect(tabs.length).toBe(Object.keys(tabLabelIconPairs).length);
// Check labels and icons for each tab
tabs.forEach((tab: any) => {
const label: string = tab.querySelector('mat-label').innerText;
const icon: string = tab.querySelector('mat-icon').innerText;
expect(label in tabLabelIconPairs).toBeTruthy();
expect(tabLabelIconPairs[label]).toBe(icon)
});
});
});
我认为是与isWeb | async
isWeb | async
。 从外观上看, *ngIf
是唯一可能影响它们被渲染的。 因此,也许您应该先等待异步内容完成,然后再查询它们。 在服务器上部署--prod
可能会增加查询时间,因此在本地它可能会更快地查询并通过测试。
正如Joosep Parts所指出的,问题在于元素渲染方式的异步性。 这是通过创建一个BreakpointObserver
螺柱并对其进行监视来解决的。 当调用 observe 方法时,调用了fixture.detectChange()
并且测试通过了。 请注意,这被包装在一个fixture.wheStable()
块中
观察者螺柱:
export class BreakpointObserverStub {
observe(): BreakpointState {
return {
matches: true,
breakpoints: {
"web": true
}
} as BreakpointState
}
}
测试:
it('Should show the correct tab labels and icons in Web View', waitForAsync(() => {
fixture.whenStable().then(() => {
spyOn(observer, 'observe').and.returnValue(of({
matches: true,
breakpoints: {
"web": true
}
} as BreakpointState));
// Wait for changes and confirm observe was called
fixture.detectChanges();
expect(observer.observe).toHaveBeenCalled();
// Check correct labels and icons
tabs.forEach((tab: any) => {
const label: string = tab.querySelector('mat-label').innerText;
const icon: string = tab.querySelector('mat-icon').innerText;
// Check labels and icons for each tab
expect(label in tabLabelIconPairs).toBeTruthy();
expect(tabLabelIconPairs[label]).toBe(icon)
});
});
}));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.