Angular Unit testing - Test case is not passing with mocking child component - unit-testing

When I try to pass child component #Input() Property from parent it's throwing error.
Child component input property is undefined always.
Please check this error:
Expected undefined to equal Object
#Component({
selector: "ce-customer-profile-image",
})
class MockCECustomerProfileImageComponent
{
#Input() customer;
}
describe("CustomerProfileInfo Component", () => {
let component: CustomerProfileInfoComponent;
let mockComponent: MockCECustomerProfileImageComponent;
let fixture: ComponentFixture<CustomerProfileInfoComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [CustomerProfileInfoComponent,MockCECustomerProfileImageComponent],
imports: [],providers: [],schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
.overrideModule(BrowserDynamicTestingModule, {})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(CustomerProfileInfoComponent);
component = fixture.debugElement.componentInstance;
component.customer = {
Email: "vk#test.com",
Phone: "(123) 456-7890",
FirstName: "testV",
LastName: "testK",
CustomerId: null,
CustomerAddress: null,
};
component.customerAddress = null;
fixture.detectChanges();
});
}));
it("CustomerProfileInfoComponent for anonymous customer", () => {
fixture.detectChanges();
mockComponent = TestBed.createComponent(MockCECustomerProfileImageComponent)
.debugElement.componentInstance;
expect(mockComponent.customer).toEqual(component.customer);
});
});
Please help me if i'm missing something from above snippet.

Related

Testing angular components with dependencies

Hellow. I trying to test a component but i still doind it in the right way and i would like some help. This is the component:
export class ModalLoadingComponent implements OnInit {
#ViewChild('loading') loading: LoadingComponent;
constructor(public dialogRef: MatDialogRef<ModalLoadingComponent>, #Inject(MAT_DIALOG_DATA) public data: any) { }
ngOnInit(): void {}
close() {
this.dialogRef.close();
}
and this is my test
fdescribe('CardsComponent', () => {
let component: ModalLoadingComponent;
let fixture: ComponentFixture<ModalLoadingComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ModalLoadingComponent],
providers: [MatDialogRef],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ModalLoadingComponent);
component = fixture.componentInstance;
fixture.whenStable();
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

Nestjs mongoose unit test: TypeError: <functionName> is not a function

according to this github repo we want to test a user sample
consider this test file :
const mockUser = (
phone = '9189993388',
password = 'jack1234',
id = '3458',
): User => ({
phone,
password,
_id: new Schema.Types.ObjectId(id),
});
const mockUserDoc = (mock?: Partial<User>): Partial<IUserDocument> => ({
phone: mock?.phone || '9189993388',
password: mock?.password || 'jack1234',
_id: mock?._id || new Schema.Types.ObjectId('3458'),
});
const userArray = [
mockUser(),
mockUser('Jack', '9364445566', 'jack#gmail.com'),
];
const userDocArray = [
mockUserDoc(),
mockUserDoc({
phone: '9364445566',
password: 'jack1234',
_id: new Schema.Types.ObjectId('342'),
}),
mockUserDoc({
phone: '9364445567',
password: 'mac$',
_id: new Schema.Types.ObjectId('425'),
}),
];
describe('UserRepository', () => {
let repo: UserRepository;
let model: Model<IUserDocument>;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
UserRepository,
{
provide: getModelToken('User'),
// notice that only the functions we call from the model are mocked
useValue: {
new: jest.fn().mockResolvedValue(mockUser()),
constructor: jest.fn().mockResolvedValue(mockUser()),
find: jest.fn(),
findOne: jest.fn(),
update: jest.fn(),
create: jest.fn(),
remove: jest.fn(),
exec: jest.fn(),
},
},
],
}).compile();
repo = module.get<UserRepository>(UserRepository);
model = module.get<Model<IUserDocument>>(getModelToken('User'));
});
it('should be defined', () => {
expect(repo).toBeDefined();
});
afterEach(() => {
jest.clearAllMocks();
});
it('should return all users', async () => {
jest.spyOn(model, 'find').mockReturnValue({
exec: jest.fn().mockResolvedValueOnce(userDocArray),
} as any);
const users = await repo.findAll({});
expect(users).toEqual(userArray);
});
it('should getOne by id', async () => {
const userId = '324';
jest.spyOn(model, 'findOne').mockReturnValueOnce(
createMock<Query<IUserDocument, IUserDocument>>({
exec: jest.fn().mockResolvedValueOnce(
mockUserDoc({
_id: new Schema.Types.ObjectId(userId),
}),
),
}) as any,
);
const findMockUser = mockUser('Tom', userId);
const foundUser = await repo.findById(new Schema.Types.ObjectId(userId));
expect(foundUser).toEqual(findMockUser);
});
and this is the user document file:
export interface IUserDocument extends Document {
_id: Schema.Types.ObjectId;
email?: string;
password: string;
firstName?: string;
lastName?: string;
nationalCode?: string;
phone: string;
address?: string;
avatar?: string;
}
the 1th and 2nd test are passed but the third one throws:
TypeError: this.userModel.findById is not a function
also the interface is extended from mongoose Document, the findById function is not recognized in the test.
this is the github repo available.
so any help will be appreciated.
Notice how in your UserModel mock you don't provide a mock function for findById
{
provide: getModelToken('User'),
// notice that only the functions we call from the model are mocked
useValue: {
new: jest.fn().mockResolvedValue(mockUser()),
constructor: jest.fn().mockResolvedValue(mockUser()),
find: jest.fn(),
findOne: jest.fn(),
update: jest.fn(),
create: jest.fn(),
remove: jest.fn(),
exec: jest.fn(),
findById: jest.fn(), // <-------------- Add this
},
},
There needs to be a findById method in that set of methods that you mock.
by the way, i needed the constructor to be called via new so i preferd to define a mock class like this:
class UserModelMock {
constructor(private data) {}
new = jest.fn().mockResolvedValue(this.data);
save = jest.fn().mockResolvedValue(this.data);
static find = jest.fn().mockResolvedValue(mockUser());
static create = jest.fn().mockResolvedValue(mockUser());
static remove = jest.fn().mockResolvedValueOnce(true);
static exists = jest.fn().mockResolvedValue(false);
static findOne = jest.fn().mockResolvedValue(mockUser());
static findByIdAndUpdate = jest.fn().mockResolvedValue(mockUser());
static findByIdAndDelete = jest.fn().mockReturnThis();
static exec = jest.fn();
static deleteOne = jest.fn().mockResolvedValue(true);
static findById = jest.fn().mockReturnThis();
}

