Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angular: refactoring to have a login component #1661

Merged
merged 1 commit into from
May 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
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_ROUTING_MODULE_SPEC = "app-routing.module.spec.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 Expand Up @@ -75,8 +77,8 @@ public static Map<String, String> angularFiles() {
Map.entry(APP_COMPONENT, primaryApp),
Map.entry(APP_COMPONENT_HTML, primaryApp),
Map.entry(APP_COMPONENT_CSS, primaryApp),
Map.entry("app-routing.module.ts", primaryApp),
Map.entry("app-routing.module.spec.ts", primaryApp),
Map.entry(APP_ROUTING_MODULE, primaryApp),
Map.entry(APP_ROUTING_MODULE_SPEC, primaryApp),
Map.entry(APP_COMPONENT_SPEC, primaryApp),
Map.entry("environment.prod.ts", environments),
Map.entry("environment.prod.spec.ts", environments),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@ 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.spec.ts", 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,38 @@ 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);
{
path: '',
loadChildren: () => import('./../../../login/login.module').then(m => m.LoginModule),
}""";
projectRepository.replaceText(project, APP, APP_ROUTING_MODULE, oldHtml, newHtml);

oldHtml = "import \\{ Component, OnInit \\} from '@angular/core';";
oldHtml = "import \\{ AppRoutingModule \\} from './app-routing.module';";
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);
import { TestBed } from '@angular/core/testing';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { AppRoutingModule, routes } from './app-routing.module';""";
projectRepository.replaceText(project, APP, APP_ROUTING_MODULE_SPEC, oldHtml, newHtml);

oldHtml = "appName = '';";
oldHtml = "// jhipster-needle-angular-jwt-login-form";
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 = """
}
}
let router: Router;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule.withRoutes(routes)]
}).compileComponents();
router = TestBed.get(Router);
router.initialNavigation();
});
""";
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();
}
}""";
projectRepository.replaceText(project, APP, APP_COMPONENT, oldHtml, newHtml);
projectRepository.replaceText(project, APP, APP_ROUTING_MODULE_SPEC, oldHtml, newHtml);

oldHtml = "import \\{ NgModule \\} from '@angular/core';";
newHtml =
Expand All @@ -159,9 +96,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 +114,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,6 +1,7 @@
import { AppRoutingModule } from './app-routing.module';

describe('AppRoutingModule', () => {
// jhipster-needle-angular-jwt-login-form
it('should be defined', () => {
expect(AppRoutingModule).toBeDefined();
});
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 = [];
export 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
Loading