Skip to content

Commit

Permalink
Angular: refactoring to have a login component
Browse files Browse the repository at this point in the history
  • Loading branch information
qmonmert committed May 8, 2022
1 parent 32ab0a5 commit aeb20c1
Show file tree
Hide file tree
Showing 15 changed files with 287 additions and 291 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
public class Angular {

public static final String APP_MODULE = "app.module.ts";
public static final String APP_ROUTING_MODULE = "app-routing.module.ts";
public static final String APP_COMPONENT = "app.component.ts";
public static final String APP_COMPONENT_SPEC = "app.component.spec.ts";
public static final String APP_COMPONENT_HTML = "app.component.html";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ public static Map<String, String> angularJwtFiles() {
Map.entry("auth-jwt.service.spec.ts", primaryAppAuth),
Map.entry("login.service.ts", primaryAppLogin),
Map.entry("login.service.spec.ts", primaryAppLogin),
Map.entry("login.model.ts", primaryAppLogin)
Map.entry("login.model.ts", primaryAppLogin),
Map.entry("login.component.css", primaryAppLogin),
Map.entry("login.component.html", primaryAppLogin),
Map.entry("login.component.ts", primaryAppLogin),
Map.entry("login.module.ts", primaryAppLogin),
Map.entry("login.route.ts", primaryAppLogin)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import static tech.jhipster.lite.common.domain.FileUtils.getPath;
import static tech.jhipster.lite.generator.client.angular.core.domain.Angular.*;
import static tech.jhipster.lite.generator.client.angular.core.domain.Angular.APP_COMPONENT_SPEC;
import static tech.jhipster.lite.generator.project.domain.Constants.MAIN_WEBAPP;
import static tech.jhipster.lite.generator.project.domain.DefaultConfig.BASE_NAME;

Expand Down Expand Up @@ -46,100 +45,14 @@ public void addJwtDependencies(Project project) {
}

public void updateAngularFilesForJwt(Project project) {
String oldHtml = "<!-- jhipster-needle-angular-jwt-login-form -->";
String oldHtml = "// jhipster-needle-angular-jwt-login-form";
String newHtml =
"""
<mat-card>
<mat-card-content>
<div [ngSwitch]="account !== null">
<form class="login-form" (ngSubmit)="login()" [formGroup]="loginForm" *ngSwitchCase="false">
<mat-form-field class="form-field-full-width" appearance="fill">
<mat-label>Login</mat-label>
<input type="text" name="username" id="username" formControlName="username" #username matInput placeholder="Login" value="">
</mat-form-field>
<mat-form-field class="form-field-full-width" appearance="fill">
<mat-label>Password</mat-label>
<input type="password" name="password" id="password" formControlName="password" #password matInput placeholder="Password" value="">
</mat-form-field>
<button type="submit" mat-flat-button color="primary">Sign in</button>
</form>
<div *ngSwitchCase="true">
<div>You are logged in as user "{{ account?.login }}".</div>
<button (click)="logout()" mat-flat-button color="primary">Logout</button>
</div>
</div>
</mat-card-content>
</mat-card>""";
projectRepository.replaceText(project, APP, APP_COMPONENT_HTML, oldHtml, newHtml);

oldHtml = "import \\{ Component, OnInit \\} from '@angular/core';";
newHtml =
"""
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { Subject, takeUntil } from 'rxjs';
import { AccountService } from '../../../auth/account.service';
import { LoginService } from '../../../login/login.service';
import { Account } from '../../../auth/account.model';""";
projectRepository.replaceText(project, APP, APP_COMPONENT, oldHtml, newHtml);

oldHtml = "export class AppComponent implements OnInit \\{";
newHtml = "export class AppComponent implements OnInit, OnDestroy {";
projectRepository.replaceText(project, APP, APP_COMPONENT, oldHtml, newHtml);

oldHtml = "appName = '';";
newHtml =
"""
appName = '';
private readonly destroy\\$ = new Subject<void>();
account: Account | null = null;
loginForm = this.fb.group({
username: [null, [Validators.required]],
password: [null, [Validators.required]]
});
constructor(
private accountService: AccountService,
private loginService: LoginService,
private fb: FormBuilder
) {}
""";
projectRepository.replaceText(project, APP, APP_COMPONENT, oldHtml, newHtml);

oldHtml = """
}
}
""";
newHtml =
"""
this.accountService
.getAuthenticationState()
.pipe(takeUntil(this.destroy\\$))
.subscribe(account => this.account = account);
}
ngOnDestroy(): void {
this.destroy\\$.next();
this.destroy\\$.complete();
}
login(): void {
this.loginService
.login({
username: this.loginForm.get('username')!.value,
password: this.loginForm.get('password')!.value,
})
.subscribe();
}
logout(): void {
this.loginService.logout();
}
{
path: '',
loadChildren: () => import('./../../../login/login.module').then(m => m.LoginModule),
}""";
projectRepository.replaceText(project, APP, APP_COMPONENT, oldHtml, newHtml);
projectRepository.replaceText(project, APP, APP_ROUTING_MODULE, oldHtml, newHtml);

oldHtml = "import \\{ NgModule \\} from '@angular/core';";
newHtml =
Expand All @@ -159,9 +72,9 @@ public void updateAngularFilesForJwt(Project project) {
projectRepository.replaceText(project, APP, APP_MODULE, oldHtml, newHtml);

oldHtml =
"imports: \\[BrowserAnimationsModule, MatToolbarModule, MatIconModule, MatButtonModule, MatButtonToggleModule, MatFormFieldModule, MatInputModule, MatCardModule, MatDividerModule, BrowserModule, AppRoutingModule\\],";
"imports: \\[BrowserAnimationsModule, MatToolbarModule, MatIconModule, MatButtonModule, MatButtonToggleModule, BrowserModule, AppRoutingModule\\],";
newHtml =
"imports: [BrowserAnimationsModule, MatToolbarModule, MatIconModule, MatButtonModule, MatButtonToggleModule, MatFormFieldModule, MatInputModule, MatCardModule, MatDividerModule, BrowserModule, AppRoutingModule, HttpClientModule, ReactiveFormsModule, NgxWebstorageModule.forRoot()],";
"imports: [BrowserAnimationsModule, MatToolbarModule, MatIconModule, MatButtonModule, MatButtonToggleModule, BrowserModule, AppRoutingModule, HttpClientModule, ReactiveFormsModule, NgxWebstorageModule.forRoot()],";
projectRepository.replaceText(project, APP, APP_MODULE, oldHtml, newHtml);

oldHtml = "bootstrap: \\[AppComponent\\],";
Expand All @@ -177,169 +90,6 @@ public void updateAngularFilesForJwt(Project project) {
],""";
projectRepository.replaceText(project, APP, APP_MODULE, oldHtml, newHtml);

oldHtml =
"""
import \\{ ComponentFixture, TestBed, waitForAsync \\} from '@angular/core/testing';
import \\{ AppComponent \\} from './app.component';
describe\\('App Component', \\(\\) => \\{
let comp: AppComponent;
let fixture: ComponentFixture<AppComponent>;
beforeEach\\(
waitForAsync\\(\\(\\) => \\{
TestBed.configureTestingModule\\(\\{
declarations: \\[AppComponent\\],
\\}\\)
.overrideTemplate\\(AppComponent, ''\\)
.compileComponents\\(\\);
\\}\\)
\\);
beforeEach\\(\\(\\) => \\{
fixture = TestBed.createComponent\\(AppComponent\\);
comp = fixture.componentInstance;
\\}\\);
describe\\('ngOnInit', \\(\\) => \\{
it\\('should have appName', \\(\\) => \\{
// WHEN
comp.ngOnInit\\(\\);
// THEN
expect\\(comp.appName\\).toEqual\\('""";
newHtml =
"""
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { NgxWebstorageModule } from 'ngx-webstorage';
import { FormBuilder } from '@angular/forms';
import { of, Subject } from 'rxjs';
import { LoginService } from '../../../login/login.service';
import { AccountService } from '../../../auth/account.service';
import { Account } from '../../../auth/account.model';
import { AppComponent } from './app.component';
describe('App Component', () => {
let comp: AppComponent;
let fixture: ComponentFixture<AppComponent>;
let mockAccountService: AccountService;
let mockLoginService: LoginService;
const account: Account = {
activated: true,
authorities: [],
email: '',
firstName: null,
langKey: '',
lastName: null,
login: 'login',
};
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [AppComponent],
imports: [HttpClientTestingModule, NgxWebstorageModule.forRoot()],
providers: [
FormBuilder,
AccountService,
{
provide: LoginService,
useValue: {
login: jest.fn(() => of({})),
logout: jest.fn(() => of({})),
},
},
],
})
.overrideTemplate(AppComponent, '')
.compileComponents();
})
);
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
comp = fixture.componentInstance;
mockLoginService = TestBed.inject(LoginService);
mockAccountService = TestBed.inject(AccountService);
});
describe('ngOnInit', () => {
it('should have appName', () => {
// GIVEN
const authenticationState = new Subject<Account | null>();
mockAccountService.getAuthenticationState = jest.fn(() => authenticationState.asObservable());
// WHEN
comp.ngOnInit();
// THEN
expect(comp.appName).toEqual('""";
projectRepository.replaceText(project, APP, APP_COMPONENT_SPEC, oldHtml, newHtml);

oldHtml = """
\\}\\);
\\}\\);
\\}\\);""";
newHtml =
"""
expect(mockAccountService.getAuthenticationState).toHaveBeenCalled();
// THEN
expect(comp.account).toBeNull();
// WHEN
authenticationState.next(account);
// THEN
expect(comp.account).toEqual(account);
// WHEN
authenticationState.next(null);
// THEN
expect(comp.account).toBeNull();
});
});
describe('login', () => {
it('should authenticate the user', () => {
// GIVEN
const credentials = {
username: 'admin',
password: 'admin',
};
comp.loginForm.patchValue({
username: 'admin',
password: 'admin',
});
// WHEN
comp.login();
// THEN
expect(mockLoginService.login).toHaveBeenCalledWith(credentials);
});
});
describe('logout', () => {
it('should logout the user', () => {
// WHEN
comp.logout();
// THEN
expect(mockLoginService.logout).toHaveBeenCalled();
});
});
});
""";
projectRepository.replaceText(project, APP, APP_COMPONENT_SPEC, oldHtml, newHtml);

oldHtml = "9000";
newHtml = """
9000,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [];
const routes: Routes = [
// jhipster-needle-angular-jwt-login-form
];

@NgModule({
imports: [RouterModule.forRoot(routes)],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,6 @@
width: 250px;
}

.login-form {
min-width: 150px;
max-width: 500px;
width: 100%;
}

.form-field-full-width {
width: 100%;
}

.toolbar-spacer {
flex: 1 1 auto;
}

mat-card{
width: 350px;
display: block;
margin-left:auto;
margin-right:auto;
margin-top: 20px;
}

#footer {
width: 100%;
text-align: center;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

<img alt="JHipster logo" class="jhipster-logo" src="../../../../content/images/JHipster-Lite-neon-red.png" />

<!-- jhipster-needle-angular-jwt-login-form -->
<router-outlet></router-outlet>

<div id="footer">
<h1>{{=<% %>=}}{{ appName }}<%={{ }}=%>: Angular + TypeScript</h1>
Expand All @@ -27,5 +27,3 @@
<code>app.component.ts</code> to test hot module replacement.
</p>
</div>

<router-outlet></router-outlet>
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Component, OnInit } from '@angular/core';
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
export class AppComponent implements OnInit{
appName = '';
ngOnInit(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,10 @@ import { MatToolbarModule } from '@angular/material/toolbar';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatCardModule } from '@angular/material/card';
import { MatDividerModule } from '@angular/material/divider';

@NgModule({
declarations: [AppComponent],
imports: [BrowserAnimationsModule, MatToolbarModule, MatIconModule, MatButtonModule, MatButtonToggleModule, MatFormFieldModule, MatInputModule, MatCardModule, MatDividerModule, BrowserModule, AppRoutingModule],
imports: [BrowserAnimationsModule, MatToolbarModule, MatIconModule, MatButtonModule, MatButtonToggleModule, BrowserModule, AppRoutingModule],
bootstrap: [AppComponent],
})
export class AppModule {}
Loading

0 comments on commit aeb20c1

Please sign in to comment.