ionic 5 unit test with popover controller

I am trying to spy popover present method in my ionic 5 / angular 11 project but getting an error
Unhandled Promise rejection: Cannot read property 'then' of undefined
Here is unit test code
describe('LoginPage', () => {
let popoverSpy = jasmine.createSpyObj('Popover', ['create', 'present', 'onDidDismiss', 'dismiss']);
let popoverCtrlSpy = jasmine.createSpyObj('PopoverController', ['create']);
popoverCtrlSpy.create.and.callFake(function () {
return popoverSpy;
});
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [LoginPage],
imports: [
IonicModule.forRoot(),
TranslateModule.forChild(),
ComponentsModule,
TranslateModule.forRoot({
loader: { provide: TranslateLoader, useClass: TranslateFakeLoader }
})
],
providers: [{ provide: PopoverController, useValue: popoverCtrlSpy }]
}).compileComponents()
it("check popover preset", () => {
component.openEntitySelection();
fixture.detectChanges();
expect(popoverSpy.present).toHaveBeenCalled()
})
}
private async openEntitySelection() {
let popover = await this.popoverCtrl.create({
component: PopoverPage
});
await popover.present();
popover.onDidDismiss().then((response) => {
//Handle response
})
}
Thanks in advance!
It seems you're not mocking onDidDismiss to return a promise. You also need to use fixture.whenStable or waitForAsync utilities to wait for the promise to be resolved before doing your assertion.
Try this:
describe('LoginPage', () => {
let popoverSpy = jasmine.createSpyObj('Popover', ['create', 'present', 'onDidDismiss', 'dismiss']);
// !! -- Add this line -- !!
// I am mock resolving it to a value of true, you can resolve it to any value
popOverSpy.onDidDismiss.and.returnValue(Promise.resolve(true));
// !! --- !!
let popoverCtrlSpy = jasmine.createSpyObj('PopoverController', ['create']);
popoverCtrlSpy.create.and.callFake(function () {
return popoverSpy;
});
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [LoginPage],
imports: [
IonicModule.forRoot(),
TranslateModule.forChild(),
ComponentsModule,
TranslateModule.forRoot({
loader: { provide: TranslateLoader, useClass: TranslateFakeLoader }
})
],
providers: [{ provide: PopoverController, useValue: popoverCtrlSpy }]
}).compileComponents()
it("check popover preset", (done) => { // add done to let jasmine know you're done
component.openEntitySelection();
fixture.detectChanges();
// you have to wait at least for one fixture.whenStable I am thinking
// because we are returning a promise and we have to ensure that the promises
// have completed before doing our assertion.
fixture.whenStable().then(() => {
expect(popoverSpy.present).toHaveBeenCalled();
done();
});
});
}
private async openEntitySelection() {
let popover = await this.popoverCtrl.create({
component: PopoverPage
});
await popover.present();
popover.onDidDismiss().then((response) => {
//Handle response
})
}
Argument of type 'Promise' is not assignable to parameter of type 'Promise<OverlayEventDetail>'.
Type 'boolean' has no properties in common with type 'OverlayEventDetail'

