correctif des tests et du workflow ci

This commit is contained in:
styve Lioumba
2025-10-05 15:06:14 +02:00
parent 6dc072b7eb
commit 9678ccbfc6
23 changed files with 207 additions and 25 deletions

View File

@@ -2,7 +2,9 @@ name: Docker Build Check
# Déclencheur pour chaque pull request
on:
workflow_call:
push:
branches: ['**']
pull_request:
jobs:
build:

View File

@@ -13,4 +13,5 @@ module.exports = {
'^@app/(.*)$': '<rootDir>/src/app/$1',
'^@env/(.*)$': '<rootDir>/src/environments/$1',
},
testTimeout: 30000,
};

View File

@@ -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<AppComponent>;
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', () => {

View File

@@ -10,6 +10,10 @@ import {Observable, of} from "rxjs";
describe('listResolver', () => {
let mockProfileService: Partial<ProfileService>;
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
]
});
});

View File

@@ -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);

View File

@@ -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);
});

View File

@@ -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);
});

View File

@@ -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);
});

View File

@@ -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);
});

View File

@@ -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);
});

View File

@@ -19,6 +19,8 @@ describe('AuthComponent', () => {
fixture = TestBed.createComponent(AuthComponent);
component = fixture.componentInstance;
fixture.detectChanges();
await fixture.whenStable();
});
it('should create', () => {

View File

@@ -19,6 +19,8 @@ describe('MyProfileComponent', () => {
fixture = TestBed.createComponent(MyProfileComponent);
component = fixture.componentInstance;
fixture.detectChanges();
await fixture.whenStable();
});
it('should create', () => {

View File

@@ -19,6 +19,8 @@ describe('ProfileDetailComponent', () => {
fixture = TestBed.createComponent(ProfileDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
await fixture.whenStable();
});
it('should create', () => {

View File

@@ -15,6 +15,8 @@ describe('MyHomeProfileComponent', () => {
fixture = TestBed.createComponent(MyHomeProfileComponent);
component = fixture.componentInstance;
fixture.detectChanges();
await fixture.whenStable();
});
it('should create', () => {

View File

@@ -15,6 +15,8 @@ describe('MyProfileProjectItemComponent', () => {
fixture = TestBed.createComponent(MyProfileProjectItemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
await fixture.whenStable();
});
it('should create', () => {

View File

@@ -15,6 +15,8 @@ describe('ProjectListComponent', () => {
fixture = TestBed.createComponent(ProjectListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
await fixture.whenStable();
});
it('should create', () => {

View File

@@ -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<VerticalProfileListComponent>;
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', () => {

View File

@@ -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(() => {

View File

@@ -24,6 +24,8 @@ describe('PdfViewerComponent', () => {
component.profile = mockProfile;
fixture.detectChanges();
await fixture.whenStable();
});
it('should create', () => {

View File

@@ -44,6 +44,8 @@ describe('RegisterComponent', () => {
fixture = TestBed.createComponent(RegisterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
await fixture.whenStable();
});
it('should create', () => {

View File

@@ -15,6 +15,8 @@ describe('SearchComponent', () => {
fixture = TestBed.createComponent(SearchComponent);
component = fixture.componentInstance;
fixture.detectChanges();
await fixture.whenStable();
});
it('should create', () => {

View File

@@ -1,4 +1,4 @@
export const environment = {
production: true,
baseUrl: 'https://pb.prod.K3s.technostrea.fr'
baseUrl: 'https://pb-dev.prod.K3s.technostrea.fr'
};

View File

@@ -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?.();
});