Last fixes before release (#2027)

* Disable login button when a login is in-progress. This will help prevent spamming when internet is slow.

* Fixed a bug where an empty space could cause an error when creating a library.

* Apply Split Options throughout the codebase to add extra safe-guard on empty spaces and ensure trimming.
This commit is contained in:
Joe Milazzo 2023-06-02 08:09:22 -05:00 committed by GitHub
parent a28cd31ed8
commit 68c2577e15
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 26 additions and 114 deletions

View file

@ -1,14 +1,14 @@
<app-splash-container>
<ng-container title><h2>Login</h2></ng-container>
<ng-container body>
<ng-container *ngIf="isLoaded">
<ng-container *ngIf="isLoaded">
<form [formGroup]="loginForm" (ngSubmit)="login()" novalidate class="needs-validation" *ngIf="!firstTimeFlow">
<div class="card-text">
<div class="mb-3">
<label for="username" class="form-label visually-hidden">Username</label>
<input class="form-control custom-input" formControlName="username" id="username" type="text" autofocus placeholder="Username">
</div>
<div class="mb-2">
<label for="password" class="form-label visually-hidden">Password</label>
<input class="form-control custom-input" formControlName="password" name="password"
@ -23,12 +23,12 @@
<div class="mb-3">
<a routerLink="/registration/reset-password" style="color: white">Forgot Password?</a>
</div>
<div>
<button class="btn btn-secondary alt" type="submit">Submit</button>
<button class="btn btn-secondary alt" type="submit" [disabled]="isSubmitting">Submit</button>
</div>
</div>
</form>
</ng-container>
</ng-container>
</app-splash-container>
</app-splash-container>

View file

@ -1,94 +0,0 @@
import { of } from 'rxjs';
import { MemberService } from '../../_services/member.service';
import { UserLoginComponent } from './user-login.component';
xdescribe('UserLoginComponent', () => {
let accountServiceMock: any;
let routerMock: any;
let memberServiceMock: any;
let fixture: UserLoginComponent;
const http = jest.fn();
beforeEach(async () => {
accountServiceMock = {
login: jest.fn()
};
memberServiceMock = {
adminExists: jest.fn().mockReturnValue(of({
success: true,
message: false,
token: ''
}))
};
routerMock = {
navigateByUrl: jest.fn()
};
//fixture = new UserLoginComponent(accountServiceMock, routerMock, memberServiceMock);
//fixture.ngOnInit();
});
describe('Test: ngOnInit', () => {
xit('should redirect to /home if no admin user', done => {
const response = {
success: true,
message: false,
token: ''
}
const httpMock = {
get: jest.fn().mockReturnValue(of(response))
};
const serviceMock = new MemberService(httpMock as any);
serviceMock.adminExists().subscribe((data: any) => {
expect(httpMock.get).toBeDefined();
expect(httpMock.get).toHaveBeenCalled();
expect(routerMock.navigateByUrl).toHaveBeenCalledWith('/home');
done();
});
});
xit('should initialize login form', () => {
const loginForm = {
username: '',
password: ''
};
expect(fixture.loginForm.value).toEqual(loginForm);
});
});
xdescribe('Test: Login Form', () => {
it('should invalidate the form', () => {
fixture.loginForm.controls.username.setValue('');
fixture.loginForm.controls.password.setValue('');
expect(fixture.loginForm.valid).toBeFalsy();
});
it('should validate the form', () => {
fixture.loginForm.controls.username.setValue('demo');
fixture.loginForm.controls.password.setValue('Pa$$word!');
expect(fixture.loginForm.valid).toBeTruthy();
});
});
xdescribe('Test: Form Invalid', () => {
it('should not call login', () => {
fixture.loginForm.controls.username.setValue('');
fixture.loginForm.controls.password.setValue('');
fixture.login();
expect(accountServiceMock.login).not.toHaveBeenCalled();
});
});
// describe('Test: Form valid', () => {
// it('should call login', () => {
// fixture.loginForm.controls.username.setValue('demo');
// fixture.loginForm.controls.password.setValue('Pa$$word!');
// const spyLoginUser = jest.spyOn(accountServiceMock, 'login').mockReturnValue();
// fixture.login();
// expect(accountServiceMock.login).not.toHaveBeenCalled();
// const spyRouterNavigate = jest.spyOn(routerMock, 'navigateByUrl').mockReturnValue();
// });
// });
});

View file

@ -33,9 +33,10 @@ export class UserLoginComponent implements OnInit {
* Used for first time the page loads to ensure no flashing
*/
isLoaded: boolean = false;
isSubmitting = false;
constructor(private accountService: AccountService, private router: Router, private memberService: MemberService,
private toastr: ToastrService, private navService: NavService, private modalService: NgbModal,
private toastr: ToastrService, private navService: NavService, private modalService: NgbModal,
private readonly cdRef: ChangeDetectorRef) {
this.navService.showNavBar();
this.navService.hideSideNav();
@ -53,7 +54,7 @@ export class UserLoginComponent implements OnInit {
this.router.navigateByUrl('/libraries');
}
});
this.memberService.adminExists().pipe(take(1)).subscribe(adminExists => {
this.firstTimeFlow = !adminExists;
@ -79,6 +80,8 @@ export class UserLoginComponent implements OnInit {
login() {
const model = this.loginForm.getRawValue();
this.isSubmitting = true;
this.cdRef.markForCheck();
this.accountService.login(model).subscribe(() => {
this.loginForm.reset();
this.navService.showNavBar();
@ -92,6 +95,8 @@ export class UserLoginComponent implements OnInit {
} else {
this.router.navigateByUrl('/libraries');
}
this.isSubmitting = false;
this.cdRef.markForCheck();
}, err => {
if (err.error === 'You are missing an email on your account. Please wait while we migrate your account.') {
const modalRef = this.modalService.open(AddEmailToAccountMigrationModalComponent, { scrollable: true, size: 'md' });
@ -101,6 +106,8 @@ export class UserLoginComponent implements OnInit {
} else {
this.toastr.error(err.error);
}
this.isSubmitting = false;
this.cdRef.markForCheck();
});
}
}