From 9678ccbfc65602d52dfeda06a47ec035569e37b2 Mon Sep 17 00:00:00 2001 From: styve Lioumba Date: Sun, 5 Oct 2025 15:06:14 +0200 Subject: [PATCH] correctif des tests et du workflow ci --- .github/workflows/ci.yaml | 4 +- jest.config.js | 1 + src/app/app.component.spec.ts | 11 ++- .../profile/list/list.resolver.spec.ts | 7 +- .../authentication/auth.service.spec.ts | 10 ++- .../services/profile/profile.service.spec.ts | 13 ++- .../services/project/project.service.spec.ts | 13 ++- .../services/sector/sector.service.spec.ts | 13 ++- .../core/services/theme/theme.service.spec.ts | 13 ++- .../core/services/user/user.service.spec.ts | 13 ++- .../auth/auth.component.spec.ts | 2 + .../my-profile/my-profile.component.spec.ts | 2 + .../profile-detail.component.spec.ts | 2 + .../my-home-profile.component.spec.ts | 4 +- .../my-profile-project-item.component.spec.ts | 4 +- .../project-list.component.spec.ts | 4 +- .../vertical-profile-list.component.spec.ts | 13 ++- .../features/login/login.component.spec.ts | 4 +- .../pdf-viewer/pdf-viewer.component.spec.ts | 2 + .../register/register.component.spec.ts | 2 + .../features/search/search.component.spec.ts | 4 +- src/environments/environment.ts | 2 +- src/setup-jest.ts | 89 +++++++++++++++++-- 23 files changed, 207 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5a14efc..97b9e59 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -2,7 +2,9 @@ name: Docker Build Check # Déclencheur pour chaque pull request on: - workflow_call: + push: + branches: ['**'] + pull_request: jobs: build: diff --git a/jest.config.js b/jest.config.js index fa73e52..2131a65 100644 --- a/jest.config.js +++ b/jest.config.js @@ -13,4 +13,5 @@ module.exports = { '^@app/(.*)$': '/src/app/$1', '^@env/(.*)$': '/src/environments/$1', }, + testTimeout: 30000, }; diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index 90e06de..6a9df2a 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -1,9 +1,12 @@ -import { TestBed } from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; import { AppComponent } from './app.component'; import {provideRouter} from "@angular/router"; import {ThemeService} from "@app/core/services/theme/theme.service"; +import {ProfileDetailComponent} from "@app/routes/profile/profile-detail/profile-detail.component"; describe('AppComponent', () => { + let component: AppComponent; + let fixture: ComponentFixture; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -12,6 +15,12 @@ describe('AppComponent', () => { provideRouter([]) ], }).compileComponents(); + + fixture = TestBed.createComponent(AppComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + + await fixture.whenStable(); }); it('should create the app', () => { diff --git a/src/app/core/resolvers/profile/list/list.resolver.spec.ts b/src/app/core/resolvers/profile/list/list.resolver.spec.ts index a5d6002..2605a27 100644 --- a/src/app/core/resolvers/profile/list/list.resolver.spec.ts +++ b/src/app/core/resolvers/profile/list/list.resolver.spec.ts @@ -10,6 +10,10 @@ import {Observable, of} from "rxjs"; describe('listResolver', () => { let mockProfileService: Partial; + const routerSpy = { + navigate: jest.fn(), + navigateByUrl: jest.fn(), + }; beforeEach(() => { @@ -19,7 +23,8 @@ describe('listResolver', () => { TestBed.configureTestingModule({ providers: [ - { provide: ProfileService, useValue: mockProfileService } + { provide: ProfileService, useValue: mockProfileService }, + { provide: Router, useValue: routerSpy }, // <<— spy: neutralise la navigation ] }); }); diff --git a/src/app/core/services/authentication/auth.service.spec.ts b/src/app/core/services/authentication/auth.service.spec.ts index 7a56624..fd432f0 100644 --- a/src/app/core/services/authentication/auth.service.spec.ts +++ b/src/app/core/services/authentication/auth.service.spec.ts @@ -4,6 +4,7 @@ import {AuthService} from './auth.service'; import {LoginDto} from "@app/shared/models/login-dto"; import {RegisterDto} from "@app/shared/models/register-dto"; import {User} from "@app/shared/models/user"; +import {Router} from "@angular/router"; describe('AuthService', () => { let authService: AuthService; @@ -37,9 +38,16 @@ describe('AuthService', () => { authStore: mockAuthStore, })); + const routerSpy = { + navigate: jest.fn(), + navigateByUrl: jest.fn(), + }; + beforeEach(() => { TestBed.configureTestingModule({ - providers: [], + providers: [ + { provide: Router, useValue: routerSpy }, // <<— spy: neutralise la navigation + ], imports: [] }); authService = TestBed.inject(AuthService); diff --git a/src/app/core/services/profile/profile.service.spec.ts b/src/app/core/services/profile/profile.service.spec.ts index 704eab5..e7edca2 100644 --- a/src/app/core/services/profile/profile.service.spec.ts +++ b/src/app/core/services/profile/profile.service.spec.ts @@ -1,12 +1,23 @@ import { TestBed } from '@angular/core/testing'; import { ProfileService } from './profile.service'; +import {Router} from "@angular/router"; describe('ProfileService', () => { let service: ProfileService; + const routerSpy = { + navigate: jest.fn(), + navigateByUrl: jest.fn(), + }; + beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + providers: [ + { provide: Router, useValue: routerSpy }, // <<— spy: neutralise la navigation + ], + imports: [] + }); service = TestBed.inject(ProfileService); }); diff --git a/src/app/core/services/project/project.service.spec.ts b/src/app/core/services/project/project.service.spec.ts index 545f0f0..48564aa 100644 --- a/src/app/core/services/project/project.service.spec.ts +++ b/src/app/core/services/project/project.service.spec.ts @@ -1,12 +1,23 @@ import { TestBed } from '@angular/core/testing'; import { ProjectService } from './project.service'; +import {Router} from "@angular/router"; describe('ProjectService', () => { let service: ProjectService; + const routerSpy = { + navigate: jest.fn(), + navigateByUrl: jest.fn(), + }; + beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + providers: [ + { provide: Router, useValue: routerSpy }, // <<— spy: neutralise la navigation + ], + imports: [] + }); service = TestBed.inject(ProjectService); }); diff --git a/src/app/core/services/sector/sector.service.spec.ts b/src/app/core/services/sector/sector.service.spec.ts index ec63383..234b657 100644 --- a/src/app/core/services/sector/sector.service.spec.ts +++ b/src/app/core/services/sector/sector.service.spec.ts @@ -1,12 +1,23 @@ import { TestBed } from '@angular/core/testing'; import { SectorService } from './sector.service'; +import {Router} from "@angular/router"; describe('SectorService', () => { let service: SectorService; + const routerSpy = { + navigate: jest.fn(), + navigateByUrl: jest.fn(), + }; + beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + providers: [ + { provide: Router, useValue: routerSpy }, // <<— spy: neutralise la navigation + ], + imports: [] + }); service = TestBed.inject(SectorService); }); diff --git a/src/app/core/services/theme/theme.service.spec.ts b/src/app/core/services/theme/theme.service.spec.ts index dad28a5..0bffc5d 100644 --- a/src/app/core/services/theme/theme.service.spec.ts +++ b/src/app/core/services/theme/theme.service.spec.ts @@ -1,12 +1,23 @@ import { TestBed } from '@angular/core/testing'; import { ThemeService } from './theme.service'; +import {Router} from "@angular/router"; describe('ThemeService', () => { let service: ThemeService; + const routerSpy = { + navigate: jest.fn(), + navigateByUrl: jest.fn(), + }; + beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + providers: [ + { provide: Router, useValue: routerSpy }, // <<— spy: neutralise la navigation + ], + imports: [] + }); service = TestBed.inject(ThemeService); }); diff --git a/src/app/core/services/user/user.service.spec.ts b/src/app/core/services/user/user.service.spec.ts index 5fcf668..44fcfbe 100644 --- a/src/app/core/services/user/user.service.spec.ts +++ b/src/app/core/services/user/user.service.spec.ts @@ -1,12 +1,23 @@ import { TestBed } from '@angular/core/testing'; import { UserService } from './user.service'; +import {Router} from "@angular/router"; describe('UserService', () => { let service: UserService; + const routerSpy = { + navigate: jest.fn(), + navigateByUrl: jest.fn(), + }; + beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + providers: [ + { provide: Router, useValue: routerSpy }, // <<— spy: neutralise la navigation + ], + imports: [] + }); service = TestBed.inject(UserService); }); diff --git a/src/app/routes/authentification/auth/auth.component.spec.ts b/src/app/routes/authentification/auth/auth.component.spec.ts index fc87f68..c0fdb63 100644 --- a/src/app/routes/authentification/auth/auth.component.spec.ts +++ b/src/app/routes/authentification/auth/auth.component.spec.ts @@ -19,6 +19,8 @@ describe('AuthComponent', () => { fixture = TestBed.createComponent(AuthComponent); component = fixture.componentInstance; fixture.detectChanges(); + + await fixture.whenStable(); }); it('should create', () => { diff --git a/src/app/routes/my-profile/my-profile.component.spec.ts b/src/app/routes/my-profile/my-profile.component.spec.ts index 2e38e6d..1280b8e 100644 --- a/src/app/routes/my-profile/my-profile.component.spec.ts +++ b/src/app/routes/my-profile/my-profile.component.spec.ts @@ -19,6 +19,8 @@ describe('MyProfileComponent', () => { fixture = TestBed.createComponent(MyProfileComponent); component = fixture.componentInstance; fixture.detectChanges(); + + await fixture.whenStable(); }); it('should create', () => { diff --git a/src/app/routes/profile/profile-detail/profile-detail.component.spec.ts b/src/app/routes/profile/profile-detail/profile-detail.component.spec.ts index 8d44ba0..b9f86ee 100644 --- a/src/app/routes/profile/profile-detail/profile-detail.component.spec.ts +++ b/src/app/routes/profile/profile-detail/profile-detail.component.spec.ts @@ -19,6 +19,8 @@ describe('ProfileDetailComponent', () => { fixture = TestBed.createComponent(ProfileDetailComponent); component = fixture.componentInstance; fixture.detectChanges(); + + await fixture.whenStable(); }); it('should create', () => { diff --git a/src/app/shared/components/my-home-profile/my-home-profile.component.spec.ts b/src/app/shared/components/my-home-profile/my-home-profile.component.spec.ts index 2dbd60f..710b92d 100644 --- a/src/app/shared/components/my-home-profile/my-home-profile.component.spec.ts +++ b/src/app/shared/components/my-home-profile/my-home-profile.component.spec.ts @@ -11,10 +11,12 @@ describe('MyHomeProfileComponent', () => { imports: [MyHomeProfileComponent] }) .compileComponents(); - + fixture = TestBed.createComponent(MyHomeProfileComponent); component = fixture.componentInstance; fixture.detectChanges(); + + await fixture.whenStable(); }); it('should create', () => { diff --git a/src/app/shared/components/my-profile-project-item/my-profile-project-item.component.spec.ts b/src/app/shared/components/my-profile-project-item/my-profile-project-item.component.spec.ts index b2842a4..1998bf0 100644 --- a/src/app/shared/components/my-profile-project-item/my-profile-project-item.component.spec.ts +++ b/src/app/shared/components/my-profile-project-item/my-profile-project-item.component.spec.ts @@ -11,10 +11,12 @@ describe('MyProfileProjectItemComponent', () => { imports: [MyProfileProjectItemComponent] }) .compileComponents(); - + fixture = TestBed.createComponent(MyProfileProjectItemComponent); component = fixture.componentInstance; fixture.detectChanges(); + + await fixture.whenStable(); }); it('should create', () => { diff --git a/src/app/shared/components/project-list/project-list.component.spec.ts b/src/app/shared/components/project-list/project-list.component.spec.ts index ba2b1fa..407752f 100644 --- a/src/app/shared/components/project-list/project-list.component.spec.ts +++ b/src/app/shared/components/project-list/project-list.component.spec.ts @@ -11,10 +11,12 @@ describe('ProjectListComponent', () => { imports: [ProjectListComponent] }) .compileComponents(); - + fixture = TestBed.createComponent(ProjectListComponent); component = fixture.componentInstance; fixture.detectChanges(); + + await fixture.whenStable(); }); it('should create', () => { diff --git a/src/app/shared/components/vertical-profile-list/vertical-profile-list.component.spec.ts b/src/app/shared/components/vertical-profile-list/vertical-profile-list.component.spec.ts index 6336d27..915e871 100644 --- a/src/app/shared/components/vertical-profile-list/vertical-profile-list.component.spec.ts +++ b/src/app/shared/components/vertical-profile-list/vertical-profile-list.component.spec.ts @@ -1,20 +1,29 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { VerticalProfileListComponent } from './vertical-profile-list.component'; +import {Router} from "@angular/router"; describe('VerticalProfileListComponent', () => { let component: VerticalProfileListComponent; let fixture: ComponentFixture; + const routerSpy = { + navigate: jest.fn(), + navigateByUrl: jest.fn(), + }; + beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [VerticalProfileListComponent] + imports: [VerticalProfileListComponent], + providers: [{ provide: Router, useValue: routerSpy }], }) .compileComponents(); - + fixture = TestBed.createComponent(VerticalProfileListComponent); component = fixture.componentInstance; fixture.detectChanges(); + + await fixture.whenStable(); }); it('should create', () => { diff --git a/src/app/shared/features/login/login.component.spec.ts b/src/app/shared/features/login/login.component.spec.ts index ebbfad5..eaf3734 100644 --- a/src/app/shared/features/login/login.component.spec.ts +++ b/src/app/shared/features/login/login.component.spec.ts @@ -4,7 +4,7 @@ import {LoginComponent} from './login.component'; import {AuthService} from "@app/core/services/authentication/auth.service"; import {ToastrService} from "ngx-toastr"; import {FormBuilder} from "@angular/forms"; -import {provideRouter} from "@angular/router"; +import {provideRouter, Router} from "@angular/router"; describe('LoginComponent', () => { let component: LoginComponent; @@ -40,6 +40,8 @@ describe('LoginComponent', () => { fixture = TestBed.createComponent(LoginComponent); component = fixture.componentInstance; fixture.detectChanges(); + + await fixture.whenStable(); }); afterEach(() => { diff --git a/src/app/shared/features/pdf-viewer/pdf-viewer.component.spec.ts b/src/app/shared/features/pdf-viewer/pdf-viewer.component.spec.ts index 6ad95de..46ae1fe 100644 --- a/src/app/shared/features/pdf-viewer/pdf-viewer.component.spec.ts +++ b/src/app/shared/features/pdf-viewer/pdf-viewer.component.spec.ts @@ -24,6 +24,8 @@ describe('PdfViewerComponent', () => { component.profile = mockProfile; fixture.detectChanges(); + + await fixture.whenStable(); }); it('should create', () => { diff --git a/src/app/shared/features/register/register.component.spec.ts b/src/app/shared/features/register/register.component.spec.ts index ff97b4e..b23696d 100644 --- a/src/app/shared/features/register/register.component.spec.ts +++ b/src/app/shared/features/register/register.component.spec.ts @@ -44,6 +44,8 @@ describe('RegisterComponent', () => { fixture = TestBed.createComponent(RegisterComponent); component = fixture.componentInstance; fixture.detectChanges(); + + await fixture.whenStable(); }); it('should create', () => { diff --git a/src/app/shared/features/search/search.component.spec.ts b/src/app/shared/features/search/search.component.spec.ts index 6882bb0..17cd0ef 100644 --- a/src/app/shared/features/search/search.component.spec.ts +++ b/src/app/shared/features/search/search.component.spec.ts @@ -11,10 +11,12 @@ describe('SearchComponent', () => { imports: [SearchComponent] }) .compileComponents(); - + fixture = TestBed.createComponent(SearchComponent); component = fixture.componentInstance; fixture.detectChanges(); + + await fixture.whenStable(); }); it('should create', () => { diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 91bf6c2..77ed75c 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -1,4 +1,4 @@ export const environment = { production: true, - baseUrl: 'https://pb.prod.K3s.technostrea.fr' + baseUrl: 'https://pb-dev.prod.K3s.technostrea.fr' }; diff --git a/src/setup-jest.ts b/src/setup-jest.ts index c7798c1..eb299eb 100644 --- a/src/setup-jest.ts +++ b/src/setup-jest.ts @@ -1,9 +1,82 @@ -import { setupZoneTestEnv } from "jest-preset-angular/setup-env/zone"; -import * as fetch from 'node-fetch'; - -(global as any).fetch = fetch; -(global as any).Headers = fetch.Headers; -(global as any).Request = fetch.Request; -(global as any).Response = fetch.Response; - +import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone'; setupZoneTestEnv(); + +/** + * 1) fetch “neutre” + * - conserve le vrai fetch pour http(s) si dispo (Node >=18 + jsdom), + * - renvoie une réponse OK pour data:/blob:/file: (cas angularx-qrcode). + */ +const realFetch = + typeof global.fetch === 'function' ? global.fetch.bind(global) : undefined; + +(global as any).fetch = jest.fn((input: any, init?: any) => { + const url = typeof input === 'string' ? input : input?.url; + if (url && /^https?:/i.test(url) && realFetch) { + return realFetch(input as any, init) as any; + } + return Promise.resolve({ + ok: true, + status: 200, + blob: async () => new Blob(), + arrayBuffer: async () => new ArrayBuffer(0), + text: async () => '', + json: async () => ({}), + } as Response); +}); + +/** + * 2) Polyfills blob URL et canvas (jsdom ne couvre pas tout) + */ +if (!(global as any).URL) (global as any).URL = {} as any; +if (!(global as any).URL.createObjectURL) { + (global as any).URL.createObjectURL = jest.fn( + () => `blob:jest-${Math.random().toString(36).slice(2)}` + ); +} +if (!(global as any).URL.revokeObjectURL) { + (global as any).URL.revokeObjectURL = jest.fn(); +} +if (!(HTMLCanvasElement.prototype as any).toDataURL) { + (HTMLCanvasElement.prototype as any).toDataURL = jest.fn( + () => 'data:image/png;base64,' + ); +} + +/** + * 3) Filtrer les logs “toxiques” (qui font crasher après la fin des tests) + * -> on mock console.* AVANT que quoi que ce soit ne loggue. + */ +const origLog = console.log, origWarn = console.warn, origErr = console.error; +const IGNORE = [ + 'Navigation triggered outside Angular zone', + '[angularx-qrcode] Error when fetching image/png URL:', + 'loadPackages: TypeError [ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING_FLAG]', +]; + +beforeAll(() => { + jest.spyOn(console, 'error').mockImplementation((...args: any[]) => { + const msg = args[0] && String(args[0]); + if (msg && IGNORE.some(p => msg.includes(p))) return; + // Si tu veux tout couper en CI : + // return; + return origErr(...(args as unknown[])); + }); + + jest.spyOn(console, 'warn').mockImplementation((...args: any[]) => { + const msg = args[0] && String(args[0]); + if (msg && IGNORE.some(p => msg.includes(p))) return; + return origWarn(...(args as unknown[])); + }); + + jest.spyOn(console, 'log').mockImplementation((...args: any[]) => { + const msg = args[0] && String(args[0]); + if (msg && IGNORE.some(p => msg.includes(p))) return; + return origLog(...(args as unknown[])); + }); +}); + +afterAll(() => { + (console.error as jest.Mock).mockRestore?.(); + (console.warn as jest.Mock).mockRestore?.(); + (console.log as jest.Mock).mockRestore?.(); +});