From 7b4873455c11a5c1ea2934b46065394bf367cb29 Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Mon, 6 Jan 2025 17:19:44 -0800 Subject: [PATCH 01/11] fix google login button --- core/gui/src/app/common/service/user/google-auth.service.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/gui/src/app/common/service/user/google-auth.service.ts b/core/gui/src/app/common/service/user/google-auth.service.ts index 001d533b61c..da134938243 100644 --- a/core/gui/src/app/common/service/user/google-auth.service.ts +++ b/core/gui/src/app/common/service/user/google-auth.service.ts @@ -27,6 +27,10 @@ export class GoogleAuthService { window.google.accounts.id.renderButton(parent, { width: 200 }); window.google.accounts.id.prompt(); }; + + if (typeof window.google !== "undefined") { + window.onGoogleLibraryLoad(); + } }, error: (err: unknown) => { console.error(err); From 6ea854e71ea55fcb91e1114e82b0c9eb64227943 Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Wed, 8 Jan 2025 22:46:09 -0800 Subject: [PATCH 02/11] use promise, use window.google --- .../service/user/google-auth.service.ts | 53 +++++++++++++------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/core/gui/src/app/common/service/user/google-auth.service.ts b/core/gui/src/app/common/service/user/google-auth.service.ts index da134938243..124b6aa5b90 100644 --- a/core/gui/src/app/common/service/user/google-auth.service.ts +++ b/core/gui/src/app/common/service/user/google-auth.service.ts @@ -15,26 +15,45 @@ export class GoogleAuthService { private _googleCredentialResponse = new Subject(); constructor(private http: HttpClient) {} public googleAuthInit(parent: HTMLElement | null) { - this.http.get(`${AppSettings.getApiEndpoint()}/auth/google/clientid`, { responseType: "text" }).subscribe({ - next: response => { - window.onGoogleLibraryLoad = () => { - window.google.accounts.id.initialize({ - client_id: response, - callback: (auth: CredentialResponse) => { - this._googleCredentialResponse.next(auth); - }, - }); - window.google.accounts.id.renderButton(parent, { width: 200 }); - window.google.accounts.id.prompt(); - }; + this.waitForGoogleScript(2000) + .then(() => { + this.http.get(`${AppSettings.getApiEndpoint()}/auth/google/clientid`, { responseType: "text" }).subscribe({ + next: response => { + window.google.accounts.id.initialize({ + client_id: response, + callback: (auth: CredentialResponse) => { + this._googleCredentialResponse.next(auth); + }, + }); + window.google.accounts.id.renderButton(parent, { width: 200 }); + window.google.accounts.id.prompt(); + }, + error: (err: unknown) => { + console.error(err); + }, + }); + }) + .catch(err => { + console.error(err.message); + }); + } + + private waitForGoogleScript(timeout: number): Promise { + return new Promise((resolve, reject) => { + const interval = 100; + let elapsedTime = 0; + + const checkGoogleScript = setInterval(() => { + elapsedTime += interval; if (typeof window.google !== "undefined") { - window.onGoogleLibraryLoad(); + clearInterval(checkGoogleScript); + resolve(); + } else if (elapsedTime >= timeout) { + clearInterval(checkGoogleScript); + reject(new Error("Google script is not loaded or not available within the timeout period.")); } - }, - error: (err: unknown) => { - console.error(err); - }, + }, interval); }); } From 4d853acd9715a441cda366cc087ee5091aea8617 Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Wed, 15 Jan 2025 16:13:26 -0800 Subject: [PATCH 03/11] use angularx social login --- core/gui/package.json | 1 + core/gui/src/app/app.module.ts | 24 ++++++++ .../app/common/service/user/auth.service.ts | 8 ++- .../service/user/google-auth.service.ts | 55 ++++++------------- .../app/common/service/user/user.service.ts | 1 + .../component/dashboard.component.scss | 6 ++ .../google-login/google-login.component.html | 3 + .../google-login/google-login.component.ts | 18 +++--- core/gui/yarn.lock | 20 +++++++ 9 files changed, 87 insertions(+), 49 deletions(-) create mode 100644 core/gui/src/app/dashboard/component/user/google-login/google-login.component.html diff --git a/core/gui/package.json b/core/gui/package.json index 29a4bb0588e..6208258a3dd 100644 --- a/core/gui/package.json +++ b/core/gui/package.json @@ -21,6 +21,7 @@ }, "private": true, "dependencies": { + "@abacritt/angularx-social-login": "2.1.0", "@ali-hm/angular-tree-component": "12.0.5", "@angular/animations": "16.2.12", "@angular/cdk": "16.2.12", diff --git a/core/gui/src/app/app.module.ts b/core/gui/src/app/app.module.ts index c477a8af9c0..2045ca5af09 100644 --- a/core/gui/src/app/app.module.ts +++ b/core/gui/src/app/app.module.ts @@ -140,6 +140,10 @@ import { LandingPageComponent } from "./hub/component/landing-page/landing-page. import { BrowseSectionComponent } from "./hub/component/browse-section/browse-section.component"; import { BreakpointConditionInputComponent } from "./workspace/component/code-editor-dialog/breakpoint-condition-input/breakpoint-condition-input.component"; import { CodeDebuggerComponent } from "./workspace/component/code-editor-dialog/code-debugger.component"; +import { SocialLoginModule, SocialAuthServiceConfig, GoogleSigninButtonModule } from "@abacritt/angularx-social-login"; +import { + GoogleLoginProvider, +} from "@abacritt/angularx-social-login"; registerLocaleData(en); @@ -289,6 +293,8 @@ registerLocaleData(en); NzTreeViewModule, NzNoAnimationModule, TreeModule, + SocialLoginModule, + GoogleSigninButtonModule, ], providers: [ provideNzI18n(en_US), @@ -303,6 +309,24 @@ registerLocaleData(en); useClass: BlobErrorHttpInterceptor, multi: true, }, + { + provide: "SocialAuthServiceConfig", + useValue: { + autoLogin: false, + lang: "en", + providers: [ + { + id: GoogleLoginProvider.PROVIDER_ID, + provider: new GoogleLoginProvider( + "127689596526-if7cekkg5fv1kpva65h0cdth2l2sadts.apps.googleusercontent.com" + ), + }, + ], + onError: err => { + console.error(err); + }, + } as SocialAuthServiceConfig, + }, ], bootstrap: [AppComponent], }) diff --git a/core/gui/src/app/common/service/user/auth.service.ts b/core/gui/src/app/common/service/user/auth.service.ts index 71699e3eadd..85f875e6007 100644 --- a/core/gui/src/app/common/service/user/auth.service.ts +++ b/core/gui/src/app/common/service/user/auth.service.ts @@ -61,7 +61,13 @@ export class AuthService { public googleAuth(credential: string): Observable> { return this.http.post>( `${AppSettings.getApiEndpoint()}/${AuthService.GOOGLE_LOGIN_ENDPOINT}`, - `${credential}` + credential, + { + headers: { + "Content-Type": "text/plain", + "Accept": "application/json", + }, + } ); } diff --git a/core/gui/src/app/common/service/user/google-auth.service.ts b/core/gui/src/app/common/service/user/google-auth.service.ts index 124b6aa5b90..001d533b61c 100644 --- a/core/gui/src/app/common/service/user/google-auth.service.ts +++ b/core/gui/src/app/common/service/user/google-auth.service.ts @@ -15,45 +15,22 @@ export class GoogleAuthService { private _googleCredentialResponse = new Subject(); constructor(private http: HttpClient) {} public googleAuthInit(parent: HTMLElement | null) { - this.waitForGoogleScript(2000) - .then(() => { - this.http.get(`${AppSettings.getApiEndpoint()}/auth/google/clientid`, { responseType: "text" }).subscribe({ - next: response => { - window.google.accounts.id.initialize({ - client_id: response, - callback: (auth: CredentialResponse) => { - this._googleCredentialResponse.next(auth); - }, - }); - window.google.accounts.id.renderButton(parent, { width: 200 }); - window.google.accounts.id.prompt(); - }, - error: (err: unknown) => { - console.error(err); - }, - }); - }) - .catch(err => { - console.error(err.message); - }); - } - - private waitForGoogleScript(timeout: number): Promise { - return new Promise((resolve, reject) => { - const interval = 100; - let elapsedTime = 0; - - const checkGoogleScript = setInterval(() => { - elapsedTime += interval; - - if (typeof window.google !== "undefined") { - clearInterval(checkGoogleScript); - resolve(); - } else if (elapsedTime >= timeout) { - clearInterval(checkGoogleScript); - reject(new Error("Google script is not loaded or not available within the timeout period.")); - } - }, interval); + this.http.get(`${AppSettings.getApiEndpoint()}/auth/google/clientid`, { responseType: "text" }).subscribe({ + next: response => { + window.onGoogleLibraryLoad = () => { + window.google.accounts.id.initialize({ + client_id: response, + callback: (auth: CredentialResponse) => { + this._googleCredentialResponse.next(auth); + }, + }); + window.google.accounts.id.renderButton(parent, { width: 200 }); + window.google.accounts.id.prompt(); + }; + }, + error: (err: unknown) => { + console.error(err); + }, }); } diff --git a/core/gui/src/app/common/service/user/user.service.ts b/core/gui/src/app/common/service/user/user.service.ts index 9517e931604..bebc4ed7afb 100644 --- a/core/gui/src/app/common/service/user/user.service.ts +++ b/core/gui/src/app/common/service/user/user.service.ts @@ -53,6 +53,7 @@ export class UserService { } public logout(): void { + console.log("log out!!!!!") this.authService.logout(); this.changeUser(undefined); } diff --git a/core/gui/src/app/dashboard/component/dashboard.component.scss b/core/gui/src/app/dashboard/component/dashboard.component.scss index c51701e4c64..22491879e99 100644 --- a/core/gui/src/app/dashboard/component/dashboard.component.scss +++ b/core/gui/src/app/dashboard/component/dashboard.component.scss @@ -70,3 +70,9 @@ nz-content { .hidden { display: none; } + +#nav { + max-width: 100%; + max-height: 100%; + overflow: hidden; +} diff --git a/core/gui/src/app/dashboard/component/user/google-login/google-login.component.html b/core/gui/src/app/dashboard/component/user/google-login/google-login.component.html new file mode 100644 index 00000000000..b4520afa3f1 --- /dev/null +++ b/core/gui/src/app/dashboard/component/user/google-login/google-login.component.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/core/gui/src/app/dashboard/component/user/google-login/google-login.component.ts b/core/gui/src/app/dashboard/component/user/google-login/google-login.component.ts index f446a337d1a..e7d666bc2f9 100644 --- a/core/gui/src/app/dashboard/component/user/google-login/google-login.component.ts +++ b/core/gui/src/app/dashboard/component/user/google-login/google-login.component.ts @@ -1,31 +1,31 @@ -import { AfterViewInit, Component, ElementRef, ViewChild } from "@angular/core"; +import { Component, ElementRef, OnInit, ViewChild } from "@angular/core"; import { UserService } from "../../../../common/service/user/user.service"; import { mergeMap } from "rxjs/operators"; import { GoogleAuthService } from "../../../../common/service/user/google-auth.service"; import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; import { DASHBOARD_USER_WORKFLOW } from "../../../../app-routing.constant"; import { ActivatedRoute, Router } from "@angular/router"; +import { SocialAuthService } from "@abacritt/angularx-social-login"; @UntilDestroy() @Component({ selector: "texera-google-login", - template: "", + templateUrl: "./google-login.component.html", }) -export class GoogleLoginComponent implements AfterViewInit { +export class GoogleLoginComponent implements OnInit { @ViewChild("googleButton") googleButton!: ElementRef; constructor( private userService: UserService, private route: ActivatedRoute, - private googleAuthService: GoogleAuthService, private router: Router, - private elementRef: ElementRef + private elementRef: ElementRef, + private socialAuthService: SocialAuthService ) {} - ngAfterViewInit(): void { - this.googleAuthService.googleAuthInit(this.elementRef.nativeElement); - this.googleAuthService.googleCredentialResponse + ngOnInit() { + this.socialAuthService.authState .pipe( - mergeMap(res => this.userService.googleLogin(res.credential)), + mergeMap(res => this.userService.googleLogin(res.idToken)), untilDestroyed(this) ) .subscribe(() => { diff --git a/core/gui/yarn.lock b/core/gui/yarn.lock index 5926766289c..8bbe7249723 100644 --- a/core/gui/yarn.lock +++ b/core/gui/yarn.lock @@ -5,6 +5,18 @@ __metadata: version: 8 cacheKey: 10c0 +"@abacritt/angularx-social-login@npm:2.1.0": + version: 2.1.0 + resolution: "@abacritt/angularx-social-login@npm:2.1.0" + dependencies: + tslib: "npm:>=2.5.0" + peerDependencies: + "@angular/common": ">=16.0.0" + "@angular/core": ">=16.0.0" + checksum: 10c0/b1759db0d79fdbc902180aa1974c5aa8db5372a7c4750127bbf5b1d94aadeb1f7bad27a0ac488e98cbe53a600a438a3900b4974009e4a648df5edf583cc5eb0d + languageName: node + linkType: hard + "@adobe/css-tools@npm:^4.0.1": version: 4.4.0 resolution: "@adobe/css-tools@npm:4.4.0" @@ -11066,6 +11078,7 @@ __metadata: version: 0.0.0-use.local resolution: "gui@workspace:." dependencies: + "@abacritt/angularx-social-login": "npm:2.1.0" "@ali-hm/angular-tree-component": "npm:12.0.5" "@angular-builders/custom-webpack": "npm:16.0.1" "@angular-devkit/build-angular": "npm:16.2.12" @@ -17971,6 +17984,13 @@ __metadata: languageName: node linkType: hard +"tslib@npm:>=2.5.0": + version: 2.8.1 + resolution: "tslib@npm:2.8.1" + checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62 + languageName: node + linkType: hard + "tslib@npm:^1.6.0, tslib@npm:^1.8.1": version: 1.14.1 resolution: "tslib@npm:1.14.1" From ea41a249b2d1a1834d3e623f747dd6a4d7e302db Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Wed, 15 Jan 2025 17:57:17 -0800 Subject: [PATCH 04/11] update --- .../src/app/dashboard/component/dashboard.component.html | 2 +- .../user/google-login/google-login.component.html | 2 +- .../user/google-login/google-login.component.ts | 9 +++------ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/core/gui/src/app/dashboard/component/dashboard.component.html b/core/gui/src/app/dashboard/component/dashboard.component.html index 059146949be..3d32b127bfd 100644 --- a/core/gui/src/app/dashboard/component/dashboard.component.html +++ b/core/gui/src/app/dashboard/component/dashboard.component.html @@ -141,7 +141,7 @@
diff --git a/core/gui/src/app/dashboard/component/dashboard.component.spec.ts b/core/gui/src/app/dashboard/component/dashboard.component.spec.ts new file mode 100644 index 00000000000..ae0551ee597 --- /dev/null +++ b/core/gui/src/app/dashboard/component/dashboard.component.spec.ts @@ -0,0 +1,72 @@ +import { ComponentFixture, TestBed } from "@angular/core/testing"; +import { DashboardComponent } from "./dashboard.component"; +import { UserService } from "../../common/service/user/user.service"; +import { SocialAuthService } from "@abacritt/angularx-social-login"; +import { Router } from "@angular/router"; +import { RouterTestingModule } from "@angular/router/testing"; +import { BehaviorSubject } from "rxjs"; +import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; +import { DASHBOARD_USER_WORKFLOW } from "../../app-routing.constant"; + +describe("DashboardComponent", () => { + let component: DashboardComponent; + let fixture: ComponentFixture; + let userServiceMock: jasmine.SpyObj; + let socialAuthServiceMock: jasmine.SpyObj; + let routerMock: jasmine.SpyObj; + let authStateMock: BehaviorSubject; + + beforeEach(async () => { + userServiceMock = jasmine.createSpyObj("UserService", ["isLogin", "isAdmin"]); + userServiceMock.isLogin.and.returnValue(false); + userServiceMock.isAdmin.and.returnValue(false); + + authStateMock = new BehaviorSubject(null); + socialAuthServiceMock = jasmine.createSpyObj("SocialAuthService", [], { + authState: authStateMock.asObservable(), + }); + + routerMock = jasmine.createSpyObj("Router", ["navigateByUrl"]); + + await TestBed.configureTestingModule({ + imports: [RouterTestingModule], + declarations: [DashboardComponent], + providers: [ + { provide: UserService, useValue: userServiceMock }, + { provide: SocialAuthService, useValue: socialAuthServiceMock }, + { provide: Router, useValue: routerMock }, + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DashboardComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it("should render Google login button when user is NOT logged in", () => { + const compiled = fixture.nativeElement; + const googleSignInButton = compiled.querySelector("asl-google-signin-button"); + + expect(googleSignInButton).toBeTruthy(); + }); + + it("should NOT render Google login button when user IS logged in", () => { + userServiceMock.isLogin.and.returnValue(true); + fixture.detectChanges(); + + const compiled = fixture.nativeElement; + const googleSignInButton = compiled.querySelector("asl-google-signin-button"); + + expect(googleSignInButton).toBeFalsy(); + }); + + it("should redirect to DASHBOARD_USER_WORKFLOW after Google login", () => { + authStateMock.next({ idToken: "test_token" } as any); + fixture.detectChanges(); + + expect(routerMock.navigateByUrl).toHaveBeenCalledWith(DASHBOARD_USER_WORKFLOW); + }); +}); diff --git a/core/gui/src/app/dashboard/component/dashboard.component.ts b/core/gui/src/app/dashboard/component/dashboard.component.ts index f825801c71e..4f52ce5a81d 100644 --- a/core/gui/src/app/dashboard/component/dashboard.component.ts +++ b/core/gui/src/app/dashboard/component/dashboard.component.ts @@ -3,8 +3,10 @@ import { UserService } from "../../common/service/user/user.service"; import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; import { FlarumService } from "../service/user/flarum/flarum.service"; import { HttpErrorResponse } from "@angular/common/http"; -import { NavigationEnd, Router } from "@angular/router"; +import { ActivatedRoute, NavigationEnd, Router } from "@angular/router"; import { HubComponent } from "../../hub/component/hub.component"; +import { SocialAuthService } from "@abacritt/angularx-social-login"; +import { filter, switchMap } from "rxjs/operators"; import { DASHBOARD_ADMIN_EXECUTION, @@ -47,13 +49,12 @@ export class DashboardComponent implements OnInit { private router: Router, private flarumService: FlarumService, private cdr: ChangeDetectorRef, - private ngZone: NgZone + private ngZone: NgZone, + private socialAuthService: SocialAuthService, + private route: ActivatedRoute ) {} ngOnInit(): void { - this.isLogin = this.userService.isLogin(); - this.isAdmin = this.userService.isAdmin(); - this.isCollpased = false; this.router.events.pipe(untilDestroyed(this)).subscribe(() => { @@ -78,6 +79,20 @@ export class DashboardComponent implements OnInit { this.cdr.detectChanges(); }); }); + + if (!this.isLogin) { + this.socialAuthService.authState + .pipe( + filter(res => !!res), + switchMap(res => this.userService.googleLogin(res.idToken)), + untilDestroyed(this) + ) + .subscribe(() => { + this.ngZone.run(() => { + this.router.navigateByUrl(this.route.snapshot.queryParams["returnUrl"] || DASHBOARD_USER_WORKFLOW); + }); + }); + } } forumLogin() { diff --git a/core/gui/src/app/dashboard/component/user/google-login/google-login.component.html b/core/gui/src/app/dashboard/component/user/google-login/google-login.component.html deleted file mode 100644 index cfd91e483d8..00000000000 --- a/core/gui/src/app/dashboard/component/user/google-login/google-login.component.html +++ /dev/null @@ -1,6 +0,0 @@ -
- -
diff --git a/core/gui/src/app/dashboard/component/user/google-login/google-login.component.spec.ts b/core/gui/src/app/dashboard/component/user/google-login/google-login.component.spec.ts deleted file mode 100644 index 884e6662515..00000000000 --- a/core/gui/src/app/dashboard/component/user/google-login/google-login.component.spec.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { ComponentFixture, TestBed } from "@angular/core/testing"; -import { GoogleLoginComponent } from "./google-login.component"; -import { HttpClientTestingModule } from "@angular/common/http/testing"; -import { RouterTestingModule } from "@angular/router/testing"; -import { UserService } from "../../../../common/service/user/user.service"; -import { SocialAuthService } from "@abacritt/angularx-social-login"; -import { of } from "rxjs"; - -describe("GoogleLoginComponent", () => { - let component: GoogleLoginComponent; - let fixture: ComponentFixture; - let userService: jasmine.SpyObj; - let socialAuthService: jasmine.SpyObj; - - beforeEach(async () => { - const userServiceSpy = jasmine.createSpyObj("UserService", ["googleLogin"]); - const socialAuthServiceSpy = jasmine.createSpyObj("SocialAuthService", [], { - authState: of({ idToken: "mock-id-token" }), - }); - - await TestBed.configureTestingModule({ - imports: [HttpClientTestingModule, RouterTestingModule], - declarations: [GoogleLoginComponent], - providers: [ - { provide: UserService, useValue: userServiceSpy }, - { provide: SocialAuthService, useValue: socialAuthServiceSpy }, - ], - }).compileComponents(); - - fixture = TestBed.createComponent(GoogleLoginComponent); - component = fixture.componentInstance; - userService = TestBed.inject(UserService) as jasmine.SpyObj; - socialAuthService = TestBed.inject(SocialAuthService) as jasmine.SpyObj; - }); - - it("should create the component", () => { - expect(component).toBeTruthy(); - }); - - it("should render Google Sign-In button", () => { - const compiled = fixture.nativeElement as HTMLElement; - const button = compiled.querySelector("asl-google-signin-button"); - expect(button).toBeTruthy(); - }); -}); diff --git a/core/gui/src/app/dashboard/component/user/google-login/google-login.component.ts b/core/gui/src/app/dashboard/component/user/google-login/google-login.component.ts deleted file mode 100644 index 3efe60667a9..00000000000 --- a/core/gui/src/app/dashboard/component/user/google-login/google-login.component.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { AfterViewInit, Component } from "@angular/core"; -import { UserService } from "../../../../common/service/user/user.service"; -import { mergeMap } from "rxjs/operators"; -import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; -import { DASHBOARD_USER_WORKFLOW } from "../../../../app-routing.constant"; -import { ActivatedRoute, Router } from "@angular/router"; -import { SocialAuthService } from "@abacritt/angularx-social-login"; - -@UntilDestroy() -@Component({ - selector: "texera-google-login", - templateUrl: "./google-login.component.html", -}) -export class GoogleLoginComponent implements AfterViewInit { - constructor( - private userService: UserService, - private route: ActivatedRoute, - private router: Router, - private socialAuthService: SocialAuthService - ) {} - - ngAfterViewInit() { - this.socialAuthService.authState - .pipe( - mergeMap(res => this.userService.googleLogin(res.idToken)), - untilDestroyed(this) - ) - .subscribe(() => { - this.router.navigateByUrl(this.route.snapshot.queryParams["returnUrl"] || DASHBOARD_USER_WORKFLOW); - }); - } -} From 3d2fd0fbcfa6c5b546ece6a843c9283aa5af973d Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Fri, 17 Jan 2025 15:16:38 -0800 Subject: [PATCH 09/11] fix unit test --- .../dashboard/component/dashboard.component.spec.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/core/gui/src/app/dashboard/component/dashboard.component.spec.ts b/core/gui/src/app/dashboard/component/dashboard.component.spec.ts index ae0551ee597..223c1927f16 100644 --- a/core/gui/src/app/dashboard/component/dashboard.component.spec.ts +++ b/core/gui/src/app/dashboard/component/dashboard.component.spec.ts @@ -2,9 +2,11 @@ import { ComponentFixture, TestBed } from "@angular/core/testing"; import { DashboardComponent } from "./dashboard.component"; import { UserService } from "../../common/service/user/user.service"; import { SocialAuthService } from "@abacritt/angularx-social-login"; +import { FlarumService } from "../service/user/flarum/flarum.service"; import { Router } from "@angular/router"; import { RouterTestingModule } from "@angular/router/testing"; -import { BehaviorSubject } from "rxjs"; +import { HttpClientTestingModule } from "@angular/common/http/testing"; +import { of, BehaviorSubject } from "rxjs"; import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; import { DASHBOARD_USER_WORKFLOW } from "../../app-routing.constant"; @@ -13,6 +15,7 @@ describe("DashboardComponent", () => { let fixture: ComponentFixture; let userServiceMock: jasmine.SpyObj; let socialAuthServiceMock: jasmine.SpyObj; + let flarumServiceMock: jasmine.SpyObj; let routerMock: jasmine.SpyObj; let authStateMock: BehaviorSubject; @@ -26,14 +29,17 @@ describe("DashboardComponent", () => { authState: authStateMock.asObservable(), }); + flarumServiceMock = jasmine.createSpyObj("FlarumService", ["auth", "register"]); + routerMock = jasmine.createSpyObj("Router", ["navigateByUrl"]); await TestBed.configureTestingModule({ - imports: [RouterTestingModule], + imports: [RouterTestingModule, HttpClientTestingModule], declarations: [DashboardComponent], providers: [ { provide: UserService, useValue: userServiceMock }, { provide: SocialAuthService, useValue: socialAuthServiceMock }, + { provide: FlarumService, useValue: flarumServiceMock }, { provide: Router, useValue: routerMock }, ], schemas: [CUSTOM_ELEMENTS_SCHEMA], From 6ac8cbdd4295df8bb9fb5b059ac267c583573b24 Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Fri, 17 Jan 2025 15:26:01 -0800 Subject: [PATCH 10/11] fix unit test --- .../component/dashboard.component.spec.ts | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/core/gui/src/app/dashboard/component/dashboard.component.spec.ts b/core/gui/src/app/dashboard/component/dashboard.component.spec.ts index 223c1927f16..83f59cfdbaf 100644 --- a/core/gui/src/app/dashboard/component/dashboard.component.spec.ts +++ b/core/gui/src/app/dashboard/component/dashboard.component.spec.ts @@ -3,12 +3,12 @@ import { DashboardComponent } from "./dashboard.component"; import { UserService } from "../../common/service/user/user.service"; import { SocialAuthService } from "@abacritt/angularx-social-login"; import { FlarumService } from "../service/user/flarum/flarum.service"; -import { Router } from "@angular/router"; +import { Router, ActivatedRoute } from "@angular/router"; import { RouterTestingModule } from "@angular/router/testing"; import { HttpClientTestingModule } from "@angular/common/http/testing"; import { of, BehaviorSubject } from "rxjs"; import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; -import { DASHBOARD_USER_WORKFLOW } from "../../app-routing.constant"; +import {DASHBOARD_USER_WORKFLOW} from "../../app-routing.constant"; describe("DashboardComponent", () => { let component: DashboardComponent; @@ -17,12 +17,15 @@ describe("DashboardComponent", () => { let socialAuthServiceMock: jasmine.SpyObj; let flarumServiceMock: jasmine.SpyObj; let routerMock: jasmine.SpyObj; + let activatedRouteMock: any; let authStateMock: BehaviorSubject; beforeEach(async () => { - userServiceMock = jasmine.createSpyObj("UserService", ["isLogin", "isAdmin"]); + userServiceMock = jasmine.createSpyObj("UserService", ["isLogin", "isAdmin", "userChanged", "googleLogin"]); userServiceMock.isLogin.and.returnValue(false); userServiceMock.isAdmin.and.returnValue(false); + userServiceMock.userChanged.and.returnValue(of(undefined)); + userServiceMock.googleLogin.and.returnValue(of(undefined)); authStateMock = new BehaviorSubject(null); socialAuthServiceMock = jasmine.createSpyObj("SocialAuthService", [], { @@ -30,17 +33,29 @@ describe("DashboardComponent", () => { }); flarumServiceMock = jasmine.createSpyObj("FlarumService", ["auth", "register"]); + flarumServiceMock.auth.and.returnValue(of({ token: "fake_token" })); + flarumServiceMock.register.and.returnValue(of()); routerMock = jasmine.createSpyObj("Router", ["navigateByUrl"]); + activatedRouteMock = { + snapshot: { + queryParams: {}, + }, + }; + await TestBed.configureTestingModule({ - imports: [RouterTestingModule, HttpClientTestingModule], + imports: [ + RouterTestingModule.withRoutes([]), // 确保 Router 正常工作 + HttpClientTestingModule, + ], declarations: [DashboardComponent], providers: [ { provide: UserService, useValue: userServiceMock }, { provide: SocialAuthService, useValue: socialAuthServiceMock }, { provide: FlarumService, useValue: flarumServiceMock }, { provide: Router, useValue: routerMock }, + { provide: ActivatedRoute, useValue: activatedRouteMock }, ], schemas: [CUSTOM_ELEMENTS_SCHEMA], }).compileComponents(); From 1f392ba9a7547d2bfbcf0f2d3f42e4f86de3b076 Mon Sep 17 00:00:00 2001 From: gspikehalo <2318002579@qq.com> Date: Fri, 17 Jan 2025 15:31:44 -0800 Subject: [PATCH 11/11] fmt fix --- .../gui/src/app/dashboard/component/dashboard.component.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/gui/src/app/dashboard/component/dashboard.component.spec.ts b/core/gui/src/app/dashboard/component/dashboard.component.spec.ts index 83f59cfdbaf..7318d330f2c 100644 --- a/core/gui/src/app/dashboard/component/dashboard.component.spec.ts +++ b/core/gui/src/app/dashboard/component/dashboard.component.spec.ts @@ -8,7 +8,7 @@ import { RouterTestingModule } from "@angular/router/testing"; import { HttpClientTestingModule } from "@angular/common/http/testing"; import { of, BehaviorSubject } from "rxjs"; import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; -import {DASHBOARD_USER_WORKFLOW} from "../../app-routing.constant"; +import { DASHBOARD_USER_WORKFLOW } from "../../app-routing.constant"; describe("DashboardComponent", () => { let component: DashboardComponent;