- - -
- - - Rocket Ship - - - - - - - - - - {{ title }} app is running! - - - Rocket Ship Smoke - - - -
- - -

Resources

-

Here are some links to help you get started:

- -
- - - Learn Angular - - - - - CLI Documentation - - - - - - Angular Material - - - - - - Angular Blog - - - - - - Angular DevTools - - - +
+ + +
+
- - -

Next Steps

-

What do you want to do next with your app?

- - - -
- - - - - - - - - - - -
- - -
-
ng generate component xyz
-
ng add @angular/material
-
ng add @angular/pwa
-
ng add _____
-
ng test
-
ng build
-
- - - - - - - - - Gray Clouds Background - - -
- - - - - - - - - - diff --git a/src/app/app.component.ts b/src/app/app.component.ts index e1f3d79..242adcc 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,4 +1,8 @@ import { Component } from '@angular/core'; +import { Subscription } from 'rxjs'; +import { StorageService } from './_services/storage.service'; +import { AuthService } from './_services/auth.service'; +import { EventBusService } from './_shared/event-bus.service'; @Component({ selector: 'app-root', @@ -6,5 +10,49 @@ import { Component } from '@angular/core'; styleUrls: ['./app.component.css'] }) export class AppComponent { - title = 'angular-16-jwt-auth'; + private roles: string[] = []; + isLoggedIn = false; + showAdminBoard = false; + showModeratorBoard = false; + username?: string; + + eventBusSub?: Subscription; + + constructor( + private storageService: StorageService, + private authService: AuthService, + private eventBusService: EventBusService + ) {} + + ngOnInit(): void { + this.isLoggedIn = this.storageService.isLoggedIn(); + + if (this.isLoggedIn) { + const user = this.storageService.getUser(); + this.roles = user.roles; + + this.showAdminBoard = this.roles.includes('ROLE_ADMIN'); + this.showModeratorBoard = this.roles.includes('ROLE_MODERATOR'); + + this.username = user.username; + } + + this.eventBusSub = this.eventBusService.on('logout', () => { + this.logout(); + }); + } + + logout(): void { + this.authService.logout().subscribe({ + next: res => { + console.log(res); + this.storageService.clean(); + + window.location.reload(); + }, + error: err => { + console.log(err); + } + }); + } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index b1c6c96..782bfe6 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,18 +1,38 @@ import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; +import { FormsModule } from '@angular/forms'; +import { HttpClientModule } from '@angular/common/http'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; +import { LoginComponent } from './login/login.component'; +import { RegisterComponent } from './register/register.component'; +import { HomeComponent } from './home/home.component'; +import { ProfileComponent } from './profile/profile.component'; +import { BoardAdminComponent } from './board-admin/board-admin.component'; +import { BoardModeratorComponent } from './board-moderator/board-moderator.component'; +import { BoardUserComponent } from './board-user/board-user.component'; + +import { httpInterceptorProviders } from './_helpers/http.interceptor'; @NgModule({ declarations: [ - AppComponent + AppComponent, + LoginComponent, + RegisterComponent, + HomeComponent, + ProfileComponent, + BoardAdminComponent, + BoardModeratorComponent, + BoardUserComponent ], imports: [ BrowserModule, - AppRoutingModule + AppRoutingModule, + FormsModule, + HttpClientModule ], - providers: [], + providers: [httpInterceptorProviders], bootstrap: [AppComponent] }) export class AppModule { } diff --git a/src/app/board-admin/board-admin.component.css b/src/app/board-admin/board-admin.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/board-admin/board-admin.component.html b/src/app/board-admin/board-admin.component.html new file mode 100644 index 0000000..cbadc7a --- /dev/null +++ b/src/app/board-admin/board-admin.component.html @@ -0,0 +1,5 @@ +
+
+

{{ content }}

+
+
diff --git a/src/app/board-admin/board-admin.component.spec.ts b/src/app/board-admin/board-admin.component.spec.ts new file mode 100644 index 0000000..b91a08d --- /dev/null +++ b/src/app/board-admin/board-admin.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BoardAdminComponent } from './board-admin.component'; + +describe('BoardAdminComponent', () => { + let component: BoardAdminComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [BoardAdminComponent] + }); + fixture = TestBed.createComponent(BoardAdminComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/board-admin/board-admin.component.ts b/src/app/board-admin/board-admin.component.ts new file mode 100644 index 0000000..5b70d2d --- /dev/null +++ b/src/app/board-admin/board-admin.component.ts @@ -0,0 +1,33 @@ +import { Component, OnInit } from '@angular/core'; +import { UserService } from '../_services/user.service'; + +@Component({ + selector: 'app-board-admin', + templateUrl: './board-admin.component.html', + styleUrls: ['./board-admin.component.css'] +}) +export class BoardAdminComponent implements OnInit { + content?: string; + + constructor(private userService: UserService) { } + + ngOnInit(): void { + this.userService.getAdminBoard().subscribe({ + next: data => { + this.content = data; + }, + error: err => { + if (err.error) { + try { + const res = JSON.parse(err.error); + this.content = res.message; + } catch { + this.content = `Error with status: ${err.status} - ${err.statusText}`; + } + } else { + this.content = `Error with status: ${err.status}`; + } + } + }); + } +} diff --git a/src/app/board-moderator/board-moderator.component.css b/src/app/board-moderator/board-moderator.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/board-moderator/board-moderator.component.html b/src/app/board-moderator/board-moderator.component.html new file mode 100644 index 0000000..cbadc7a --- /dev/null +++ b/src/app/board-moderator/board-moderator.component.html @@ -0,0 +1,5 @@ +
+
+

{{ content }}

+
+
diff --git a/src/app/board-moderator/board-moderator.component.spec.ts b/src/app/board-moderator/board-moderator.component.spec.ts new file mode 100644 index 0000000..2343025 --- /dev/null +++ b/src/app/board-moderator/board-moderator.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BoardModeratorComponent } from './board-moderator.component'; + +describe('BoardModeratorComponent', () => { + let component: BoardModeratorComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [BoardModeratorComponent] + }); + fixture = TestBed.createComponent(BoardModeratorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/board-moderator/board-moderator.component.ts b/src/app/board-moderator/board-moderator.component.ts new file mode 100644 index 0000000..c04c397 --- /dev/null +++ b/src/app/board-moderator/board-moderator.component.ts @@ -0,0 +1,33 @@ +import { Component, OnInit } from '@angular/core'; +import { UserService } from '../_services/user.service'; + +@Component({ + selector: 'app-board-moderator', + templateUrl: './board-moderator.component.html', + styleUrls: ['./board-moderator.component.css'] +}) +export class BoardModeratorComponent implements OnInit { + content?: string; + + constructor(private userService: UserService) { } + + ngOnInit(): void { + this.userService.getModeratorBoard().subscribe({ + next: data => { + this.content = data; + }, + error: err => { + if (err.error) { + try { + const res = JSON.parse(err.error); + this.content = res.message; + } catch { + this.content = `Error with status: ${err.status} - ${err.statusText}`; + } + } else { + this.content = `Error with status: ${err.status}`; + } + } + }); + } +} diff --git a/src/app/board-user/board-user.component.css b/src/app/board-user/board-user.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/board-user/board-user.component.html b/src/app/board-user/board-user.component.html new file mode 100644 index 0000000..cbadc7a --- /dev/null +++ b/src/app/board-user/board-user.component.html @@ -0,0 +1,5 @@ +
+
+

{{ content }}

+
+
diff --git a/src/app/board-user/board-user.component.spec.ts b/src/app/board-user/board-user.component.spec.ts new file mode 100644 index 0000000..33a199c --- /dev/null +++ b/src/app/board-user/board-user.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BoardUserComponent } from './board-user.component'; + +describe('BoardUserComponent', () => { + let component: BoardUserComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [BoardUserComponent] + }); + fixture = TestBed.createComponent(BoardUserComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/board-user/board-user.component.ts b/src/app/board-user/board-user.component.ts new file mode 100644 index 0000000..6e17378 --- /dev/null +++ b/src/app/board-user/board-user.component.ts @@ -0,0 +1,33 @@ +import { Component, OnInit } from '@angular/core'; +import { UserService } from '../_services/user.service'; + +@Component({ + selector: 'app-board-user', + templateUrl: './board-user.component.html', + styleUrls: ['./board-user.component.css'] +}) +export class BoardUserComponent implements OnInit { + content?: string; + + constructor(private userService: UserService) { } + + ngOnInit(): void { + this.userService.getUserBoard().subscribe({ + next: data => { + this.content = data; + }, + error: err => { + if (err.error) { + try { + const res = JSON.parse(err.error); + this.content = res.message; + } catch { + this.content = `Error with status: ${err.status} - ${err.statusText}`; + } + } else { + this.content = `Error with status: ${err.status}`; + } + } + }); + } +} diff --git a/src/app/home/home.component.css b/src/app/home/home.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html new file mode 100644 index 0000000..cbadc7a --- /dev/null +++ b/src/app/home/home.component.html @@ -0,0 +1,5 @@ +
+
+

{{ content }}

+
+
diff --git a/src/app/home/home.component.spec.ts b/src/app/home/home.component.spec.ts new file mode 100644 index 0000000..ba1b4a3 --- /dev/null +++ b/src/app/home/home.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HomeComponent } from './home.component'; + +describe('HomeComponent', () => { + let component: HomeComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [HomeComponent] + }); + fixture = TestBed.createComponent(HomeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts new file mode 100644 index 0000000..02f10a3 --- /dev/null +++ b/src/app/home/home.component.ts @@ -0,0 +1,33 @@ +import { Component, OnInit } from '@angular/core'; +import { UserService } from '../_services/user.service'; + +@Component({ + selector: 'app-home', + templateUrl: './home.component.html', + styleUrls: ['./home.component.css'] +}) +export class HomeComponent implements OnInit { + content?: string; + + constructor(private userService: UserService) { } + + ngOnInit(): void { + this.userService.getPublicContent().subscribe({ + next: data => { + this.content = data; + }, + error: err => { + if (err.error) { + try { + const res = JSON.parse(err.error); + this.content = res.message; + } catch { + this.content = `Error with status: ${err.status} - ${err.statusText}`; + } + } else { + this.content = `Error with status: ${err.status}`; + } + } + }); + } +} diff --git a/src/app/login/login.component.css b/src/app/login/login.component.css new file mode 100644 index 0000000..924cf00 --- /dev/null +++ b/src/app/login/login.component.css @@ -0,0 +1,32 @@ +label { + display: block; + margin-top: 10px; +} + +.card-container.card { + max-width: 400px !important; + padding: 40px 40px; +} + +.card { + background-color: #f7f7f7; + padding: 20px 25px 30px; + margin: 0 auto 25px; + margin-top: 50px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; + -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); + -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); + box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); +} + +.profile-img-card { + width: 96px; + height: 96px; + margin: 0 auto 10px; + display: block; + -moz-border-radius: 50%; + -webkit-border-radius: 50%; + border-radius: 50%; +} \ No newline at end of file diff --git a/src/app/login/login.component.html b/src/app/login/login.component.html new file mode 100644 index 0000000..f79d7ad --- /dev/null +++ b/src/app/login/login.component.html @@ -0,0 +1,65 @@ +
+
+ +
+
+ + +
+ Username is required! +
+
+
+ + +
+
Password is required
+
+ Password must be at least 6 characters +
+
+
+
+ +
+
+ +
+
+ +
+ Logged in as {{ roles }}. +
+
+
\ No newline at end of file diff --git a/src/app/login/login.component.spec.ts b/src/app/login/login.component.spec.ts new file mode 100644 index 0000000..360f9f2 --- /dev/null +++ b/src/app/login/login.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LoginComponent } from './login.component'; + +describe('LoginComponent', () => { + let component: LoginComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [LoginComponent] + }); + fixture = TestBed.createComponent(LoginComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/login/login.component.ts b/src/app/login/login.component.ts new file mode 100644 index 0000000..97b4050 --- /dev/null +++ b/src/app/login/login.component.ts @@ -0,0 +1,51 @@ +import { Component, OnInit } from '@angular/core'; +import { AuthService } from '../_services/auth.service'; +import { StorageService } from '../_services/storage.service'; + +@Component({ + selector: 'app-login', + templateUrl: './login.component.html', + styleUrls: ['./login.component.css'] +}) +export class LoginComponent implements OnInit { + form: any = { + username: null, + password: null + }; + isLoggedIn = false; + isLoginFailed = false; + errorMessage = ''; + roles: string[] = []; + + constructor(private authService: AuthService, private storageService: StorageService) { } + + ngOnInit(): void { + if (this.storageService.isLoggedIn()) { + this.isLoggedIn = true; + this.roles = this.storageService.getUser().roles; + } + } + + onSubmit(): void { + const { username, password } = this.form; + + this.authService.login(username, password).subscribe({ + next: data => { + this.storageService.saveUser(data); + + this.isLoginFailed = false; + this.isLoggedIn = true; + this.roles = this.storageService.getUser().roles; + this.reloadPage(); + }, + error: err => { + this.errorMessage = err.error.message; + this.isLoginFailed = true; + } + }); + } + + reloadPage(): void { + window.location.reload(); + } +} diff --git a/src/app/profile/profile.component.css b/src/app/profile/profile.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/profile/profile.component.html b/src/app/profile/profile.component.html new file mode 100644 index 0000000..bf82165 --- /dev/null +++ b/src/app/profile/profile.component.html @@ -0,0 +1,21 @@ +
+
+

+ {{ currentUser.username }} Profile +

+
+

+ Email: + {{ currentUser.email }} +

+ Roles: +
    +
  • + {{ role }} +
  • +
+
+ + + Please login. + \ No newline at end of file diff --git a/src/app/profile/profile.component.spec.ts b/src/app/profile/profile.component.spec.ts new file mode 100644 index 0000000..042e899 --- /dev/null +++ b/src/app/profile/profile.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProfileComponent } from './profile.component'; + +describe('ProfileComponent', () => { + let component: ProfileComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ProfileComponent] + }); + fixture = TestBed.createComponent(ProfileComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/profile/profile.component.ts b/src/app/profile/profile.component.ts new file mode 100644 index 0000000..b574b93 --- /dev/null +++ b/src/app/profile/profile.component.ts @@ -0,0 +1,17 @@ +import { Component, OnInit } from '@angular/core'; +import { StorageService } from '../_services/storage.service'; + +@Component({ + selector: 'app-profile', + templateUrl: './profile.component.html', + styleUrls: ['./profile.component.css'] +}) +export class ProfileComponent implements OnInit { + currentUser: any; + + constructor(private storageService: StorageService) { } + + ngOnInit(): void { + this.currentUser = this.storageService.getUser(); + } +} diff --git a/src/app/register/register.component.css b/src/app/register/register.component.css new file mode 100644 index 0000000..924cf00 --- /dev/null +++ b/src/app/register/register.component.css @@ -0,0 +1,32 @@ +label { + display: block; + margin-top: 10px; +} + +.card-container.card { + max-width: 400px !important; + padding: 40px 40px; +} + +.card { + background-color: #f7f7f7; + padding: 20px 25px 30px; + margin: 0 auto 25px; + margin-top: 50px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; + -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); + -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); + box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); +} + +.profile-img-card { + width: 96px; + height: 96px; + margin: 0 auto 10px; + display: block; + -moz-border-radius: 50%; + -webkit-border-radius: 50%; + border-radius: 50%; +} \ No newline at end of file diff --git a/src/app/register/register.component.html b/src/app/register/register.component.html new file mode 100644 index 0000000..05bac8a --- /dev/null +++ b/src/app/register/register.component.html @@ -0,0 +1,89 @@ +
+
+ +
+
+ + +
+
Username is required
+
+ Username must be at least 3 characters +
+
+ Username must be at most 20 characters +
+
+
+
+ + +
+
Email is required
+
+ Email must be a valid email address +
+
+
+
+ + +
+
Password is required
+
+ Password must be at least 6 characters +
+
+
+
+ +
+ +
+ Signup failed!
{{ errorMessage }} +
+
+ +
+ Your registration is successful! +
+
+
\ No newline at end of file diff --git a/src/app/register/register.component.spec.ts b/src/app/register/register.component.spec.ts new file mode 100644 index 0000000..9c4c73c --- /dev/null +++ b/src/app/register/register.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RegisterComponent } from './register.component'; + +describe('RegisterComponent', () => { + let component: RegisterComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [RegisterComponent] + }); + fixture = TestBed.createComponent(RegisterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/register/register.component.ts b/src/app/register/register.component.ts new file mode 100644 index 0000000..2cd4997 --- /dev/null +++ b/src/app/register/register.component.ts @@ -0,0 +1,36 @@ +import { Component, OnInit } from '@angular/core'; +import { AuthService } from '../_services/auth.service'; + +@Component({ + selector: 'app-register', + templateUrl: './register.component.html', + styleUrls: ['./register.component.css'] +}) +export class RegisterComponent { + form: any = { + username: null, + email: null, + password: null + }; + isSuccessful = false; + isSignUpFailed = false; + errorMessage = ''; + + constructor(private authService: AuthService) { } + + onSubmit(): void { + const { username, email, password } = this.form; + + this.authService.register(username, email, password).subscribe({ + next: data => { + console.log(data); + this.isSuccessful = true; + this.isSignUpFailed = false; + }, + error: err => { + this.errorMessage = err.error.message; + this.isSignUpFailed = true; + } + }); + } +} diff --git a/src/styles.css b/src/styles.css index 90d4ee0..a97f91e 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1 +1,2 @@ /* You can add global styles to this file, and also import other style files */ +@import "~bootstrap/dist/css/bootstrap.css"; \ No newline at end of file From a2c907cb5f5a6f1dbb20062541564528e7f52c08 Mon Sep 17 00:00:00 2001 From: GaryDev <112358055+garydev10@users.noreply.github.com> Date: Sun, 11 Jun 2023 15:09:50 +0800 Subject: [PATCH 2/5] fix ng test error issue #1 --- src/app/_services/auth.service.spec.ts | 8 +++- src/app/_services/user.service.spec.ts | 7 +++- src/app/app.component.spec.ts | 37 +++++++++++++------ .../board-admin/board-admin.component.spec.ts | 5 +++ .../board-moderator.component.spec.ts | 5 +++ .../board-user/board-user.component.spec.ts | 5 +++ src/app/home/home.component.spec.ts | 5 +++ src/app/login/login.component.spec.ts | 13 +++++++ src/app/register/register.component.spec.ts | 9 +++++ 9 files changed, 80 insertions(+), 14 deletions(-) diff --git a/src/app/_services/auth.service.spec.ts b/src/app/_services/auth.service.spec.ts index f1251ca..82e0fb0 100644 --- a/src/app/_services/auth.service.spec.ts +++ b/src/app/_services/auth.service.spec.ts @@ -2,11 +2,17 @@ import { TestBed } from '@angular/core/testing'; import { AuthService } from './auth.service'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; + describe('AuthService', () => { let service: AuthService; beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [AuthService] + }); + service = TestBed.inject(AuthService); }); diff --git a/src/app/_services/user.service.spec.ts b/src/app/_services/user.service.spec.ts index 3f804c9..72f193f 100644 --- a/src/app/_services/user.service.spec.ts +++ b/src/app/_services/user.service.spec.ts @@ -2,11 +2,16 @@ import { TestBed } from '@angular/core/testing'; import { UserService } from './user.service'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; + describe('UserService', () => { let service: UserService; beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [UserService] + }); service = TestBed.inject(UserService); }); diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index 3005eac..24f1e23 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -2,9 +2,22 @@ import { TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { AppComponent } from './app.component'; +import { StorageService } from './_services/storage.service'; +import { AuthService } from './_services/auth.service'; +import { EventBusService } from './_shared/event-bus.service'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; + describe('AppComponent', () => { beforeEach(() => TestBed.configureTestingModule({ - imports: [RouterTestingModule], + providers: [ + StorageService, + AuthService, + EventBusService + ], + imports: [ + RouterTestingModule, + HttpClientTestingModule + ], declarations: [AppComponent] })); @@ -14,16 +27,16 @@ describe('AppComponent', () => { expect(app).toBeTruthy(); }); - it(`should have as title 'angular-16-jwt-auth'`, () => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.componentInstance; - expect(app.title).toEqual('angular-16-jwt-auth'); - }); + // it(`should have as title 'angular-16-jwt-auth'`, () => { + // const fixture = TestBed.createComponent(AppComponent); + // const app = fixture.componentInstance; + // expect(app.title).toEqual('angular-16-jwt-auth'); + // }); - it('should render title', () => { - const fixture = TestBed.createComponent(AppComponent); - fixture.detectChanges(); - const compiled = fixture.nativeElement as HTMLElement; - expect(compiled.querySelector('.content span')?.textContent).toContain('angular-16-jwt-auth app is running!'); - }); + // it('should render title', () => { + // const fixture = TestBed.createComponent(AppComponent); + // fixture.detectChanges(); + // const compiled = fixture.nativeElement as HTMLElement; + // expect(compiled.querySelector('.content span')?.textContent).toContain('angular-16-jwt-auth app is running!'); + // }); }); diff --git a/src/app/board-admin/board-admin.component.spec.ts b/src/app/board-admin/board-admin.component.spec.ts index b91a08d..38f6084 100644 --- a/src/app/board-admin/board-admin.component.spec.ts +++ b/src/app/board-admin/board-admin.component.spec.ts @@ -2,12 +2,17 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { BoardAdminComponent } from './board-admin.component'; +import { UserService } from '../_services/user.service'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; + describe('BoardAdminComponent', () => { let component: BoardAdminComponent; let fixture: ComponentFixture; beforeEach(() => { TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [UserService], declarations: [BoardAdminComponent] }); fixture = TestBed.createComponent(BoardAdminComponent); diff --git a/src/app/board-moderator/board-moderator.component.spec.ts b/src/app/board-moderator/board-moderator.component.spec.ts index 2343025..3236fc3 100644 --- a/src/app/board-moderator/board-moderator.component.spec.ts +++ b/src/app/board-moderator/board-moderator.component.spec.ts @@ -2,12 +2,17 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { BoardModeratorComponent } from './board-moderator.component'; +import { UserService } from '../_services/user.service'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; + describe('BoardModeratorComponent', () => { let component: BoardModeratorComponent; let fixture: ComponentFixture; beforeEach(() => { TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [UserService], declarations: [BoardModeratorComponent] }); fixture = TestBed.createComponent(BoardModeratorComponent); diff --git a/src/app/board-user/board-user.component.spec.ts b/src/app/board-user/board-user.component.spec.ts index 33a199c..4a69d1a 100644 --- a/src/app/board-user/board-user.component.spec.ts +++ b/src/app/board-user/board-user.component.spec.ts @@ -2,12 +2,17 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { BoardUserComponent } from './board-user.component'; +import { UserService } from '../_services/user.service'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; + describe('BoardUserComponent', () => { let component: BoardUserComponent; let fixture: ComponentFixture; beforeEach(() => { TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [UserService], declarations: [BoardUserComponent] }); fixture = TestBed.createComponent(BoardUserComponent); diff --git a/src/app/home/home.component.spec.ts b/src/app/home/home.component.spec.ts index ba1b4a3..c5f3e24 100644 --- a/src/app/home/home.component.spec.ts +++ b/src/app/home/home.component.spec.ts @@ -2,12 +2,17 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HomeComponent } from './home.component'; +import { UserService } from '../_services/user.service'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; + describe('HomeComponent', () => { let component: HomeComponent; let fixture: ComponentFixture; beforeEach(() => { TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [UserService], declarations: [HomeComponent] }); fixture = TestBed.createComponent(HomeComponent); diff --git a/src/app/login/login.component.spec.ts b/src/app/login/login.component.spec.ts index 360f9f2..51cc8ac 100644 --- a/src/app/login/login.component.spec.ts +++ b/src/app/login/login.component.spec.ts @@ -2,12 +2,25 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { LoginComponent } from './login.component'; +import { AuthService } from '../_services/auth.service'; +import { StorageService } from '../_services/storage.service'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { FormsModule } from '@angular/forms'; + describe('LoginComponent', () => { let component: LoginComponent; let fixture: ComponentFixture; beforeEach(() => { TestBed.configureTestingModule({ + imports: [ + HttpClientTestingModule, + FormsModule + ], + providers: [ + StorageService, + AuthService + ], declarations: [LoginComponent] }); fixture = TestBed.createComponent(LoginComponent); diff --git a/src/app/register/register.component.spec.ts b/src/app/register/register.component.spec.ts index 9c4c73c..b2fd412 100644 --- a/src/app/register/register.component.spec.ts +++ b/src/app/register/register.component.spec.ts @@ -2,12 +2,21 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { RegisterComponent } from './register.component'; +import { AuthService } from '../_services/auth.service'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { FormsModule } from '@angular/forms'; + describe('RegisterComponent', () => { let component: RegisterComponent; let fixture: ComponentFixture; beforeEach(() => { TestBed.configureTestingModule({ + imports: [ + HttpClientTestingModule, + FormsModule + ], + providers: [AuthService], declarations: [RegisterComponent] }); fixture = TestBed.createComponent(RegisterComponent); From 986900800db3a3823a694b7fd48255f14b4f3c5c Mon Sep 17 00:00:00 2001 From: GaryDev <112358055+garydev10@users.noreply.github.com> Date: Sun, 11 Jun 2023 16:13:29 +0800 Subject: [PATCH 3/5] fix ng test in Docker DevContainer for issue #1 --- angular.json | 3 ++- karma.conf.js | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 karma.conf.js diff --git a/angular.json b/angular.json index 5c2542a..8e05b2d 100644 --- a/angular.json +++ b/angular.json @@ -89,7 +89,8 @@ "styles": [ "src/styles.css" ], - "scripts": [] + "scripts": [], + "karmaConfig": "karma.conf.js" } } } diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..4d72060 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,49 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/1.0/config/configuration-file.html + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage'), + require('@angular-devkit/build-angular/plugins/karma') + ], + client: { + jasmine: { + // you can add configuration options for Jasmine here + // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html + // for example, you can disable the random execution with `random: false` + // or set a specific seed with `seed: 4321` + }, + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + jasmineHtmlReporter: { + suppressAll: true // removes the duplicated traces + }, + coverageReporter: { + dir: require('path').join(__dirname, './coverage/angular-16-jwt-auth'), + subdir: '.', + reporters: [ + { type: 'html' }, + { type: 'text-summary' } + ] + }, + reporters: ['progress', 'kjhtml'], + // browsers: ['Chrome'], + browsers: ['ChromeHeadlessNoSandbox'], + customLaunchers: { + ChromeHeadlessNoSandbox: { + base: "ChromeHeadless", + flags: [ + "--no-sandbox", + "--disable-setuid-sandbox" + ] + } + }, + restartOnFileChange: true + }); +}; From 37665c62ddaebadc913102c1ca7920c88a92916d Mon Sep 17 00:00:00 2001 From: GaryDev <112358055+garydev10@users.noreply.github.com> Date: Tue, 20 Jun 2023 11:11:56 +0800 Subject: [PATCH 4/5] Update GitHub CI test config --- karma.conf.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/karma.conf.js b/karma.conf.js index 4d72060..394f5eb 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -44,6 +44,10 @@ module.exports = function (config) { ] } }, + logLevel: config.LOG_ERROR, + autoWatch: false, + singleRun: true, + browserNoActivityTimeout: 40000, restartOnFileChange: true }); }; From 5346d380356744c253032a64231bb0e96e953ffd Mon Sep 17 00:00:00 2001 From: GaryDev <112358055+garydev10@users.noreply.github.com> Date: Sun, 14 Jul 2024 16:59:29 +0100 Subject: [PATCH 5/5] sync file with upstream repo --- src/app/register/register.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/register/register.component.ts b/src/app/register/register.component.ts index 2cd4997..0b2d193 100644 --- a/src/app/register/register.component.ts +++ b/src/app/register/register.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { AuthService } from '../_services/auth.service'; @Component({