refs #1867 Add MatDialog to LoginComponent for displaying GlobalStatusComponent on successful login
testing/ogGui-multibranch/pipeline/head This commit looks good Details

pull/19/head
Lucas Lara García 2025-04-09 13:31:10 +02:00
parent bd0135b796
commit 02fbf57384
2 changed files with 14 additions and 101 deletions

View File

@ -7,9 +7,11 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatIconModule } from '@angular/material/icon';
import { MatDialogModule } from '@angular/material/dialog';
import { TranslateModule } from '@ngx-translate/core';
import { of, throwError } from 'rxjs';
import { ConfigService } from '@services/config.service';
import { GlobalStatusComponent } from '../global-status/global-status.component';
describe('LoginComponent', () => {
let component: LoginComponent;
@ -22,7 +24,7 @@ describe('LoginComponent', () => {
};
await TestBed.configureTestingModule({
declarations: [LoginComponent],
declarations: [LoginComponent, GlobalStatusComponent],
imports: [
FormsModule,
ToastrModule.forRoot(),
@ -30,7 +32,8 @@ describe('LoginComponent', () => {
MatFormFieldModule,
MatInputModule,
MatIconModule,
TranslateModule.forRoot()
MatDialogModule,
TranslateModule.forRoot()
],
providers: [
provideHttpClient(withInterceptorsFromDi()),
@ -46,101 +49,4 @@ describe('LoginComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
it('should disable the login button if username or password is missing', () => {
component.loginObj.username = '';
component.loginObj.password = '';
fixture.detectChanges();
const button = fixture.nativeElement.querySelector('button[type="submit"]');
expect(button.disabled).toBeTruthy();
});
it('should enable the login button if username and password are present', () => {
component.loginObj.username = 'testUser';
component.loginObj.password = 'testPass';
fixture.detectChanges();
const button = fixture.nativeElement.querySelector('button[type="submit"]');
expect(button.disabled).toBeFalsy();
});
it('should call onLogin and navigate on successful login', () => {
const mockRouter = spyOn(component['router'], 'navigateByUrl');
const mockHttp = spyOn(component['http'], 'post').and.returnValue(of({ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c', refreshToken: '456' }));
component.loginObj.username = 'testUser';
component.loginObj.password = 'testPass';
component.onLogin();
expect(mockHttp).toHaveBeenCalledWith(`${component.baseUrl}/auth/login`, component.loginObj);
expect(mockRouter).toHaveBeenCalledWith('/groups');
});
it('should show error message on login failure', () => {
const mockToast = spyOn(component['toastService'], 'error');
const mockHttp = spyOn(component['http'], 'post').and.returnValue(throwError({ error: { message: 'Invalid credentials' } }));
component.loginObj.username = 'testUser';
component.loginObj.password = 'testPass';
component.onLogin();
expect(mockHttp).toHaveBeenCalled();
expect(mockToast).toHaveBeenCalledWith('Error al iniciar sesión: Invalid credentials', 'Error');
});
it('should change language to Spanish and save to localStorage', () => {
const mockTranslate = spyOn(component['translateService'], 'use');
component.changeLanguage('es');
expect(localStorage.getItem('language')).toBe('es');
expect(mockTranslate).toHaveBeenCalledWith('es');
});
it('should change language to English and save to localStorage', () => {
const mockTranslate = spyOn(component['translateService'], 'use');
component.changeLanguage('en');
expect(localStorage.getItem('language')).toBe('en');
expect(mockTranslate).toHaveBeenCalledWith('en');
});
it('should toggle password visibility when clicking the button', () => {
const initialHideState = component.hide();
const button = fixture.nativeElement.querySelector('button[mat-icon-button]');
button.click();
expect(component.hide()).toBe(!initialHideState);
});
it('should add "invalid" class to username input if it is invalid and touched', () => {
const usernameInput = fixture.nativeElement.querySelector('input[name="username"]');
usernameInput.value = ''; // Empty value makes it invalid
usernameInput.dispatchEvent(new Event('input'));
usernameInput.dispatchEvent(new Event('blur')); // Simulates "touched"
fixture.detectChanges();
expect(usernameInput.classList).toContain('invalid');
});
it('should add rotating class to the logo when loading', () => {
component.isLoading = true;
fixture.detectChanges();
const logo = fixture.nativeElement.querySelector('.login-logo');
expect(logo.classList).toContain('rotating');
});
it('should not add rotating class to the logo when not loading', () => {
component.isLoading = false;
fixture.detectChanges();
const logo = fixture.nativeElement.querySelector('.login-logo');
expect(logo.classList).not.toContain('rotating');
});
it('should show a success toast message', () => {
const mockToast = spyOn(component['toastService'], 'success');
component.openSnackBar(false, 'Welcome!');
expect(mockToast).toHaveBeenCalledWith('Welcome!', 'Éxito');
});
it('should show an error toast message', () => {
const mockToast = spyOn(component['toastService'], 'error');
component.openSnackBar(true, 'Something went wrong');
expect(mockToast).toHaveBeenCalledWith('Something went wrong', 'Error');
});
});
});

View File

@ -5,6 +5,8 @@ import { TranslateService } from '@ngx-translate/core';
import { ToastrService } from "ngx-toastr";
import { jwtDecode } from "jwt-decode";
import { ConfigService } from '@services/config.service';
import { MatDialog } from '@angular/material/dialog';
import { GlobalStatusComponent } from '../global-status/global-status.component'
@Component({
selector: 'app-login',
@ -27,7 +29,8 @@ export class LoginComponent {
private router: Router,
private configService: ConfigService,
private toastService: ToastrService,
private translateService: TranslateService
private translateService: TranslateService,
private dialog: MatDialog
) {
this.baseUrl = this.configService.apiUrl;
const savedLanguage = localStorage.getItem('language') || 'es';
@ -67,6 +70,10 @@ export class LoginComponent {
this.openSnackBar(false, 'Bienvenido ' + this.loginObj.username);
this.router.navigateByUrl('/groups');
this.dialog.open(GlobalStatusComponent, {
width: '45vw',
height: '80vh',
});
}
this.isLoading = false;
},