Why viewChild reference on Angular 8 unit test is undefinded

I am using Angular 8 in my project but I have a problem with the unit-test when I have a component with ViewChild Ref in the unit-test is undefined. any help
I have one component
#Component({
selector: "app-rating-star",
templateUrl: "./rating-star.component.html",
styleUrls: ["./rating-star.component.scss"],
encapsulation: ViewEncapsulation.None
})
export class RatingStarComponent implements OnInit, AfterViewInit {
#ViewChild("measurementBoxStar") measurementBox: ElementRef;
constructor(private _render: Renderer2) {}
ngOnInit() {}
ngAfterViewInit() {
this._render.addClass(this.measurementBox.nativeElement, newClass);
}
}
and my unit-test for this component is
beforeEach(async(() => {
TestBed.configureTestingModule({
schemas: [NO_ERRORS_SCHEMA],
declarations: [RatingStarComponent],
providers: [
{
provide: Renderer2,
useClass: rootRendererMock
}
]
}).compileComponents();
fixture = TestBed.createComponent(RatingStarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it("check Input value for Box in red", () => {
component = fixture.componentInstance;
component.ngOnInit();
fixture.detectChanges();
component.ngAfterViewInit();
expect(component.valueStar).toEqual(1.702);
fixture.detectChanges();
expect(component.measurementBox.nativeElement.querySelector("span").innerText)
.toEqual("1.702");
});
when I run the unit-test, I received this error Error for Jasmine
obviously #ViewChild("measurementBoxStar") measurementBox: ElementRef; is not returning any elements. it may be because *ngIf="valueStar !== -1 && measurementName === ''" evaluates to false in tests. So changing your spec as follows should fix the problem.
it("check Input value for Box in red", () => {
component = fixture.componentInstance;
component.measurementName = "";
fixture.detectChanges();
expect(component.valueStar).toEqual(1.702);
expect(component.measurementBox.nativeElement.querySelector("span").innerText)
.toEqual("1.702");
});

How to handle bootstrap-daterangepicker in angular component unit test?

I am trying to write a unit test of an angular 6 component which is initializing the bootstrap-daterangepicker in the ngAfterViewInit() method. When I run my unit test it gives the following error:
TypeError: $(...).daterangepicker is not a function
this is the code from the actual component(EmployeeComponent):
ngAfterViewInit(): void {
this.initializeDatePicker(this);
}
initializeDatePicker(that: any) {
const start = moment().subtract(7, 'days');
const end = moment();
$('#reportrange').daterangepicker({
startDate: start,
endDate: end,
maxDate: moment(),
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')]
}
}, cb);
cb(start, end);
}
this is the code from my test class:
describe('EmployeeComponent', () => {
let component: EmployeeComponent;
let fixture: ComponentFixture<EmployeeComponent>;
let messageService: NotificationService;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [EmployeeComponent]
})
.overrideComponent(EmployeeComponent, {
set: {
template: '',
providers: [
{ provide: NotificationService, useValue: messageService },
{ provide: ActivatedRoute, useValue: { queryParams: of({ emp: "123" }) } }
]
}
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EmployeeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
You don't need to handle it in your test cases. That component should be initialized in a separate service and you can simply mock that method from the service. In the way you can avoid this error.
let say you move all the code of the initializeDatePicker() in a method in some service let say common-service.ts and you can simply call that service from this method like
this.commonServiceObj.initializeDatePicker();
Now after doing this, you can simply mock initializeDatePicker() from the service object and error should be gone.