implement angular testing
This commit is contained in:
@@ -1,16 +1,27 @@
|
|||||||
import {TestBed} from '@angular/core/testing';
|
import {TestBed} from '@angular/core/testing';
|
||||||
import {provideHttpClient, withXhr} from '@angular/common/http';
|
import {provideHttpClient, withXhr} from '@angular/common/http';
|
||||||
|
import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing';
|
||||||
import {AuthService} from './auth-service';
|
import {AuthService} from './auth-service';
|
||||||
|
import {environment} from '../../../environments/environment.development';
|
||||||
|
|
||||||
describe('AuthService', () => {
|
describe('AuthService', () => {
|
||||||
let service: AuthService;
|
let service: AuthService;
|
||||||
|
let httpTesting: HttpTestingController;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
providers: [provideHttpClient(withXhr())]
|
providers: [
|
||||||
|
provideHttpClient(withXhr()),
|
||||||
|
provideHttpClientTesting(),
|
||||||
|
]
|
||||||
});
|
});
|
||||||
service = TestBed.inject(AuthService);
|
service = TestBed.inject(AuthService);
|
||||||
|
httpTesting = TestBed.inject(HttpTestingController);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
httpTesting.verify();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be created', () => {
|
it('should be created', () => {
|
||||||
@@ -42,4 +53,42 @@ describe('AuthService', () => {
|
|||||||
service.signOut();
|
service.signOut();
|
||||||
expect(service.isLoggedIn()).toBeFalse();
|
expect(service.isLoggedIn()).toBeFalse();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should POST to auth/login on login', () => {
|
||||||
|
const credentials = {email: 'test@example.com', password: 'password123'};
|
||||||
|
|
||||||
|
service.login(credentials).subscribe();
|
||||||
|
|
||||||
|
const req = httpTesting.expectOne(`${environment.baseUrl}auth/login`);
|
||||||
|
expect(req.request.method).toBe('POST');
|
||||||
|
expect(req.request.body).toEqual(credentials);
|
||||||
|
req.flush({value: {token: {accessToken: 'access', refreshToken: 'refresh'}}});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should POST to auth/register on register', () => {
|
||||||
|
const request = {username: 'newuser', email: 'new@example.com', password: 'StrongP@ss1'};
|
||||||
|
|
||||||
|
service.register(request).subscribe();
|
||||||
|
|
||||||
|
const req = httpTesting.expectOne(`${environment.baseUrl}auth/register`);
|
||||||
|
expect(req.request.method).toBe('POST');
|
||||||
|
expect(req.request.body).toEqual(request);
|
||||||
|
req.flush({value: 'User registered successfully'});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should POST to auth/refresh-token on renewToken', () => {
|
||||||
|
const refreshRequest = {userId: 1, refreshToken: 'refresh-token'};
|
||||||
|
|
||||||
|
service.renewToken(refreshRequest).subscribe();
|
||||||
|
|
||||||
|
const req = httpTesting.expectOne(`${environment.baseUrl}auth/refresh-token`);
|
||||||
|
expect(req.request.method).toBe('POST');
|
||||||
|
expect(req.request.body).toEqual(refreshRequest);
|
||||||
|
req.flush({value: {accessToken: 'new-access', refreshToken: 'new-refresh'}});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return null for decodedToken when no token', () => {
|
||||||
|
localStorage.removeItem('token');
|
||||||
|
expect(service.decodedToken()).toBeNull();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,27 +1,66 @@
|
|||||||
import {TestBed} from '@angular/core/testing';
|
import {TestBed} from '@angular/core/testing';
|
||||||
|
import {PLATFORM_ID} from '@angular/core';
|
||||||
import {DarkModeService} from './dark-mode.service';
|
import {DarkModeService} from './dark-mode.service';
|
||||||
|
|
||||||
describe('DarkModeService', () => {
|
describe('DarkModeService', () => {
|
||||||
let service: DarkModeService;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({});
|
localStorage.clear();
|
||||||
service = TestBed.inject(DarkModeService);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be created', () => {
|
it('should be created', () => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
const service = TestBed.inject(DarkModeService);
|
||||||
expect(service).toBeTruthy();
|
expect(service).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should toggle from null to dark', () => {
|
it('should toggle from null to dark', () => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
const service = TestBed.inject(DarkModeService);
|
||||||
service.darkModeSignal.set(null);
|
service.darkModeSignal.set(null);
|
||||||
service.updateDarkMode();
|
service.updateDarkMode();
|
||||||
expect(service.darkModeSignal()).toBe('dark');
|
expect(service.darkModeSignal()).toBe('dark');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should toggle from dark to null', () => {
|
it('should toggle from dark to null', () => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
const service = TestBed.inject(DarkModeService);
|
||||||
service.darkModeSignal.set('dark');
|
service.darkModeSignal.set('dark');
|
||||||
service.updateDarkMode();
|
service.updateDarkMode();
|
||||||
expect(service.darkModeSignal()).toBeNull();
|
expect(service.darkModeSignal()).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should start with null when localStorage is empty', () => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
const service = TestBed.inject(DarkModeService);
|
||||||
|
expect(localStorage.getItem('darkModeSignal')).toBeNull();
|
||||||
|
expect(service.darkModeSignal()).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should read initial value from localStorage', () => {
|
||||||
|
localStorage.setItem('darkModeSignal', '"dark"');
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
const service = TestBed.inject(DarkModeService);
|
||||||
|
TestBed.flushEffects();
|
||||||
|
expect(service.darkModeSignal()).toBe('dark');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should persist to localStorage when value changes', () => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
const service = TestBed.inject(DarkModeService);
|
||||||
|
service.darkModeSignal.set('dark');
|
||||||
|
TestBed.flushEffects();
|
||||||
|
expect(localStorage.getItem('darkModeSignal')).toBe('"dark"');
|
||||||
|
service.darkModeSignal.set(null);
|
||||||
|
TestBed.flushEffects();
|
||||||
|
expect(localStorage.getItem('darkModeSignal')).toBe('null');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should do nothing in non-browser platform', () => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [{provide: PLATFORM_ID, useValue: 'server'}]
|
||||||
|
});
|
||||||
|
const serverService = TestBed.inject(DarkModeService);
|
||||||
|
serverService.updateDarkMode();
|
||||||
|
expect(serverService.darkModeSignal()).toBe('dark');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+47
@@ -67,4 +67,51 @@ describe('ForgetPasswordPopupComponent', () => {
|
|||||||
|
|
||||||
expect(toastService.show).toHaveBeenCalledWith('User not found', jasmine.any(Object));
|
expect(toastService.show).toHaveBeenCalledWith('User not found', jasmine.any(Object));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should emit close event on successful send', () => {
|
||||||
|
const closeSpy = jasmine.createSpy();
|
||||||
|
component.close.subscribe(closeSpy);
|
||||||
|
|
||||||
|
resetService.sendResetPasswordLink.and.returnValue(of({value: 'Email sent'}));
|
||||||
|
component.resetPasswordEmail = 'test@example.com';
|
||||||
|
component.isValidEmail = true;
|
||||||
|
|
||||||
|
component.confirmToSend();
|
||||||
|
|
||||||
|
expect(closeSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show success toast on successful send', () => {
|
||||||
|
resetService.sendResetPasswordLink.and.returnValue(of({value: 'Email sent'}));
|
||||||
|
component.resetPasswordEmail = 'test@example.com';
|
||||||
|
component.isValidEmail = true;
|
||||||
|
|
||||||
|
component.confirmToSend();
|
||||||
|
|
||||||
|
expect(toastService.show).toHaveBeenCalledWith('Email sent', jasmine.objectContaining({
|
||||||
|
classname: 'bg-success text-light'
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should clear email on successful send', () => {
|
||||||
|
resetService.sendResetPasswordLink.and.returnValue(of({value: 'Email sent'}));
|
||||||
|
component.resetPasswordEmail = 'test@example.com';
|
||||||
|
component.isValidEmail = true;
|
||||||
|
|
||||||
|
component.confirmToSend();
|
||||||
|
|
||||||
|
expect(component.resetPasswordEmail).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should clear email on error', () => {
|
||||||
|
resetService.sendResetPasswordLink.and.returnValue(throwError(() => ({
|
||||||
|
error: {error: {message: 'Error'}}
|
||||||
|
})));
|
||||||
|
component.resetPasswordEmail = 'test@example.com';
|
||||||
|
component.isValidEmail = true;
|
||||||
|
|
||||||
|
component.confirmToSend();
|
||||||
|
|
||||||
|
expect(component.resetPasswordEmail).toBe('');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,32 +1,68 @@
|
|||||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||||
import {HeaderComponent} from './header.component';
|
import {HeaderComponent} from './header.component';
|
||||||
import {AuthService} from '../../../infrastructure/services/auth-service';
|
import {AuthService} from '../../../infrastructure/services/auth-service';
|
||||||
|
import {UserStoreService} from '../../../infrastructure/services/user-store.service';
|
||||||
import {ActivatedRoute} from '@angular/router';
|
import {ActivatedRoute} from '@angular/router';
|
||||||
|
|
||||||
describe('HeaderComponent', () => {
|
describe('HeaderComponent', () => {
|
||||||
let component: HeaderComponent;
|
let component: HeaderComponent;
|
||||||
let fixture: ComponentFixture<HeaderComponent>;
|
let fixture: ComponentFixture<HeaderComponent>;
|
||||||
|
let authService: jasmine.SpyObj<AuthService>;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const authSpy = jasmine.createSpyObj('AuthService', [
|
authService = jasmine.createSpyObj('AuthService', [
|
||||||
'getUsernameFromToken', 'getRoleFromToken', 'getEmailFromToken', 'getUserIdFromToken',
|
'getUsernameFromToken', 'getRoleFromToken', 'getEmailFromToken',
|
||||||
'isLoggedIn', 'getToken', 'signOut', 'decodedToken'
|
'getUserIdFromToken', 'isLoggedIn', 'getToken', 'signOut', 'decodedToken'
|
||||||
]);
|
]);
|
||||||
|
authService.getUsernameFromToken.and.returnValue('default-user');
|
||||||
|
authService.getRoleFromToken.and.returnValue('User');
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [HeaderComponent],
|
imports: [HeaderComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: AuthService, useValue: authSpy},
|
{provide: AuthService, useValue: authService},
|
||||||
{provide: ActivatedRoute, useValue: {snapshot: {data: {}}, firstChild: null}},
|
{
|
||||||
|
provide: ActivatedRoute,
|
||||||
|
useValue: {snapshot: {data: {}}, firstChild: null}
|
||||||
|
},
|
||||||
|
UserStoreService,
|
||||||
]
|
]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
fixture = TestBed.createComponent(HeaderComponent);
|
fixture = TestBed.createComponent(HeaderComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
|
fixture.detectChanges();
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should load username from store or token fallback', () => {
|
||||||
|
const userStore = TestBed.inject(UserStoreService);
|
||||||
|
userStore.setUsernameForStore('store-user');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.username).toBe('store-user');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fall back to token username when store is empty', () => {
|
||||||
|
authService.getUsernameFromToken.and.returnValue('token-user');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.username).toBe('token-user');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load role from store or token fallback', () => {
|
||||||
|
authService.getRoleFromToken.and.returnValue('Admin');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.role).toBe('Admin');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call signOut on logout', () => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.logOut();
|
||||||
|
expect(authService.signOut).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,23 +1,35 @@
|
|||||||
import {TestBed} from '@angular/core/testing';
|
import {fakeAsync, TestBed, tick} from '@angular/core/testing';
|
||||||
import {HttpClient, HttpInterceptorFn, provideHttpClient, withInterceptors, withXhr} from '@angular/common/http';
|
import {HttpClient, HttpInterceptorFn, provideHttpClient, withInterceptors, withXhr} from '@angular/common/http';
|
||||||
import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing';
|
import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing';
|
||||||
import {tokenInterceptor} from './token.interceptor';
|
import {tokenInterceptor} from './token.interceptor';
|
||||||
import {AuthService} from '../../infrastructure/services/auth-service';
|
import {AuthService} from '../../infrastructure/services/auth-service';
|
||||||
|
import {ToastService} from '../../infrastructure/services/toast.service';
|
||||||
|
import {Router} from '@angular/router';
|
||||||
|
import {of, throwError} from 'rxjs';
|
||||||
|
|
||||||
describe('tokenInterceptor', () => {
|
describe('tokenInterceptor', () => {
|
||||||
let authService: jasmine.SpyObj<AuthService>;
|
let authService: jasmine.SpyObj<AuthService>;
|
||||||
|
let toastService: jasmine.SpyObj<ToastService>;
|
||||||
|
let router: jasmine.SpyObj<Router>;
|
||||||
let httpClient: HttpClient;
|
let httpClient: HttpClient;
|
||||||
let httpTesting: HttpTestingController;
|
let httpTesting: HttpTestingController;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
authService = jasmine.createSpyObj('AuthService', ['getToken', 'getRefreshToken', 'getUserIdFromToken',
|
authService = jasmine.createSpyObj('AuthService', [
|
||||||
'storeToken', 'storeRefreshToken', 'signOut', 'renewToken']);
|
'getToken', 'getRefreshToken', 'getUserIdFromToken',
|
||||||
|
'storeToken', 'storeRefreshToken', 'signOut', 'renewToken'
|
||||||
|
]);
|
||||||
|
toastService = jasmine.createSpyObj('ToastService', ['show']);
|
||||||
|
router = jasmine.createSpyObj('Router', ['navigate']);
|
||||||
|
router.navigate.and.returnValue(Promise.resolve(true));
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
providers: [
|
providers: [
|
||||||
provideHttpClient(withXhr(), withInterceptors([tokenInterceptor])),
|
provideHttpClient(withXhr(), withInterceptors([tokenInterceptor])),
|
||||||
provideHttpClientTesting(),
|
provideHttpClientTesting(),
|
||||||
{provide: AuthService, useValue: authService},
|
{provide: AuthService, useValue: authService},
|
||||||
|
{provide: ToastService, useValue: toastService},
|
||||||
|
{provide: Router, useValue: router},
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
httpClient = TestBed.inject(HttpClient);
|
httpClient = TestBed.inject(HttpClient);
|
||||||
@@ -47,4 +59,61 @@ describe('tokenInterceptor', () => {
|
|||||||
expect(req.request.headers.has('Authorization')).toBeFalse();
|
expect(req.request.headers.has('Authorization')).toBeFalse();
|
||||||
req.flush({});
|
req.flush({});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should retry with new token on 401 and refresh succeeds', () => {
|
||||||
|
authService.getToken.and.returnValues('expired-token', 'new-access-token');
|
||||||
|
authService.getRefreshToken.and.returnValue('valid-refresh');
|
||||||
|
authService.getUserIdFromToken.and.returnValue(1);
|
||||||
|
authService.renewToken.and.returnValue(of({
|
||||||
|
value: {accessToken: 'new-access-token', refreshToken: 'new-refresh-token'}
|
||||||
|
}));
|
||||||
|
|
||||||
|
const results: any[] = [];
|
||||||
|
httpClient.get('/api/data').subscribe({next: r => results.push(r)});
|
||||||
|
|
||||||
|
const req1 = httpTesting.expectOne('/api/data');
|
||||||
|
req1.flush('Unauthorized', {status: 401, statusText: 'Unauthorized'});
|
||||||
|
|
||||||
|
const req2 = httpTesting.expectOne('/api/data');
|
||||||
|
expect(req2.request.headers.get('Authorization')).toBe('Bearer new-access-token');
|
||||||
|
req2.flush({data: 'success'});
|
||||||
|
|
||||||
|
expect(results).toEqual([{data: 'success'}]);
|
||||||
|
expect(authService.storeToken).toHaveBeenCalledWith('new-access-token');
|
||||||
|
expect(authService.storeRefreshToken).toHaveBeenCalledWith('new-refresh-token');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should sign out and redirect on 401 when refresh fails', fakeAsync(() => {
|
||||||
|
authService.getToken.and.returnValue('expired-token');
|
||||||
|
authService.getRefreshToken.and.returnValue('expired-refresh');
|
||||||
|
authService.getUserIdFromToken.and.returnValue(1);
|
||||||
|
authService.renewToken.and.returnValue(throwError(() => ({
|
||||||
|
error: {error: {message: 'Token expired'}}
|
||||||
|
})));
|
||||||
|
|
||||||
|
httpClient.get('/api/data').subscribe({error: () => {}});
|
||||||
|
|
||||||
|
const req = httpTesting.expectOne('/api/data');
|
||||||
|
req.flush('Unauthorized', {status: 401, statusText: 'Unauthorized'});
|
||||||
|
tick();
|
||||||
|
|
||||||
|
expect(authService.signOut).toHaveBeenCalled();
|
||||||
|
expect(router.navigate).toHaveBeenCalledWith(['login']);
|
||||||
|
expect(toastService.show).toHaveBeenCalledWith('Token expired', jasmine.objectContaining({
|
||||||
|
classname: 'bg-warning text-light'
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should pass through non-401 errors', () => {
|
||||||
|
authService.getToken.and.returnValue('some-token');
|
||||||
|
|
||||||
|
const errors: any[] = [];
|
||||||
|
httpClient.get('/api/test').subscribe({error: e => errors.push(e)});
|
||||||
|
|
||||||
|
const req = httpTesting.expectOne('/api/test');
|
||||||
|
req.flush('Forbidden', {status: 403, statusText: 'Forbidden'});
|
||||||
|
|
||||||
|
expect(errors.length).toBe(1);
|
||||||
|
expect(errors[0].status).toBe(403);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+28
-5
@@ -1,6 +1,5 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||||
|
import {PopupModalComponent} from './popup-modal.component';
|
||||||
import { PopupModalComponent } from './popup-modal.component';
|
|
||||||
|
|
||||||
describe('PopupModalComponent', () => {
|
describe('PopupModalComponent', () => {
|
||||||
let component: PopupModalComponent;
|
let component: PopupModalComponent;
|
||||||
@@ -9,8 +8,7 @@ describe('PopupModalComponent', () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [PopupModalComponent]
|
imports: [PopupModalComponent]
|
||||||
})
|
}).compileComponents();
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(PopupModalComponent);
|
fixture = TestBed.createComponent(PopupModalComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
@@ -20,4 +18,29 @@ describe('PopupModalComponent', () => {
|
|||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should have default headerClass', () => {
|
||||||
|
expect(component.headerClass).toBe('bg-light');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should bind title input', () => {
|
||||||
|
component.title = 'Warning';
|
||||||
|
fixture.detectChanges();
|
||||||
|
const titleEl: HTMLElement = fixture.nativeElement.querySelector('.modal-title');
|
||||||
|
expect(titleEl.textContent).toContain('Warning');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should bind body input', () => {
|
||||||
|
component.body = 'Are you sure?';
|
||||||
|
fixture.detectChanges();
|
||||||
|
const bodyEl: HTMLElement = fixture.nativeElement.querySelector('.modal-body p');
|
||||||
|
expect(bodyEl.textContent).toContain('Are you sure?');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit confirm on onConfirm', () => {
|
||||||
|
const spy = jasmine.createSpy();
|
||||||
|
component.confirm.subscribe(spy);
|
||||||
|
component.onConfirm();
|
||||||
|
expect(spy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||||
|
|
||||||
import {ToastComponent} from './toast.component';
|
import {ToastComponent} from './toast.component';
|
||||||
|
import {ToastService} from '../../../infrastructure/services/toast.service';
|
||||||
|
|
||||||
describe('ToastComponent', () => {
|
describe('ToastComponent', () => {
|
||||||
let component: ToastComponent;
|
let component: ToastComponent;
|
||||||
let fixture: ComponentFixture<ToastComponent>;
|
let fixture: ComponentFixture<ToastComponent>;
|
||||||
|
let toastService: ToastService;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [ToastComponent]
|
imports: [ToastComponent]
|
||||||
})
|
}).compileComponents();
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
|
toastService = TestBed.inject(ToastService);
|
||||||
fixture = TestBed.createComponent(ToastComponent);
|
fixture = TestBed.createComponent(ToastComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -20,4 +21,45 @@ describe('ToastComponent', () => {
|
|||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should render toasts from service', () => {
|
||||||
|
toastService.show('Hello World', {classname: 'bg-info'});
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const toastEl = fixture.nativeElement.querySelector('.toast');
|
||||||
|
expect(toastEl).toBeTruthy();
|
||||||
|
expect(toastEl.textContent).toContain('Hello World');
|
||||||
|
expect(toastEl.classList).toContain('bg-info');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render multiple toasts', () => {
|
||||||
|
toastService.show('First');
|
||||||
|
toastService.show('Second');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const toastEls = fixture.nativeElement.querySelectorAll('.toast');
|
||||||
|
expect(toastEls.length).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove toast on close button click', () => {
|
||||||
|
toastService.show('Dismiss me');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const closeBtn = fixture.nativeElement.querySelector('.btn-close');
|
||||||
|
closeBtn.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const toastEls = fixture.nativeElement.querySelectorAll('.toast');
|
||||||
|
expect(toastEls.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should stop rendering after toast is removed', () => {
|
||||||
|
toastService.show('Temporary');
|
||||||
|
toastService.show('Persistent');
|
||||||
|
toastService.remove(toastService.toasts[0]);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const toastEls = fixture.nativeElement.querySelectorAll('.toast');
|
||||||
|
expect(toastEls.length).toBe(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user