我的茉莉花单元测试存在一些问题。
我所有的测试,在同一文件中,引发以下错误:
“无法读取未定义的属性'toUpperCase'”
我试图将所有从模块中导入的文件都放入测试文件中,但是我没有成功
.html
<div class="km-btn-group" *ngIf="create">
<button class="km-btn km-btn-cancel" type="button" (click)="delete()">descartar bot</button>
<button *ngIf="botThirdStep?.type?.toUpperCase() == 'FAQ'" class="km-btn km-btn-default" type="button" (click)="cleanStep()">remover
selecionados</button>
<button class="km-btn km-btn-success" type="button" (click)="goToReview()">concluir</button>
</div>
<div class="km-btn-group" *ngIf="!create">
<button class="km-btn km-btn-cancel" type="button" (click)="cancel()">cancelar</button>
<!-- <button *ngIf="botThirdStep?.type?.toUpperCase() == 'FAQ'" class="km-btn km-btn-default" type="button" (click)="reset()">limpar
alterações</button> -->
<button class="km-btn km-btn-success" type="button" (click)="saveChanges()">salvar</button>
</div>
<card-structured-dialog *ngIf="botThirdStep?.type?.toUpperCase() == 'STRUCTURED'" class="km-structured-dialog"></card-structured-dialog>
<div *ngIf="botThirdStep?.type?.toUpperCase() != 'STRUCTURED'" class="row no-gutters km-newbot-wrap">
<div class="col-md-4">
<div class="card km-card km-newbot-card">
<h2 class="km-newbot-card-title">Assuntos Selecionados</h2>
<app-loading *ngIf="loading"></app-loading>
<ul *ngIf="!loading" class="list-unstyled km-newbot-dragarea" dragula="SUBJECTS" [(dragulaModel)]='selected'>
<li *ngFor="let subject of selected">
<app-bot-subject [botSubjects]="subject" remove="true" (backToAvailable)="goBackToAvailable(subject.id)"></app-bot-subject>
</li>
</ul>
</div>
</div>
<div class="col-md-8">
<div class="card km-card km-newbot-card">
<div class="row km-newbot-card-title">
<div class="col-md-5 col-lg-4">
<h2>Assuntos Disponíveis</h2>
</div>
<div *ngIf="!loading" class="col-md-7 col-lg-8 km-newbot-search">
<app-input name="search" placeholder="Qual Assunto você procura?" [value]="filter" (bindValue)="debounce.next($event)"
urlimg="../../../assets/images/search.png">
</app-input>
</div>
</div>
<app-loading *ngIf="loading"></app-loading>
<ul *ngIf="!loading" class="row list-unstyled km-newbot-droparea" dragula="SUBJECTS" [(dragulaModel)]='available'>
<li class="col-xs-12 col-sm-6" *ngFor="let subject of available | filterByParam: 'name':filter | orderByParam: 'name'">
<app-bot-subject [botSubjects]="subject"></app-bot-subject>
</li>
</ul>
</div>
</div>
</div><div class="km-btn-group" *ngIf="create">
<button class="km-btn km-btn-cancel" type="button" (click)="delete()">descartar bot</button>
<button *ngIf="botThirdStep?.type?.toUpperCase() == 'FAQ'" class="km-btn km-btn-default" type="button" (click)="cleanStep()">remover
selecionados</button>
<button class="km-btn km-btn-success" type="button" (click)="goToReview()">concluir</button>
</div>
<div class="km-btn-group" *ngIf="!create">
<button class="km-btn km-btn-cancel" type="button" (click)="cancel()">cancelar</button>
<!-- <button *ngIf="botThirdStep?.type?.toUpperCase() == 'FAQ'" class="km-btn km-btn-default" type="button" (click)="reset()">limpar
alterações</button> -->
<button class="km-btn km-btn-success" type="button" (click)="saveChanges()">salvar</button>
</div>
<card-structured-dialog *ngIf="botThirdStep?.type?.toUpperCase() == 'STRUCTURED'" class="km-structured-dialog"></card-structured-dialog>
<div *ngIf="botThirdStep?.type?.toUpperCase() != 'STRUCTURED'" class="row no-gutters km-newbot-wrap">
<div class="col-md-4">
<div class="card km-card km-newbot-card">
<h2 class="km-newbot-card-title">Assuntos Selecionados</h2>
<app-loading *ngIf="loading"></app-loading>
<ul *ngIf="!loading" class="list-unstyled km-newbot-dragarea" dragula="SUBJECTS" [(dragulaModel)]='selected'>
<li *ngFor="let subject of selected">
<app-bot-subject [botSubjects]="subject" remove="true" (backToAvailable)="goBackToAvailable(subject.id)"></app-bot-subject>
</li>
</ul>
</div>
</div>
<div class="col-md-8">
<div class="card km-card km-newbot-card">
<div class="row km-newbot-card-title">
<div class="col-md-5 col-lg-4">
<h2>Assuntos Disponíveis</h2>
</div>
<div *ngIf="!loading" class="col-md-7 col-lg-8 km-newbot-search">
<app-input name="search" placeholder="Qual Assunto você procura?" [value]="filter" (bindValue)="debounce.next($event)"
urlimg="../../../assets/images/search.png">
</app-input>
</div>
</div>
<app-loading *ngIf="loading"></app-loading>
<ul *ngIf="!loading" class="row list-unstyled km-newbot-droparea" dragula="SUBJECTS" [(dragulaModel)]='available'>
<li class="col-xs-12 col-sm-6" *ngFor="let subject of available | filterByParam: 'name':filter | orderByParam: 'name'">
<app-bot-subject [botSubjects]="subject"></app-bot-subject>
</li>
</ul>
</div>
</div>
</div>
component.ts
@Component({
selector: 'app-step-third',
templateUrl: './step-third.component.html',
styleUrls: ['./step-third.component.scss']
})
export class StepThirdComponent implements OnInit, OnDestroy {
private loading = false;
private filter = '';
private debounce: Subject<string> = new Subject<string>();
private subs = new Subscription();
private compareAvailable: BotSubject[] = [];
private compareSelected: BotSubject[] = [];
@Input() autosave = false;
@Input() create = true;
@Input() botThirdStep: Bot;
@Input() available: BotSubject[] = [];
@Input() selected: BotSubject[] = [];
@Output() relodSubjects: EventEmitter<any> = new EventEmitter();
@Output() deleteDraft: EventEmitter<any> = new EventEmitter();
@Output() goBack: EventEmitter<any> = new EventEmitter();
private user: UserModel;
private userColaboratorInformation: UserColaboratorInformation
constructor(
private router: Router,
private dragulaService: DragulaService,
private subjectService: BotSubjectService
) {
this.user = new UserModel();
this.user = JSON.parse(window.localStorage.getItem('userLogged'));
this.userColaboratorInformation = new UserColaboratorInformation();
this.userColaboratorInformation = JSON.parse(window.localStorage.getItem('userColaboratorInformation'));
}
ngOnInit(): void {
if ((this.botThirdStep.type.toUpperCase() === 'STRUCTURED') && !(this.selected.length === 0))
this.cleanStep()
window.scrollTo(0, 0);
this.debounce
.subscribe(filter => this.filter = filter);
if (this.autosave) {
this.subs.add(this.dragulaService.dropModel('SUBJECTS')
.subscribe(({ sourceModel, targetModel, item }) => {
if (sourceModel !== targetModel) {
this.updateSubject(this.botThirdStep._id, item.id, false);
}
})
);
} else {
this.compareAvailable = this.available;
this.compareSelected = this.selected;
}
}
ngOnDestroy(): void {
this.debounce.unsubscribe();
this.subs.unsubscribe();
}
public updateSubject(botId: string, subjectId: string, reload: boolean): void {
this.loading = true;
const data: changeSubject = {
userName: this.userColaboratorInformation.employeeName,
userRole: this.userColaboratorInformation.occupationName,
};
this.subjectService.updateSubject(botId, subjectId, data)
// .map((res: Response) => (res.json()))
.subscribe((res) => {
this.loading = false;
if (reload) {
this.relodSubjects.emit();
}
}, (err) => {
this.loading = false;
if (reload) {
this.relodSubjects.emit();
}
});
}
public cleanStep(): void {
if (this.autosave) {
this.selected.forEach(subject => {
this.updateSubject(this.botThirdStep._id, subject.id, true);
});
}
}
public delete(): void {
this.deleteDraft.emit();
}
public goToReview(): void {
this.router.navigateByUrl('/bot/review-draft/' + this.botThirdStep._id);
}
public goBackToAvailable(subjectId): void {
if (this.autosave) {
this.updateSubject(this.botThirdStep._id, subjectId, true);
} else {
this.loading = true;
this.filter = ' ';
let auxIndex = -1;
let auxObj: BotSubject;
this.selected.forEach((element, index) => {
if (element.id === subjectId) {
auxIndex = index;
auxObj = element;
}
});
if (auxIndex >= 0) {
setTimeout(() => {
this.selected.splice(auxIndex, 1);
this.available.push(auxObj);
this.filter = null;
this.loading = false;
}, 100);
}
}
}
public saveChanges(): void {
this.loading = true;
let sendToChange: BotSubject[];
sendToChange = this.objectsInBoth(this.compareAvailable, this.selected).concat(this.objectsInBoth(this.compareSelected, this.available));
if (sendToChange.length > 0) {
this.subjectService.swapSelected(this.botThirdStep._id, this.jsonWithOnlySubjectId(sendToChange))
// .map((res: Response) => (res.json()))
.subscribe((res) => {
this.loading = false;
this.goBack.emit();
}, (err) => {
this.loading = false;
alert('Ocorreu algum erro ao tentar salvar as alterações. Por favor tente novamente');
});
} else {
this.goBack.emit();
}
}
public objectsInBoth(mainArray, compareArray): BotSubject[] {
const hasInBoth = [];
mainArray.forEach(obj => {
if (compareArray.includes(obj)) {
hasInBoth.push(obj);
}
});
return hasInBoth;
}
public jsonWithOnlySubjectId(array: BotSubject[]) {
const normalizeArray = [];
for (const object of array) {
normalizeArray.push({ 'id': object.id });
}
const json = {
'userName': 'Maycon pacheco',
'userRole': 'Back',
'subjects': normalizeArray
};
return json;
}
public cancel(): void {
this.goBack.emit();
}
}
.spec
class MockDragulaService {
dropModel = jasmine.createSpy('dropModel').and.returnValue(
Observable.of({
name: '',
el: undefined,
target: undefined,
source: undefined,
sibling: undefined,
item: { id: 111 },
sourceModel: [1],
targetModel: [2],
sourceIndex: 0,
targetIndex: 0
})
);
}
class MockBotSubjectService {
updateSubject = jasmine.createSpy('updateSubject').and.returnValue(Observable.of({ attr: 'test' }));
}
fdescribe('StepThirdComponent', () => {
let component: StepThirdComponent;
let fixture: ComponentFixture<StepThirdComponent>;
const router = {
navigateByUrl: jasmine.createSpy('navigateByUrl'), // to spy on the url that has been routed
};
let dragulaServiceSpy: DragulaService;
let botSubjectServiceSpy: BotSubjectService;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
],
declarations: [
StepThirdComponent,
// SubjectStubComponent,
// InputStubComponent,
FilterByParamPipe,
OrderByParamPipe,
],
schemas: [
NO_ERRORS_SCHEMA
],
providers: [
{ provide: Router, useValue: router },
{ provide: DragulaService, useClass: MockDragulaService },
{ provide: BotSubjectService, useClass: MockBotSubjectService },
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(StepThirdComponent);
component = fixture.componentInstance;
component.botThirdStep = { _id: 'test' };
fixture.detectChanges();
dragulaServiceSpy = fixture.debugElement.injector.get(DragulaService);
botSubjectServiceSpy = fixture.debugElement.injector.get(BotSubjectService);
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should test updateSubject called on ngOnInit if autosave is true', () => {
component['debounce'] = new Subject<string>();
component['subs'] = new Subscription();
component['autosave'] = true;
component.ngOnInit();
expect(botSubjectServiceSpy.updateSubject).toHaveBeenCalled();
});
it('should test ngOnDestroy', () => {
spyOn(component['debounce'], 'unsubscribe');
spyOn(component['subs'], 'unsubscribe');
component.ngOnDestroy();
expect(component['debounce'].unsubscribe).toHaveBeenCalled();
expect(component['subs'].unsubscribe).toHaveBeenCalled();
});
describe('should test updateSubject', () => {
it('should test updateSubject for reload = false', () => {
const mockData: changeSubject = {
userName: 'Iara Nascimento',
userRole: 'Front End'
};
component.updateSubject('botId', 'subjectId', false);
expect(component['loading']).toBe(false);
expect(botSubjectServiceSpy.updateSubject).toHaveBeenCalledWith('botId', 'subjectId', mockData);
});
});
it('should test cleanStep', () => {
botSubjectServiceSpy.updateSubject = jasmine.createSpy('updateSubject').and.returnValue(Observable.of({ attr: 'test' }));
component.botThirdStep._id = 'testId1';
component.selected = [
{ id: 'testId2', name: '', userName: '', userRole: '', subjectType: '', subjectChannel: '', subjectArea: '' },
{ id: 'testId3', name: '', userName: '', userRole: '', subjectType: '', subjectChannel: '', subjectArea: '' }
];
component['autosave'] = true;
component.cleanStep();
expect(botSubjectServiceSpy.updateSubject).toHaveBeenCalledTimes(2);
});
it('should test cleanStep else case', () => {
component['autosave'] = false;
component.cleanStep();
});
it('should test delete', () => {
spyOn(component['deleteDraft'], 'emit');
component.delete();
expect(component['deleteDraft'].emit).toHaveBeenCalled();
});
it('should test goToReview', () => {
component.botThirdStep._id = 'testId1';
component.goToReview();
expect(router.navigateByUrl).toHaveBeenCalledWith('/bot/review-draft/testId1');
});
it('should test goBackToAvailable', () => {
spyOn(component, 'updateSubject');
component.botThirdStep._id = 'testId1';
component['autosave'] = true;
component.goBackToAvailable('testId2');
expect(component.updateSubject).toHaveBeenCalledWith('testId1', 'testId2', true);
});
it('should test goBackToAvailable else case with an array with 1 or more lenght', () => {
// tslint:disable-next-line:max-line-length
const selected: BotSubject[] = [{ id: '1234', name: 'Cartão', userName: 'Jonathan', userRole: 'Jonathan', subjectType: 'FAQ', subjectChannel: 'Mobile', subjectArea: 'Cartões' }, { id: '4321', name: 'Cartão', userName: 'Jonathan', userRole: 'Jonathan', subjectType: 'FAQ', subjectChannel: 'Mobile', subjectArea: 'Cartões' }, { id: '1234', name: 'Cartão', userName: 'Jonathan', userRole: 'Jonathan', subjectType: 'FAQ', subjectChannel: 'Mobile', subjectArea: 'Cartões' }];
component.selected = selected;
component['autosave'] = false;
component.goBackToAvailable('1234');
});
});
我没想到所有这些问题。 拜托,我尝试了很多没有成功的事情,请帮助我。