Merge pull request 'ttp-14' (#28) from ttp-14 into main
Reviewed-on: #28 Reviewed-by: technostrea <contact@technostrea.fr>
This commit is contained in:
2
.act.secrets.example
Normal file
2
.act.secrets.example
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ROBOT_TOKEN=fake_gitea_token
|
||||||
|
ENV_URL=fake_env_url
|
||||||
8
.actrc
8
.actrc
@@ -1,3 +1,5 @@
|
|||||||
--container-architecture linux/amd64
|
--container-architecture linux/arm64
|
||||||
-W .gitea/workflows
|
--workflows .gitea/workflows/
|
||||||
-P ubuntu-latest==ghcr.io/catthehacker/ubuntu:act-latest
|
--platform ubuntu-latest
|
||||||
|
--secret-file .act.secrets
|
||||||
|
--env-file .env
|
||||||
|
|||||||
1
.env.example
Normal file
1
.env.example
Normal file
@@ -0,0 +1 @@
|
|||||||
|
GITEA_SERVER_URL=https://fake-gitea-url.example.com
|
||||||
31
.gitea/workflows/trigger-deploy.yaml
Normal file
31
.gitea/workflows/trigger-deploy.yaml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
name: Trigger Deploy Repo
|
||||||
|
run-name: Trigger deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*' # Se déclenche sur n'importe quel tag
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
dispatch:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
env:
|
||||||
|
# ------- À ADAPTER -------
|
||||||
|
CODE_REF: ${{ gitea.ref }} # branche/tag/sha à récupérer
|
||||||
|
GITEA_SERVER_URL: https://git.prod.k3s.technostrea.fr # URL du serveur Gitea
|
||||||
|
# --------------------------
|
||||||
|
steps:
|
||||||
|
- name: Dispatch Signal to ttp-deploy
|
||||||
|
run: |
|
||||||
|
# Récupération de la version sans le "refs/tags/"
|
||||||
|
VERSION=${{ env.CODE_REF }}
|
||||||
|
|
||||||
|
echo "Déclenchement du déploiement pour la version $VERSION sur l'instance ${{ env.GITEA_SERVER_URL }}"
|
||||||
|
|
||||||
|
# Appel API Gitea.
|
||||||
|
# Notez la structure de l'URL : /api/v1/repos/{owner}/{repo}/dispatches
|
||||||
|
curl -X POST "${{ env.GITEA_SERVER_URL }}/api/v1/repos/technostrea/trouvetonprofile-deployment/dispatches" \
|
||||||
|
-H "Authorization: token ${{ secrets.ROBOT_TOKEN }}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"event_type\": \"build-release\", \"client_payload\": {\"version\": \"$VERSION\"}}"
|
||||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -127,3 +127,11 @@ logs/*.log
|
|||||||
|
|
||||||
pb/data/*
|
pb/data/*
|
||||||
src/environments/environment.development.ts
|
src/environments/environment.development.ts
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
.idea
|
||||||
|
logs/
|
||||||
|
*.log
|
||||||
|
*.secrets
|
||||||
|
.act.secrets
|
||||||
|
.env
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ describe('AppComponent', () => {
|
|||||||
create: jest.fn(),
|
create: jest.fn(),
|
||||||
list: jest.fn(),
|
list: jest.fn(),
|
||||||
update: jest.fn(),
|
update: jest.fn(),
|
||||||
getByUserId: jest.fn(),
|
getById: jest.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { ApplicationConfig } from '@angular/core';
|
|||||||
import {
|
import {
|
||||||
PreloadAllModules,
|
PreloadAllModules,
|
||||||
provideRouter,
|
provideRouter,
|
||||||
|
withComponentInputBinding,
|
||||||
withInMemoryScrolling,
|
withInMemoryScrolling,
|
||||||
withPreloading,
|
withPreloading,
|
||||||
withViewTransitions,
|
withViewTransitions,
|
||||||
@@ -21,6 +22,8 @@ import { USER_REPOSITORY_TOKEN } from '@app/infrastructure/users/user-repository
|
|||||||
import { PbUserRepository } from '@app/infrastructure/users/pb-user.repository';
|
import { PbUserRepository } from '@app/infrastructure/users/pb-user.repository';
|
||||||
import { AUTH_REPOSITORY_TOKEN } from '@app/infrastructure/authentification/auth-repository.token';
|
import { AUTH_REPOSITORY_TOKEN } from '@app/infrastructure/authentification/auth-repository.token';
|
||||||
import { PbAuthRepository } from '@app/infrastructure/authentification/pb-auth.repository';
|
import { PbAuthRepository } from '@app/infrastructure/authentification/pb-auth.repository';
|
||||||
|
import { WEB_SHARE_SERVICE_TOKEN } from '@app/infrastructure/shareData/web-share.service.token';
|
||||||
|
import { WebShareService } from '@app/infrastructure/shareData/web-share.service';
|
||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [
|
providers: [
|
||||||
@@ -31,7 +34,8 @@ export const appConfig: ApplicationConfig = {
|
|||||||
withInMemoryScrolling({
|
withInMemoryScrolling({
|
||||||
scrollPositionRestoration: 'enabled',
|
scrollPositionRestoration: 'enabled',
|
||||||
anchorScrolling: 'enabled',
|
anchorScrolling: 'enabled',
|
||||||
})
|
}),
|
||||||
|
withComponentInputBinding()
|
||||||
),
|
),
|
||||||
provideAnimations(),
|
provideAnimations(),
|
||||||
provideHttpClient(withFetch()),
|
provideHttpClient(withFetch()),
|
||||||
@@ -40,6 +44,7 @@ export const appConfig: ApplicationConfig = {
|
|||||||
{ provide: SECTOR_REPOSITORY_TOKEN, useExisting: PbSectorRepository },
|
{ provide: SECTOR_REPOSITORY_TOKEN, useExisting: PbSectorRepository },
|
||||||
{ provide: USER_REPOSITORY_TOKEN, useExisting: PbUserRepository },
|
{ provide: USER_REPOSITORY_TOKEN, useExisting: PbUserRepository },
|
||||||
{ provide: AUTH_REPOSITORY_TOKEN, useExisting: PbAuthRepository },
|
{ provide: AUTH_REPOSITORY_TOKEN, useExisting: PbAuthRepository },
|
||||||
|
{ provide: WEB_SHARE_SERVICE_TOKEN, useExisting: WebShareService },
|
||||||
provideToastr({
|
provideToastr({
|
||||||
timeOut: 10000,
|
timeOut: 10000,
|
||||||
positionClass: 'toast-top-right',
|
positionClass: 'toast-top-right',
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { SearchFilters } from '@app/domain/search/search-filters';
|
|||||||
|
|
||||||
export interface ProfileRepository {
|
export interface ProfileRepository {
|
||||||
list(params?: SearchFilters): Observable<ProfilePaginated>;
|
list(params?: SearchFilters): Observable<ProfilePaginated>;
|
||||||
getByUserId(userId: string): Observable<Profile>;
|
getById(profileId: string): Observable<Profile>;
|
||||||
create(profile: Profile): Observable<Profile>;
|
create(profile: Profile): Observable<Profile>;
|
||||||
update(profileId: string, profile: Partial<Profile>): Observable<Profile>;
|
update(profileId: string, profile: Partial<Profile>): Observable<Profile>;
|
||||||
}
|
}
|
||||||
|
|||||||
3
src/app/domain/shareData/share-data.repository.ts
Normal file
3
src/app/domain/shareData/share-data.repository.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export abstract class ShareDataRepository {
|
||||||
|
abstract share(shareData: ShareData): void;
|
||||||
|
}
|
||||||
5
src/app/domain/shareData/share-data.ts
Normal file
5
src/app/domain/shareData/share-data.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export interface ShareData {
|
||||||
|
title: string;
|
||||||
|
text: string;
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
@@ -29,9 +29,9 @@ export class PbProfileRepository implements ProfileRepository {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getByUserId(userId: string): Observable<Profile> {
|
getById(userId: string): Observable<Profile> {
|
||||||
return from(
|
return from(
|
||||||
this.pb.collection('profiles').getFirstListItem<Profile>(`utilisateur="${userId}"`)
|
this.pb.collection('profiles').getOne<Profile>(`${userId}`, { expand: 'utilisateur' })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { InjectionToken } from '@angular/core';
|
||||||
|
import { ShareDataRepository } from '@app/domain/shareData/share-data.repository';
|
||||||
|
|
||||||
|
export const WEB_SHARE_SERVICE_TOKEN = new InjectionToken<ShareDataRepository>(
|
||||||
|
'ShareDataRepository'
|
||||||
|
);
|
||||||
36
src/app/infrastructure/shareData/web-share.service.ts
Normal file
36
src/app/infrastructure/shareData/web-share.service.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { inject, Injectable } from '@angular/core';
|
||||||
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
import { ShareDataRepository } from '@app/domain/shareData/share-data.repository';
|
||||||
|
import { ToastrService } from 'ngx-toastr';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class WebShareService implements ShareDataRepository {
|
||||||
|
private document = inject(DOCUMENT);
|
||||||
|
private toastr = inject(ToastrService);
|
||||||
|
|
||||||
|
async share(shareData: ShareData) {
|
||||||
|
const navigator = this.document.defaultView?.navigator;
|
||||||
|
|
||||||
|
if (navigator && navigator.canShare && navigator.canShare(shareData)) {
|
||||||
|
try {
|
||||||
|
await navigator.share(shareData);
|
||||||
|
return;
|
||||||
|
} catch (error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.copyToClipboard(shareData.url!);
|
||||||
|
}
|
||||||
|
|
||||||
|
private copyToClipboard(text: string) {
|
||||||
|
navigator.clipboard.writeText(text).then(() => {
|
||||||
|
this.toastr.info(`Le lien du profil est copié dans le presse papier !`, `Partage de profil`, {
|
||||||
|
closeButton: true,
|
||||||
|
progressAnimation: 'decreasing',
|
||||||
|
progressBar: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,38 +4,25 @@ import { HomeComponent } from './home.component';
|
|||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
||||||
import { SectorRepository } from '@app/domain/sectors/sector.repository';
|
import { SectorRepository } from '@app/domain/sectors/sector.repository';
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { Profile } from '@app/domain/profiles/profile.model';
|
|
||||||
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
||||||
import { SECTOR_REPOSITORY_TOKEN } from '@app/infrastructure/sectors/sector-repository.token';
|
import { SECTOR_REPOSITORY_TOKEN } from '@app/infrastructure/sectors/sector-repository.token';
|
||||||
import { Sector } from '@app/domain/sectors/sector.model';
|
import { mockSectorRepo } from '@app/testing/sector.mock';
|
||||||
|
import { mockProfileRepo } from '@app/testing/profile.mock';
|
||||||
|
|
||||||
describe('HomeComponent', () => {
|
describe('HomeComponent', () => {
|
||||||
let component: HomeComponent;
|
let component: HomeComponent;
|
||||||
let fixture: ComponentFixture<HomeComponent>;
|
let fixture: ComponentFixture<HomeComponent>;
|
||||||
|
|
||||||
let mockProfileRepo: jest.Mocked<Partial<ProfileRepository>>;
|
let mockProfileRepository: jest.Mocked<Partial<ProfileRepository>> = mockProfileRepo;
|
||||||
let mockSectorRepo: jest.Mocked<Partial<SectorRepository>>;
|
let mockSectorRepository: jest.Mocked<Partial<SectorRepository>> = mockSectorRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockProfileRepo = {
|
|
||||||
create: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
list: jest.fn().mockReturnValue(of([])),
|
|
||||||
getByUserId: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
update: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockSectorRepo = {
|
|
||||||
list: jest.fn().mockReturnValue(of([])),
|
|
||||||
getOne: jest.fn().mockReturnValue(of({} as Sector)),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [HomeComponent],
|
imports: [HomeComponent],
|
||||||
providers: [
|
providers: [
|
||||||
provideRouter([]),
|
provideRouter([]),
|
||||||
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepo },
|
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepository },
|
||||||
{ provide: SECTOR_REPOSITORY_TOKEN, useValue: mockSectorRepo },
|
{ provide: SECTOR_REPOSITORY_TOKEN, useValue: mockSectorRepository },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
|
|||||||
@@ -4,62 +4,33 @@ import { MyProfileComponent } from './my-profile.component';
|
|||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
||||||
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { Profile } from '@app/domain/profiles/profile.model';
|
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { USER_REPOSITORY_TOKEN } from '@app/infrastructure/users/user-repository.token';
|
import { USER_REPOSITORY_TOKEN } from '@app/infrastructure/users/user-repository.token';
|
||||||
import { UserRepository } from '@app/domain/users/user.repository';
|
import { UserRepository } from '@app/domain/users/user.repository';
|
||||||
import { AuthRepository } from '@app/domain/authentification/auth.repository';
|
import { AuthRepository } from '@app/domain/authentification/auth.repository';
|
||||||
import { AUTH_REPOSITORY_TOKEN } from '@app/infrastructure/authentification/auth-repository.token';
|
import { AUTH_REPOSITORY_TOKEN } from '@app/infrastructure/authentification/auth-repository.token';
|
||||||
|
import { mockProfileRepo } from '@app/testing/profile.mock';
|
||||||
|
import { mockToastR } from '@app/testing/toastr.mock';
|
||||||
|
import { mockUserRepo } from '@app/testing/user.mock';
|
||||||
|
import { mockAuthRepo } from '@app/testing/auth.mock';
|
||||||
|
|
||||||
describe('MyProfileComponent', () => {
|
describe('MyProfileComponent', () => {
|
||||||
let component: MyProfileComponent;
|
let component: MyProfileComponent;
|
||||||
let fixture: ComponentFixture<MyProfileComponent>;
|
let fixture: ComponentFixture<MyProfileComponent>;
|
||||||
|
|
||||||
let mockProfileRepo: ProfileRepository;
|
let mockProfileRepository: jest.Mocked<Partial<ProfileRepository>> = mockProfileRepo;
|
||||||
let mockToastrService: Partial<ToastrService>;
|
let mockToastrService: jest.Mocked<Partial<ToastrService>> = mockToastR;
|
||||||
let mockUserRepo: Partial<UserRepository>;
|
let mockUserRepository: jest.Mocked<Partial<UserRepository>> = mockUserRepo;
|
||||||
let mockAuthRepository: jest.Mocked<Partial<AuthRepository>>;
|
let mockAuthRepository: jest.Mocked<Partial<AuthRepository>> = mockAuthRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockProfileRepo = {
|
|
||||||
create: jest.fn(),
|
|
||||||
list: jest.fn(),
|
|
||||||
update: jest.fn(),
|
|
||||||
getByUserId: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockUserRepo = {
|
|
||||||
update: jest.fn(),
|
|
||||||
getUserById: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockToastrService = {
|
|
||||||
warning: jest.fn(),
|
|
||||||
success: jest.fn(),
|
|
||||||
info: jest.fn(),
|
|
||||||
error: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockAuthRepository = {
|
|
||||||
get: jest.fn(),
|
|
||||||
login: jest.fn(),
|
|
||||||
sendVerificationEmail: jest.fn(),
|
|
||||||
logout: jest.fn(),
|
|
||||||
isAuthenticated: jest.fn(),
|
|
||||||
isEmailVerified: jest.fn(),
|
|
||||||
register: jest.fn(),
|
|
||||||
sendRequestPasswordReset: jest.fn(),
|
|
||||||
confirmPasswordReset: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [MyProfileComponent],
|
imports: [MyProfileComponent],
|
||||||
providers: [
|
providers: [
|
||||||
provideRouter([]),
|
provideRouter([]),
|
||||||
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepo },
|
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepository },
|
||||||
{ provide: AUTH_REPOSITORY_TOKEN, useValue: mockAuthRepository },
|
{ provide: AUTH_REPOSITORY_TOKEN, useValue: mockAuthRepository },
|
||||||
{ provide: USER_REPOSITORY_TOKEN, useValue: mockUserRepo },
|
{ provide: USER_REPOSITORY_TOKEN, useValue: mockUserRepository },
|
||||||
{ provide: ToastrService, useValue: mockToastrService },
|
{ provide: ToastrService, useValue: mockToastrService },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|||||||
@@ -9,11 +9,13 @@
|
|||||||
<!-- Overlay gradient -->
|
<!-- Overlay gradient -->
|
||||||
<div class="absolute inset-0 bg-gradient-to-b from-transparent to-black/30"></div>
|
<div class="absolute inset-0 bg-gradient-to-b from-transparent to-black/30"></div>
|
||||||
|
|
||||||
<!-- Bouton retour -->
|
<!-- Boutons en haut -->
|
||||||
<div class="relative z-10 p-4 flex justify-between items-start">
|
<div class="relative z-10 p-4 flex justify-between items-start">
|
||||||
|
<!-- Bouton retour -->
|
||||||
<a
|
<a
|
||||||
[routerLink]="['/profiles']"
|
[routerLink]="['/profiles']"
|
||||||
class="group flex items-center justify-center w-10 h-10 md:w-12 md:h-12 bg-white/20 backdrop-blur-md rounded-full hover:bg-white/30 transition-all duration-300 hover:scale-110"
|
class="group flex items-center justify-center w-10 h-10 md:w-12 md:h-12 bg-white/20 backdrop-blur-md rounded-full hover:bg-white/30 transition-all duration-300 hover:scale-110"
|
||||||
|
aria-label="Retour à la liste des profils"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -30,10 +32,13 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<!-- Conteneur pour badge vérifié et bouton partage -->
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
<!-- Badge vérifié -->
|
<!-- Badge vérifié -->
|
||||||
@if (profile().estVerifier) {
|
@if (profile()!.estVerifier) {
|
||||||
<div
|
<div
|
||||||
class="flex items-center gap-2 bg-purple-500/20 backdrop-blur-md px-3 py-2 rounded-full animate-pulse-slow"
|
class="flex items-center gap-2 bg-purple-500/20 backdrop-blur-md px-3 py-2 rounded-full animate-pulse-slow"
|
||||||
|
data-testid="verified-badge"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -51,6 +56,29 @@
|
|||||||
<span class="text-white text-sm font-medium hidden md:inline">Vérifié</span>
|
<span class="text-white text-sm font-medium hidden md:inline">Vérifié</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<!-- Bouton partage -->
|
||||||
|
<button
|
||||||
|
(click)="onShare()"
|
||||||
|
class="group flex items-center justify-center w-10 h-10 md:w-12 md:h-12 bg-indigo-500/20 backdrop-blur-md rounded-full hover:bg-indigo-500/30 transition-all duration-300 hover:scale-110"
|
||||||
|
aria-label="Partager ce profil"
|
||||||
|
data-testid="share-button"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
class="w-5 h-5 md:w-6 md:h-6 text-white"
|
||||||
|
>
|
||||||
|
<title>Partager</title>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M15.75 4.5a3 3 0 11.825 2.066l-8.421 4.679a3.002 3.002 0 010 1.51l8.421 4.679a3 3 0 11-.729 1.31l-8.421-4.678a3 3 0 110-4.132l8.421-4.679a3 3 0 01-.096-.755z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -103,7 +131,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
<p class="text-lg md:text-xl text-indigo-600 dark:text-indigo-400 font-semibold">
|
<p class="text-lg md:text-xl text-indigo-600 dark:text-indigo-400 font-semibold">
|
||||||
{{ profile().profession | uppercase }}
|
{{ profile()!.profession | uppercase }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -135,9 +163,9 @@
|
|||||||
</svg>
|
</svg>
|
||||||
Biographie
|
Biographie
|
||||||
</h3>
|
</h3>
|
||||||
@if (profile().bio) {
|
@if (profile()!.bio) {
|
||||||
<p class="text-gray-600 dark:text-gray-300 text-sm leading-relaxed">
|
<p class="text-gray-600 dark:text-gray-300 text-sm leading-relaxed">
|
||||||
{{ profile().bio }}
|
{{ profile()!.bio }}
|
||||||
</p>
|
</p>
|
||||||
} @else {
|
} @else {
|
||||||
<p class="text-gray-600 dark:text-gray-300 text-sm leading-relaxed">
|
<p class="text-gray-600 dark:text-gray-300 text-sm leading-relaxed">
|
||||||
@@ -149,7 +177,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Card Secteur -->
|
<!-- Card Secteur -->
|
||||||
@if (profile().secteur) {
|
@if (profile()!.secteur) {
|
||||||
<div
|
<div
|
||||||
class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 hover:shadow-xl transition-shadow duration-300"
|
class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 hover:shadow-xl transition-shadow duration-300"
|
||||||
>
|
>
|
||||||
@@ -168,12 +196,12 @@
|
|||||||
</svg>
|
</svg>
|
||||||
Secteur
|
Secteur
|
||||||
</h3>
|
</h3>
|
||||||
<app-chips [sectorId]="profile().secteur" />
|
<app-chips [sectorId]="profile()!.secteur" />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<!-- Card Réseaux -->
|
<!-- Card Réseaux -->
|
||||||
@if (profile().reseaux) {
|
@if (profile()!.reseaux) {
|
||||||
<div
|
<div
|
||||||
class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 hover:shadow-xl transition-shadow duration-300"
|
class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 hover:shadow-xl transition-shadow duration-300"
|
||||||
>
|
>
|
||||||
@@ -195,7 +223,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
Réseaux
|
Réseaux
|
||||||
</h3>
|
</h3>
|
||||||
<app-reseaux [reseaux]="profile().reseaux" />
|
<app-reseaux [reseaux]="profile()!.reseaux" />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@@ -203,7 +231,7 @@
|
|||||||
<!-- Colonne droite - À propos et Projets -->
|
<!-- Colonne droite - À propos et Projets -->
|
||||||
<div class="lg:col-span-2 space-y-6 animate-slide-up animation-delay-300">
|
<div class="lg:col-span-2 space-y-6 animate-slide-up animation-delay-300">
|
||||||
<!-- Card À propos -->
|
<!-- Card À propos -->
|
||||||
@if (profile().apropos) {
|
@if (profile()!.apropos) {
|
||||||
<div
|
<div
|
||||||
class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 md:p-8 hover:shadow-xl transition-shadow duration-300"
|
class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 md:p-8 hover:shadow-xl transition-shadow duration-300"
|
||||||
>
|
>
|
||||||
@@ -225,7 +253,7 @@
|
|||||||
À propos
|
À propos
|
||||||
</h2>
|
</h2>
|
||||||
<p class="text-gray-700 dark:text-gray-300 leading-relaxed text-base">
|
<p class="text-gray-700 dark:text-gray-300 leading-relaxed text-base">
|
||||||
{{ profile().apropos }}
|
{{ profile()!.apropos }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,37 +4,39 @@ import { ProfileDetailComponent } from './profile-detail.component';
|
|||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
import { PROJECT_REPOSITORY_TOKEN } from '@app/infrastructure/projects/project-repository.token';
|
import { PROJECT_REPOSITORY_TOKEN } from '@app/infrastructure/projects/project-repository.token';
|
||||||
import { ProjectRepository } from '@app/domain/projects/project.repository';
|
import { ProjectRepository } from '@app/domain/projects/project.repository';
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { Project } from '@app/domain/projects/project.model';
|
|
||||||
import { Sector } from '@app/domain/sectors/sector.model';
|
|
||||||
import { SectorRepository } from '@app/domain/sectors/sector.repository';
|
import { SectorRepository } from '@app/domain/sectors/sector.repository';
|
||||||
import { SECTOR_REPOSITORY_TOKEN } from '@app/infrastructure/sectors/sector-repository.token';
|
import { SECTOR_REPOSITORY_TOKEN } from '@app/infrastructure/sectors/sector-repository.token';
|
||||||
|
import { ToastrService } from 'ngx-toastr';
|
||||||
|
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
||||||
|
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
||||||
|
import { USER_REPOSITORY_TOKEN } from '@app/infrastructure/users/user-repository.token';
|
||||||
|
import { UserRepository } from '@app/domain/users/user.repository';
|
||||||
|
import { mockProfileRepo } from '@app/testing/profile.mock';
|
||||||
|
import { mockSectorRepo } from '@app/testing/sector.mock';
|
||||||
|
import { mockToastR } from '@app/testing/toastr.mock';
|
||||||
|
import { mockUserRepo } from '@app/testing/user.mock';
|
||||||
|
import { mockProjectRepo } from '@app/testing/project.mock';
|
||||||
|
|
||||||
describe('ProfileDetailComponent', () => {
|
describe('ProfileDetailComponent', () => {
|
||||||
let component: ProfileDetailComponent;
|
let component: ProfileDetailComponent;
|
||||||
let fixture: ComponentFixture<ProfileDetailComponent>;
|
let fixture: ComponentFixture<ProfileDetailComponent>;
|
||||||
let mockProjectRepository: jest.Mocked<ProjectRepository>;
|
|
||||||
let mockSectorRepo: SectorRepository;
|
let mockProjectRepository: jest.Mocked<Partial<ProjectRepository>> = mockProjectRepo;
|
||||||
|
let mockProfileRepository: jest.Mocked<Partial<ProfileRepository>> = mockProfileRepo;
|
||||||
|
let mockSectorRepository: jest.Mocked<Partial<SectorRepository>> = mockSectorRepo;
|
||||||
|
let mockToastr: jest.Mocked<Partial<ToastrService>> = mockToastR;
|
||||||
|
let mockUserRepository: jest.Mocked<Partial<UserRepository>> = mockUserRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockProjectRepository = {
|
|
||||||
create: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
list: jest.fn().mockReturnValue(of([])),
|
|
||||||
get: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
update: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockSectorRepo = {
|
|
||||||
list: jest.fn(),
|
|
||||||
getOne: jest.fn().mockReturnValue(of({} as Sector)),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [ProfileDetailComponent],
|
imports: [ProfileDetailComponent],
|
||||||
providers: [
|
providers: [
|
||||||
provideRouter([]),
|
provideRouter([]),
|
||||||
{ provide: PROJECT_REPOSITORY_TOKEN, useValue: mockProjectRepository },
|
{ provide: PROJECT_REPOSITORY_TOKEN, useValue: mockProjectRepository },
|
||||||
{ provide: SECTOR_REPOSITORY_TOKEN, useValue: mockSectorRepo },
|
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepository },
|
||||||
|
{ provide: SECTOR_REPOSITORY_TOKEN, useValue: mockSectorRepository },
|
||||||
|
{ provide: USER_REPOSITORY_TOKEN, useValue: mockUserRepository },
|
||||||
|
{ provide: ToastrService, useValue: mockToastr },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, computed, inject } from '@angular/core';
|
import { Component, computed, effect, inject, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, RouterLink } from '@angular/router';
|
import { ActivatedRoute, RouterLink } from '@angular/router';
|
||||||
import { UpperCasePipe } from '@angular/common';
|
import { UpperCasePipe } from '@angular/common';
|
||||||
import { User } from '@app/domain/users/user.model';
|
import { User } from '@app/domain/users/user.model';
|
||||||
@@ -7,29 +7,86 @@ import { ReseauxComponent } from '@app/shared/components/reseaux/reseaux.compone
|
|||||||
import { UntilDestroy } from '@ngneat/until-destroy';
|
import { UntilDestroy } from '@ngneat/until-destroy';
|
||||||
import { ProjectListComponent } from '@app/shared/components/project-list/project-list.component';
|
import { ProjectListComponent } from '@app/shared/components/project-list/project-list.component';
|
||||||
import { environment } from '@env/environment';
|
import { environment } from '@env/environment';
|
||||||
import { Profile } from '@app/domain/profiles/profile.model';
|
import { WebShareService } from '@app/infrastructure/shareData/web-share.service';
|
||||||
|
import { ProfileFacade } from '@app/ui/profiles/profile.facade';
|
||||||
|
import { ProfileViewModel } from '@app/ui/profiles/profile.presenter.model';
|
||||||
|
import { ActionType } from '@app/domain/action-type.util';
|
||||||
|
import { UserFacade } from '@app/ui/users/user.facade';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-profile-detail',
|
selector: 'app-profile-detail',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [ChipsComponent, ReseauxComponent, RouterLink, UpperCasePipe, ProjectListComponent],
|
imports: [ChipsComponent, ReseauxComponent, RouterLink, UpperCasePipe, ProjectListComponent],
|
||||||
|
providers: [UserFacade],
|
||||||
templateUrl: './profile-detail.component.html',
|
templateUrl: './profile-detail.component.html',
|
||||||
styleUrl: './profile-detail.component.scss',
|
styleUrl: './profile-detail.component.scss',
|
||||||
})
|
})
|
||||||
@UntilDestroy()
|
@UntilDestroy()
|
||||||
export class ProfileDetailComponent {
|
export class ProfileDetailComponent implements OnInit {
|
||||||
|
private readonly webShare = inject(WebShareService);
|
||||||
|
private readonly profileFacade = inject(ProfileFacade);
|
||||||
|
private readonly userFacade = inject(UserFacade);
|
||||||
protected readonly environment = environment;
|
protected readonly environment = environment;
|
||||||
|
protected readonly ActionType = ActionType;
|
||||||
private readonly route = inject(ActivatedRoute);
|
private readonly route = inject(ActivatedRoute);
|
||||||
|
|
||||||
protected extraData: { user: User; profile: Profile } = this.route.snapshot.data['profile'];
|
protected extraData: { user: User; profile: ProfileViewModel } | undefined =
|
||||||
|
this.route.snapshot.data['profile'];
|
||||||
|
|
||||||
protected user = computed(() => {
|
slug = computed(() => this.route.snapshot.params['name'] ?? '');
|
||||||
if (this.extraData != undefined) return this.extraData.user;
|
|
||||||
return {} as User;
|
|
||||||
});
|
|
||||||
|
|
||||||
protected profile = computed(() => {
|
protected user = this.userFacade.user;
|
||||||
if (this.extraData != undefined) return this.extraData.profile;
|
protected readonly userLoading = this.userFacade.loading;
|
||||||
return {} as Profile;
|
protected readonly userError = this.userFacade.error;
|
||||||
|
|
||||||
|
protected profile = this.profileFacade.profile;
|
||||||
|
protected readonly profileLoading = this.profileFacade.loading;
|
||||||
|
protected readonly profileError = this.profileFacade.error;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
effect(() => {
|
||||||
|
if (!this.profileLoading().isLoading) {
|
||||||
|
switch (this.profileLoading().action) {
|
||||||
|
case ActionType.READ:
|
||||||
|
if (!this.profileError().hasError) {
|
||||||
|
this.profile = this.profileFacade.profile;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!this.userLoading().isLoading) {
|
||||||
|
switch (this.userLoading().action) {
|
||||||
|
case ActionType.READ:
|
||||||
|
if (!this.userError().hasError) {
|
||||||
|
this.user = this.userFacade.user;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (this.extraData === undefined) {
|
||||||
|
const extractSlug = this.slug().split('-');
|
||||||
|
const profileId = extractSlug[extractSlug.length - 1];
|
||||||
|
const userId = extractSlug[extractSlug.length - 2];
|
||||||
|
this.profileFacade.loadOne(profileId);
|
||||||
|
this.userFacade.loadOne(userId);
|
||||||
|
} else {
|
||||||
|
this.profile.set(this.extraData.profile);
|
||||||
|
this.user.set(this.extraData.user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async onShare() {
|
||||||
|
if (!this.profile) return;
|
||||||
|
const fullUrl = `${window.location.origin}/profiles/${this.slug()}`;
|
||||||
|
|
||||||
|
await this.webShare.share({
|
||||||
|
title: `Découvrez le profil de ${this.profile.name}`,
|
||||||
|
text: `Jette un œil à ce profil intéressant sur notre application !`,
|
||||||
|
url: fullUrl,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,33 +2,20 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
|
|
||||||
import { ProfileListComponent } from './profile-list.component';
|
import { ProfileListComponent } from './profile-list.component';
|
||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
||||||
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
||||||
import { Profile } from '@app/domain/profiles/profile.model';
|
|
||||||
import { SECTOR_REPOSITORY_TOKEN } from '@app/infrastructure/sectors/sector-repository.token';
|
import { SECTOR_REPOSITORY_TOKEN } from '@app/infrastructure/sectors/sector-repository.token';
|
||||||
import { SectorRepository } from '@app/domain/sectors/sector.repository';
|
import { SectorRepository } from '@app/domain/sectors/sector.repository';
|
||||||
import { Sector } from '@app/domain/sectors/sector.model';
|
import { mockProfileRepo } from '@app/testing/profile.mock';
|
||||||
|
import { mockSectorRepo } from '@app/testing/sector.mock';
|
||||||
|
|
||||||
describe('ProfileListComponent', () => {
|
describe('ProfileListComponent', () => {
|
||||||
let component: ProfileListComponent;
|
let component: ProfileListComponent;
|
||||||
let fixture: ComponentFixture<ProfileListComponent>;
|
let fixture: ComponentFixture<ProfileListComponent>;
|
||||||
let mockProfileRepository: jest.Mocked<Partial<ProfileRepository>>;
|
let mockProfileRepository: jest.Mocked<Partial<ProfileRepository>> = mockProfileRepo;
|
||||||
let mockSectorRepository: jest.Mocked<Partial<SectorRepository>>;
|
let mockSectorRepository: jest.Mocked<Partial<SectorRepository>> = mockSectorRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockProfileRepository = {
|
|
||||||
create: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
list: jest.fn().mockReturnValue(of([])),
|
|
||||||
getByUserId: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
update: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockSectorRepository = {
|
|
||||||
list: jest.fn().mockReturnValue(of([])),
|
|
||||||
getOne: jest.fn().mockReturnValue(of({} as Sector)),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [ProfileListComponent],
|
imports: [ProfileListComponent],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -3,27 +3,21 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
import { ChipsComponent } from './chips.component';
|
import { ChipsComponent } from './chips.component';
|
||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
import { SECTOR_REPOSITORY_TOKEN } from '@app/infrastructure/sectors/sector-repository.token';
|
import { SECTOR_REPOSITORY_TOKEN } from '@app/infrastructure/sectors/sector-repository.token';
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { Sector } from '@app/domain/sectors/sector.model';
|
|
||||||
import { SectorRepository } from '@app/domain/sectors/sector.repository';
|
import { SectorRepository } from '@app/domain/sectors/sector.repository';
|
||||||
|
import { mockSectorRepo } from '@app/testing/sector.mock';
|
||||||
|
|
||||||
describe('ChipsComponent', () => {
|
describe('ChipsComponent', () => {
|
||||||
let component: ChipsComponent;
|
let component: ChipsComponent;
|
||||||
let fixture: ComponentFixture<ChipsComponent>;
|
let fixture: ComponentFixture<ChipsComponent>;
|
||||||
|
|
||||||
let mockSectorRepo: SectorRepository;
|
let mockSectorRepository: jest.Mocked<Partial<SectorRepository>> = mockSectorRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockSectorRepo = {
|
|
||||||
list: jest.fn(),
|
|
||||||
getOne: jest.fn().mockReturnValue(of({} as Sector)),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [ChipsComponent],
|
imports: [ChipsComponent],
|
||||||
providers: [
|
providers: [
|
||||||
provideRouter([]),
|
provideRouter([]),
|
||||||
{ provide: SECTOR_REPOSITORY_TOKEN, useValue: mockSectorRepo },
|
{ provide: SECTOR_REPOSITORY_TOKEN, useValue: mockSectorRepository },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
|
|||||||
@@ -6,21 +6,15 @@ import { Project } from '@app/domain/projects/project.model';
|
|||||||
import { ProjectRepository } from '@app/domain/projects/project.repository';
|
import { ProjectRepository } from '@app/domain/projects/project.repository';
|
||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
import { PROJECT_REPOSITORY_TOKEN } from '@app/infrastructure/projects/project-repository.token';
|
import { PROJECT_REPOSITORY_TOKEN } from '@app/infrastructure/projects/project-repository.token';
|
||||||
|
import { mockProjectRepo } from '@app/testing/project.mock';
|
||||||
|
|
||||||
describe('MyProfileProjectItemComponent', () => {
|
describe('MyProfileProjectItemComponent', () => {
|
||||||
let component: MyProfileProjectItemComponent;
|
let component: MyProfileProjectItemComponent;
|
||||||
let fixture: ComponentFixture<MyProfileProjectItemComponent>;
|
let fixture: ComponentFixture<MyProfileProjectItemComponent>;
|
||||||
|
|
||||||
let mockProjectRepository: jest.Mocked<ProjectRepository>;
|
let mockProjectRepository: jest.Mocked<Partial<ProjectRepository>> = mockProjectRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockProjectRepository = {
|
|
||||||
create: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
list: jest.fn().mockReturnValue(of([])),
|
|
||||||
get: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
update: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [MyProfileProjectItemComponent],
|
imports: [MyProfileProjectItemComponent],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -2,24 +2,16 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
|
|
||||||
import { MyProfileProjectListComponent } from './my-profile-project-list.component';
|
import { MyProfileProjectListComponent } from './my-profile-project-list.component';
|
||||||
import { ProjectRepository } from '@app/domain/projects/project.repository';
|
import { ProjectRepository } from '@app/domain/projects/project.repository';
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
import { PROJECT_REPOSITORY_TOKEN } from '@app/infrastructure/projects/project-repository.token';
|
import { PROJECT_REPOSITORY_TOKEN } from '@app/infrastructure/projects/project-repository.token';
|
||||||
import { Project } from '@app/domain/projects/project.model';
|
import { mockProfileRepo } from '@app/testing/profile.mock';
|
||||||
|
|
||||||
describe('MyProfileProjectListComponent', () => {
|
describe('MyProfileProjectListComponent', () => {
|
||||||
let component: MyProfileProjectListComponent;
|
let component: MyProfileProjectListComponent;
|
||||||
let fixture: ComponentFixture<MyProfileProjectListComponent>;
|
let fixture: ComponentFixture<MyProfileProjectListComponent>;
|
||||||
let mockProjectRepository: jest.Mocked<ProjectRepository>;
|
let mockProjectRepository: jest.Mocked<Partial<ProjectRepository>> = mockProfileRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockProjectRepository = {
|
|
||||||
create: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
list: jest.fn().mockReturnValue(of([])),
|
|
||||||
get: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
update: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [MyProfileProjectListComponent],
|
imports: [MyProfileProjectListComponent],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -3,37 +3,24 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
import { MyProfileUpdateCvFormComponent } from './my-profile-update-cv-form.component';
|
import { MyProfileUpdateCvFormComponent } from './my-profile-update-cv-form.component';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { Profile } from '@app/domain/profiles/profile.model';
|
|
||||||
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
||||||
|
import { ProjectRepository } from '@app/domain/projects/project.repository';
|
||||||
|
import { mockProfileRepo } from '@app/testing/profile.mock';
|
||||||
|
import { mockToastR } from '@app/testing/toastr.mock';
|
||||||
|
|
||||||
describe('MyProfileUpdateCvFormComponent', () => {
|
describe('MyProfileUpdateCvFormComponent', () => {
|
||||||
let component: MyProfileUpdateCvFormComponent;
|
let component: MyProfileUpdateCvFormComponent;
|
||||||
let fixture: ComponentFixture<MyProfileUpdateCvFormComponent>;
|
let fixture: ComponentFixture<MyProfileUpdateCvFormComponent>;
|
||||||
|
|
||||||
let mockToastrService: Partial<ToastrService>;
|
let mockToastrService: jest.Mocked<Partial<ToastrService>> = mockToastR;
|
||||||
let mockProfileRepo: ProfileRepository;
|
let mockProjectRepository: jest.Mocked<Partial<ProjectRepository>> = mockProfileRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockToastrService = {
|
|
||||||
success: jest.fn(),
|
|
||||||
error: jest.fn(),
|
|
||||||
warning: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockProfileRepo = {
|
|
||||||
create: jest.fn(),
|
|
||||||
list: jest.fn(),
|
|
||||||
update: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
getByUserId: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [MyProfileUpdateCvFormComponent],
|
imports: [MyProfileUpdateCvFormComponent],
|
||||||
providers: [
|
providers: [
|
||||||
provideRouter([]),
|
provideRouter([]),
|
||||||
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepo },
|
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProjectRepository },
|
||||||
{ provide: ToastrService, useValue: mockToastrService },
|
{ provide: ToastrService, useValue: mockToastrService },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|||||||
@@ -11,14 +11,18 @@ import { Profile } from '@app/domain/profiles/profile.model';
|
|||||||
import { SectorRepository } from '@app/domain/sectors/sector.repository';
|
import { SectorRepository } from '@app/domain/sectors/sector.repository';
|
||||||
import { Sector } from '@app/domain/sectors/sector.model';
|
import { Sector } from '@app/domain/sectors/sector.model';
|
||||||
import { SECTOR_REPOSITORY_TOKEN } from '@app/infrastructure/sectors/sector-repository.token';
|
import { SECTOR_REPOSITORY_TOKEN } from '@app/infrastructure/sectors/sector-repository.token';
|
||||||
|
import { mockToastR } from '@app/testing/toastr.mock';
|
||||||
|
import { ProjectRepository } from '@app/domain/projects/project.repository';
|
||||||
|
import { mockProfileRepo } from '@app/testing/profile.mock';
|
||||||
|
import { mockSectorRepo } from '@app/testing/sector.mock';
|
||||||
|
|
||||||
describe('MyProfileUpdateFormComponent', () => {
|
describe('MyProfileUpdateFormComponent', () => {
|
||||||
let component: MyProfileUpdateFormComponent;
|
let component: MyProfileUpdateFormComponent;
|
||||||
let fixture: ComponentFixture<MyProfileUpdateFormComponent>;
|
let fixture: ComponentFixture<MyProfileUpdateFormComponent>;
|
||||||
|
|
||||||
let mockToastrService: Partial<ToastrService>;
|
let mockToastrService: jest.Mocked<Partial<ToastrService>> = mockToastR;
|
||||||
let mockProfileRepo: ProfileRepository;
|
let mockProfileRepository: jest.Mocked<Partial<ProfileRepository>> = mockProfileRepo;
|
||||||
let mockSectorRepo: SectorRepository;
|
let mockSectorRepository: jest.Mocked<Partial<SectorRepository>> = mockSectorRepo;
|
||||||
|
|
||||||
const mockProfileData = {
|
const mockProfileData = {
|
||||||
profession: '',
|
profession: '',
|
||||||
@@ -29,32 +33,14 @@ describe('MyProfileUpdateFormComponent', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockToastrService = {
|
|
||||||
warning: jest.fn(),
|
|
||||||
success: jest.fn(),
|
|
||||||
error: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockProfileRepo = {
|
|
||||||
create: jest.fn(),
|
|
||||||
list: jest.fn(),
|
|
||||||
update: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
getByUserId: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockSectorRepo = {
|
|
||||||
list: jest.fn().mockReturnValue(of([])),
|
|
||||||
getOne: jest.fn().mockReturnValue(of({} as Sector)),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [MyProfileUpdateFormComponent],
|
imports: [MyProfileUpdateFormComponent],
|
||||||
providers: [
|
providers: [
|
||||||
FormBuilder,
|
FormBuilder,
|
||||||
provideRouter([]),
|
provideRouter([]),
|
||||||
{ provide: ToastrService, useValue: mockToastrService },
|
{ provide: ToastrService, useValue: mockToastrService },
|
||||||
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepo },
|
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepository },
|
||||||
{ provide: SECTOR_REPOSITORY_TOKEN, useValue: mockSectorRepo },
|
{ provide: SECTOR_REPOSITORY_TOKEN, useValue: mockSectorRepository },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
|
|||||||
@@ -11,49 +11,22 @@ import { AUTH_REPOSITORY_TOKEN } from '@app/infrastructure/authentification/auth
|
|||||||
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
||||||
import { AuthRepository } from '@app/domain/authentification/auth.repository';
|
import { AuthRepository } from '@app/domain/authentification/auth.repository';
|
||||||
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
||||||
|
import { mockAuthRepo } from '@app/testing/auth.mock';
|
||||||
|
import { mockProfileRepo } from '@app/testing/profile.mock';
|
||||||
|
import { mockProjectRepo } from '@app/testing/project.mock';
|
||||||
|
import { mockToastR } from '@app/testing/toastr.mock';
|
||||||
|
|
||||||
describe('MyProfileUpdateProjectFormComponent', () => {
|
describe('MyProfileUpdateProjectFormComponent', () => {
|
||||||
let component: MyProfileUpdateProjectFormComponent;
|
let component: MyProfileUpdateProjectFormComponent;
|
||||||
let fixture: ComponentFixture<MyProfileUpdateProjectFormComponent>;
|
let fixture: ComponentFixture<MyProfileUpdateProjectFormComponent>;
|
||||||
|
|
||||||
let mockToastrService: jest.Mocked<Partial<ToastrService>>;
|
let mockToastrService: jest.Mocked<Partial<ToastrService>> = mockToastR;
|
||||||
let mockProjectRepository: jest.Mocked<Partial<ProjectRepository>>;
|
let mockProjectRepository: jest.Mocked<Partial<ProjectRepository>> = mockProjectRepo;
|
||||||
|
|
||||||
let mockAuthRepository: jest.Mocked<Partial<AuthRepository>>;
|
let mockAuthRepository: jest.Mocked<Partial<AuthRepository>> = mockAuthRepo;
|
||||||
let mockProfileRepo: jest.Mocked<Partial<ProfileRepository>>;
|
let mockProfileRepository: jest.Mocked<Partial<ProfileRepository>> = mockProfileRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockToastrService = {
|
|
||||||
success: jest.fn(),
|
|
||||||
error: jest.fn(),
|
|
||||||
warning: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockProjectRepository = {
|
|
||||||
create: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
list: jest.fn().mockReturnValue(of([])),
|
|
||||||
get: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
update: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
};
|
|
||||||
mockAuthRepository = {
|
|
||||||
get: jest.fn(),
|
|
||||||
login: jest.fn(),
|
|
||||||
sendVerificationEmail: jest.fn(),
|
|
||||||
logout: jest.fn(),
|
|
||||||
isAuthenticated: jest.fn(),
|
|
||||||
isEmailVerified: jest.fn(),
|
|
||||||
register: jest.fn(),
|
|
||||||
sendRequestPasswordReset: jest.fn(),
|
|
||||||
confirmPasswordReset: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockProfileRepo = {
|
|
||||||
create: jest.fn(),
|
|
||||||
list: jest.fn(),
|
|
||||||
update: jest.fn(),
|
|
||||||
getByUserId: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [MyProfileUpdateProjectFormComponent],
|
imports: [MyProfileUpdateProjectFormComponent],
|
||||||
providers: [
|
providers: [
|
||||||
@@ -61,7 +34,7 @@ describe('MyProfileUpdateProjectFormComponent', () => {
|
|||||||
{ provide: ToastrService, useValue: mockToastrService },
|
{ provide: ToastrService, useValue: mockToastrService },
|
||||||
{ provide: PROJECT_REPOSITORY_TOKEN, useValue: mockProjectRepository },
|
{ provide: PROJECT_REPOSITORY_TOKEN, useValue: mockProjectRepository },
|
||||||
{ provide: AUTH_REPOSITORY_TOKEN, useValue: mockAuthRepository },
|
{ provide: AUTH_REPOSITORY_TOKEN, useValue: mockAuthRepository },
|
||||||
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepo },
|
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepository },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
|
|||||||
@@ -7,12 +7,12 @@
|
|||||||
<a
|
<a
|
||||||
[routerLink]="['/']"
|
[routerLink]="['/']"
|
||||||
class="flex items-center space-x-2 group"
|
class="flex items-center space-x-2 group"
|
||||||
aria-label="Accueil TrouveTonProfile"
|
aria-label="Accueil TrouveTonProfil"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="text-lg sm:text-xl font-semibold text-gray-900 dark:text-white group-hover:text-indigo-600 dark:group-hover:text-indigo-400 transition-colors"
|
class="text-lg sm:text-xl font-semibold text-gray-900 dark:text-white group-hover:text-indigo-600 dark:group-hover:text-indigo-400 transition-colors"
|
||||||
>
|
>
|
||||||
TrouveTonProfile
|
TrouveTonProfil
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|||||||
@@ -3,21 +3,22 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
import { NavBarComponent } from './nav-bar.component';
|
import { NavBarComponent } from './nav-bar.component';
|
||||||
import { ThemeService } from '@app/core/services/theme/theme.service';
|
import { ThemeService } from '@app/core/services/theme/theme.service';
|
||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
import { signal } from '@angular/core';
|
|
||||||
import { AuthModel } from '@app/domain/authentification/auth.model';
|
|
||||||
import { User } from '@app/domain/users/user.model';
|
import { User } from '@app/domain/users/user.model';
|
||||||
import { AUTH_REPOSITORY_TOKEN } from '@app/infrastructure/authentification/auth-repository.token';
|
import { AUTH_REPOSITORY_TOKEN } from '@app/infrastructure/authentification/auth-repository.token';
|
||||||
import { AuthRepository } from '@app/domain/authentification/auth.repository';
|
import { AuthRepository } from '@app/domain/authentification/auth.repository';
|
||||||
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
||||||
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
||||||
|
import { mockProfileRepo } from '@app/testing/profile.mock';
|
||||||
|
import { mockAuthRepo } from '@app/testing/auth.mock';
|
||||||
|
import { mockThemeService } from '@app/testing/theme.mock';
|
||||||
|
|
||||||
describe('NavBarComponent', () => {
|
describe('NavBarComponent', () => {
|
||||||
let component: NavBarComponent;
|
let component: NavBarComponent;
|
||||||
let fixture: ComponentFixture<NavBarComponent>;
|
let fixture: ComponentFixture<NavBarComponent>;
|
||||||
let mockThemeService: jest.Mocked<Partial<ThemeService>>;
|
let mockTheme: jest.Mocked<Partial<ThemeService>> = mockThemeService;
|
||||||
|
|
||||||
let mockAuthRepository: jest.Mocked<Partial<AuthRepository>>;
|
let mockAuthRepository: jest.Mocked<Partial<AuthRepository>> = mockAuthRepo;
|
||||||
let mockProfileRepo: jest.Mocked<Partial<ProfileRepository>>;
|
let mockProfileRepository: jest.Mocked<Partial<ProfileRepository>> = mockProfileRepo;
|
||||||
|
|
||||||
const user: User = {
|
const user: User = {
|
||||||
id: 'adbc123',
|
id: 'adbc123',
|
||||||
@@ -32,37 +33,13 @@ describe('NavBarComponent', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockThemeService = {
|
|
||||||
darkModeSignal: signal<string>('null'),
|
|
||||||
updateDarkMode: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockAuthRepository = {
|
|
||||||
get: jest.fn(),
|
|
||||||
login: jest.fn(),
|
|
||||||
sendVerificationEmail: jest.fn(),
|
|
||||||
logout: jest.fn(),
|
|
||||||
isAuthenticated: jest.fn(),
|
|
||||||
isEmailVerified: jest.fn(),
|
|
||||||
register: jest.fn(),
|
|
||||||
sendRequestPasswordReset: jest.fn(),
|
|
||||||
confirmPasswordReset: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockProfileRepo = {
|
|
||||||
create: jest.fn(),
|
|
||||||
list: jest.fn(),
|
|
||||||
update: jest.fn(),
|
|
||||||
getByUserId: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [NavBarComponent],
|
imports: [NavBarComponent],
|
||||||
providers: [
|
providers: [
|
||||||
provideRouter([]),
|
provideRouter([]),
|
||||||
{ provide: ThemeService, useValue: mockThemeService },
|
{ provide: ThemeService, useValue: mockTheme },
|
||||||
{ provide: AUTH_REPOSITORY_TOKEN, useValue: mockAuthRepository },
|
{ provide: AUTH_REPOSITORY_TOKEN, useValue: mockAuthRepository },
|
||||||
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepo },
|
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepository },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
|
|||||||
@@ -2,25 +2,17 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
|
|
||||||
import { ProjectListComponent } from './project-list.component';
|
import { ProjectListComponent } from './project-list.component';
|
||||||
import { ProjectRepository } from '@app/domain/projects/project.repository';
|
import { ProjectRepository } from '@app/domain/projects/project.repository';
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { Project } from '@app/domain/projects/project.model';
|
|
||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
import { PROJECT_REPOSITORY_TOKEN } from '@app/infrastructure/projects/project-repository.token';
|
import { PROJECT_REPOSITORY_TOKEN } from '@app/infrastructure/projects/project-repository.token';
|
||||||
|
import { mockProjectRepo } from '@app/testing/project.mock';
|
||||||
|
|
||||||
describe('ProjectListComponent', () => {
|
describe('ProjectListComponent', () => {
|
||||||
let component: ProjectListComponent;
|
let component: ProjectListComponent;
|
||||||
let fixture: ComponentFixture<ProjectListComponent>;
|
let fixture: ComponentFixture<ProjectListComponent>;
|
||||||
|
|
||||||
let mockProjectRepository: jest.Mocked<ProjectRepository>;
|
let mockProjectRepository: jest.Mocked<ProjectRepository> = mockProjectRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockProjectRepository = {
|
|
||||||
create: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
list: jest.fn().mockReturnValue(of([])),
|
|
||||||
get: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
update: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [ProjectListComponent],
|
imports: [ProjectListComponent],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
|
||||||
import { UntilDestroy } from '@ngneat/until-destroy';
|
import { UntilDestroy } from '@ngneat/until-destroy';
|
||||||
import { ProjectItemComponent } from '@app/shared/components/project-item/project-item.component';
|
import { ProjectItemComponent } from '@app/shared/components/project-item/project-item.component';
|
||||||
import { ProjectFacade } from '@app/ui/projects/project.facade';
|
import { ProjectFacade } from '@app/ui/projects/project.facade';
|
||||||
@@ -11,14 +11,14 @@ import { ProjectFacade } from '@app/ui/projects/project.facade';
|
|||||||
styleUrl: './project-list.component.scss',
|
styleUrl: './project-list.component.scss',
|
||||||
})
|
})
|
||||||
@UntilDestroy()
|
@UntilDestroy()
|
||||||
export class ProjectListComponent implements OnInit {
|
export class ProjectListComponent implements OnChanges {
|
||||||
@Input({ required: true }) userProjectId = '';
|
@Input({ required: true }) userProjectId = '';
|
||||||
|
|
||||||
private readonly projectFacade = new ProjectFacade();
|
private readonly projectFacade = new ProjectFacade();
|
||||||
|
|
||||||
protected projects = this.projectFacade.projects;
|
protected projects = this.projectFacade.projects;
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
this.projectFacade.load(this.userProjectId);
|
this.projectFacade.load(this.userProjectId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,31 +4,18 @@ import { ProjectPictureFormComponent } from './project-picture-form.component';
|
|||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { PROJECT_REPOSITORY_TOKEN } from '@app/infrastructure/projects/project-repository.token';
|
import { PROJECT_REPOSITORY_TOKEN } from '@app/infrastructure/projects/project-repository.token';
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { Project } from '@app/domain/projects/project.model';
|
|
||||||
import { ProjectRepository } from '@app/domain/projects/project.repository';
|
import { ProjectRepository } from '@app/domain/projects/project.repository';
|
||||||
|
import { mockToastR } from '@app/testing/toastr.mock';
|
||||||
|
import { mockProjectRepo } from '@app/testing/project.mock';
|
||||||
|
|
||||||
describe('ProjectPictureFormComponent', () => {
|
describe('ProjectPictureFormComponent', () => {
|
||||||
let component: ProjectPictureFormComponent;
|
let component: ProjectPictureFormComponent;
|
||||||
let fixture: ComponentFixture<ProjectPictureFormComponent>;
|
let fixture: ComponentFixture<ProjectPictureFormComponent>;
|
||||||
|
|
||||||
let mockToastrService: Partial<ToastrService>;
|
let mockToastrService: jest.Mocked<Partial<ToastrService>> = mockToastR;
|
||||||
let mockProjectRepository: jest.Mocked<ProjectRepository>;
|
let mockProjectRepository: jest.Mocked<Partial<ProjectRepository>> = mockProjectRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockToastrService = {
|
|
||||||
success: jest.fn(),
|
|
||||||
error: jest.fn(),
|
|
||||||
warning: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockProjectRepository = {
|
|
||||||
create: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
list: jest.fn().mockReturnValue(of([])),
|
|
||||||
get: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
update: jest.fn().mockReturnValue(of({} as Project)),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [ProjectPictureFormComponent],
|
imports: [ProjectPictureFormComponent],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -5,31 +5,22 @@ import { provideRouter } from '@angular/router';
|
|||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
import { UserRepository } from '@app/domain/users/user.repository';
|
import { UserRepository } from '@app/domain/users/user.repository';
|
||||||
import { USER_REPOSITORY_TOKEN } from '@app/infrastructure/users/user-repository.token';
|
import { USER_REPOSITORY_TOKEN } from '@app/infrastructure/users/user-repository.token';
|
||||||
|
import { mockToastR } from '@app/testing/toastr.mock';
|
||||||
|
import { mockUserRepo } from '@app/testing/user.mock';
|
||||||
|
|
||||||
describe('UserAvatarFormComponent', () => {
|
describe('UserAvatarFormComponent', () => {
|
||||||
let component: UserAvatarFormComponent;
|
let component: UserAvatarFormComponent;
|
||||||
let fixture: ComponentFixture<UserAvatarFormComponent>;
|
let fixture: ComponentFixture<UserAvatarFormComponent>;
|
||||||
|
|
||||||
let mockToastrService: Partial<ToastrService>;
|
let mockToastrService: jest.Mocked<Partial<ToastrService>> = mockToastR;
|
||||||
let mockUserRepo: UserRepository;
|
let mockUserRepository: jest.Mocked<Partial<UserRepository>> = mockUserRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockToastrService = {
|
|
||||||
warning: jest.fn(),
|
|
||||||
success: jest.fn(),
|
|
||||||
error: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockUserRepo = {
|
|
||||||
update: jest.fn(),
|
|
||||||
getUserById: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [UserAvatarFormComponent],
|
imports: [UserAvatarFormComponent],
|
||||||
providers: [
|
providers: [
|
||||||
provideRouter([]),
|
provideRouter([]),
|
||||||
{ provide: USER_REPOSITORY_TOKEN, useValue: mockUserRepo },
|
{ provide: USER_REPOSITORY_TOKEN, useValue: mockUserRepository },
|
||||||
{ provide: ToastrService, useValue: mockToastrService },
|
{ provide: ToastrService, useValue: mockToastrService },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|||||||
@@ -6,32 +6,23 @@ import { provideRouter } from '@angular/router';
|
|||||||
import { FormBuilder } from '@angular/forms';
|
import { FormBuilder } from '@angular/forms';
|
||||||
import { USER_REPOSITORY_TOKEN } from '@app/infrastructure/users/user-repository.token';
|
import { USER_REPOSITORY_TOKEN } from '@app/infrastructure/users/user-repository.token';
|
||||||
import { UserRepository } from '@app/domain/users/user.repository';
|
import { UserRepository } from '@app/domain/users/user.repository';
|
||||||
|
import { mockToastR } from '@app/testing/toastr.mock';
|
||||||
|
import { mockUserRepo } from '@app/testing/user.mock';
|
||||||
|
|
||||||
describe('UserFormComponent', () => {
|
describe('UserFormComponent', () => {
|
||||||
let component: UserFormComponent;
|
let component: UserFormComponent;
|
||||||
let fixture: ComponentFixture<UserFormComponent>;
|
let fixture: ComponentFixture<UserFormComponent>;
|
||||||
|
|
||||||
let mockToastrService: Partial<ToastrService>;
|
let mockToastrService: jest.Mocked<Partial<ToastrService>> = mockToastR;
|
||||||
let mockUserRepo: UserRepository;
|
let mockUserRepository: jest.Mocked<Partial<UserRepository>> = mockUserRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockToastrService = {
|
|
||||||
warning: jest.fn(),
|
|
||||||
success: jest.fn(),
|
|
||||||
error: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockUserRepo = {
|
|
||||||
update: jest.fn(),
|
|
||||||
getUserById: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [UserFormComponent],
|
imports: [UserFormComponent],
|
||||||
providers: [
|
providers: [
|
||||||
provideRouter([]),
|
provideRouter([]),
|
||||||
FormBuilder,
|
FormBuilder,
|
||||||
{ provide: USER_REPOSITORY_TOKEN, useValue: mockUserRepo },
|
{ provide: USER_REPOSITORY_TOKEN, useValue: mockUserRepository },
|
||||||
{ provide: ToastrService, useValue: mockToastrService },
|
{ provide: ToastrService, useValue: mockToastrService },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|||||||
@@ -6,34 +6,23 @@ import { AuthFacade } from '@app/ui/authentification/auth.facade';
|
|||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { ActionType } from '@app/domain/action-type.util';
|
import { ActionType } from '@app/domain/action-type.util';
|
||||||
import { signal, WritableSignal } from '@angular/core';
|
import { signal, WritableSignal } from '@angular/core';
|
||||||
|
import { mockToastR } from '@app/testing/toastr.mock';
|
||||||
|
import { mockAuthenticationFacade } from '@app/testing/ui/authentification/auth.facade.mock';
|
||||||
|
|
||||||
describe('UserPasswordFormComponent', () => {
|
describe('UserPasswordFormComponent', () => {
|
||||||
let component: UserPasswordFormComponent;
|
let component: UserPasswordFormComponent;
|
||||||
let fixture: ComponentFixture<UserPasswordFormComponent>;
|
let fixture: ComponentFixture<UserPasswordFormComponent>;
|
||||||
|
|
||||||
let mockToastrService: Partial<ToastrService>;
|
let mockToastrService: jest.Mocked<Partial<ToastrService>> = mockToastR;
|
||||||
|
|
||||||
// On mocke la Facade car c'est ce que le composant utilise directement
|
// On mocke la Facade car c'est ce que le composant utilise directement
|
||||||
let mockAuthFacade: {
|
let mockAuthFacade: {
|
||||||
sendRequestPasswordReset: jest.Mock;
|
sendRequestPasswordReset: jest.Mock;
|
||||||
loading: WritableSignal<{ isLoading: boolean; action: ActionType }>;
|
loading: WritableSignal<{ isLoading: boolean; action: ActionType }>;
|
||||||
error: WritableSignal<{ hasError: boolean }>;
|
error: WritableSignal<{ hasError: boolean }>;
|
||||||
};
|
} = mockAuthenticationFacade;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockToastrService = {
|
|
||||||
warning: jest.fn(),
|
|
||||||
success: jest.fn(),
|
|
||||||
info: jest.fn(),
|
|
||||||
error: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockAuthFacade = {
|
|
||||||
sendRequestPasswordReset: jest.fn(),
|
|
||||||
loading: signal({ isLoading: false, action: ActionType.NONE }),
|
|
||||||
error: signal({ hasError: false }),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [UserPasswordFormComponent],
|
imports: [UserPasswordFormComponent],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
@if (user() !== undefined) {
|
@if (user() !== undefined) {
|
||||||
<a [routerLink]="[user().slug]" [state]="{ user: user(), profile }" class="block group">
|
<a [routerLink]="[slug()]" [state]="{ user: user(), profile }" class="block group">
|
||||||
<!-- Card du profil -->
|
<!-- Card du profil -->
|
||||||
<div
|
<div
|
||||||
class="relative bg-white dark:bg-gray-800 rounded-xl shadow-lg overflow-hidden transition-all duration-300 hover:shadow-2xl hover:-translate-y-2"
|
class="relative bg-white dark:bg-gray-800 rounded-xl shadow-lg overflow-hidden transition-all duration-300 hover:shadow-2xl hover:-translate-y-2"
|
||||||
|
|||||||
@@ -9,31 +9,23 @@ import { of } from 'rxjs';
|
|||||||
import { SECTOR_REPOSITORY_TOKEN } from '@app/infrastructure/sectors/sector-repository.token';
|
import { SECTOR_REPOSITORY_TOKEN } from '@app/infrastructure/sectors/sector-repository.token';
|
||||||
import { SectorRepository } from '@app/domain/sectors/sector.repository';
|
import { SectorRepository } from '@app/domain/sectors/sector.repository';
|
||||||
import { Sector } from '@app/domain/sectors/sector.model';
|
import { Sector } from '@app/domain/sectors/sector.model';
|
||||||
|
import { mockUserRepo } from '@app/testing/user.mock';
|
||||||
|
import { mockSectorRepo } from '@app/testing/sector.mock';
|
||||||
|
|
||||||
describe('VerticalProfileItemComponent', () => {
|
describe('VerticalProfileItemComponent', () => {
|
||||||
let component: VerticalProfileItemComponent;
|
let component: VerticalProfileItemComponent;
|
||||||
let fixture: ComponentFixture<VerticalProfileItemComponent>;
|
let fixture: ComponentFixture<VerticalProfileItemComponent>;
|
||||||
|
|
||||||
let mockUserRepo: UserRepository;
|
let mockUserRepository: jest.Mocked<Partial<UserRepository>> = mockUserRepo;
|
||||||
let mockSectorRepo: SectorRepository;
|
let mockSectorRepository: jest.Mocked<Partial<SectorRepository>> = mockSectorRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockUserRepo = {
|
|
||||||
update: jest.fn().mockReturnValue(of({} as User)),
|
|
||||||
getUserById: jest.fn().mockReturnValue(of({} as User)),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockSectorRepo = {
|
|
||||||
list: jest.fn().mockReturnValue(of({} as Sector)),
|
|
||||||
getOne: jest.fn().mockReturnValue(of({} as Sector)),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [VerticalProfileItemComponent],
|
imports: [VerticalProfileItemComponent],
|
||||||
providers: [
|
providers: [
|
||||||
provideRouter([]),
|
provideRouter([]),
|
||||||
{ provide: USER_REPOSITORY_TOKEN, useValue: mockUserRepo },
|
{ provide: USER_REPOSITORY_TOKEN, useValue: mockUserRepository },
|
||||||
{ provide: SECTOR_REPOSITORY_TOKEN, useValue: mockSectorRepo },
|
{ provide: SECTOR_REPOSITORY_TOKEN, useValue: mockSectorRepository },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, inject, Input, OnInit } from '@angular/core';
|
import { Component, computed, inject, Input, OnInit } from '@angular/core';
|
||||||
import { Router, RouterLink } from '@angular/router';
|
import { Router, RouterLink } from '@angular/router';
|
||||||
import { UntilDestroy } from '@ngneat/until-destroy';
|
import { UntilDestroy } from '@ngneat/until-destroy';
|
||||||
import { environment } from '@env/environment';
|
import { environment } from '@env/environment';
|
||||||
@@ -23,6 +23,12 @@ export class VerticalProfileItemComponent implements OnInit {
|
|||||||
protected readonly loading = this.facade.loading;
|
protected readonly loading = this.facade.loading;
|
||||||
protected readonly error = this.facade.error;
|
protected readonly error = this.facade.error;
|
||||||
|
|
||||||
|
protected slug = computed(() => {
|
||||||
|
const slug = this.user().slug ?? '';
|
||||||
|
const profileId = this.profile.id ? this.profile.id : '';
|
||||||
|
return slug === '' ? profileId : slug.concat('-', profileId);
|
||||||
|
});
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.facade.loadOne(this.profile.utilisateur);
|
this.facade.loadOne(this.profile.utilisateur);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,26 +9,16 @@ import { of } from 'rxjs';
|
|||||||
import { Profile } from '@app/domain/profiles/profile.model';
|
import { Profile } from '@app/domain/profiles/profile.model';
|
||||||
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
||||||
import { Sector } from '@app/domain/sectors/sector.model';
|
import { Sector } from '@app/domain/sectors/sector.model';
|
||||||
|
import { mockProfileRepo } from '@app/testing/profile.mock';
|
||||||
|
import { mockSectorRepo } from '@app/testing/sector.mock';
|
||||||
|
|
||||||
describe('FilterComponent', () => {
|
describe('FilterComponent', () => {
|
||||||
let component: FilterComponent;
|
let component: FilterComponent;
|
||||||
let fixture: ComponentFixture<FilterComponent>;
|
let fixture: ComponentFixture<FilterComponent>;
|
||||||
let mockProfileRepository: jest.Mocked<Partial<ProfileRepository>>;
|
let mockProfileRepository: jest.Mocked<Partial<ProfileRepository>> = mockProfileRepo;
|
||||||
let mockSectorRepository: jest.Mocked<Partial<SectorRepository>>;
|
let mockSectorRepository: jest.Mocked<Partial<SectorRepository>> = mockSectorRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockProfileRepository = {
|
|
||||||
create: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
list: jest.fn().mockReturnValue(of([])),
|
|
||||||
getByUserId: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
update: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockSectorRepository = {
|
|
||||||
list: jest.fn().mockReturnValue(of([])),
|
|
||||||
getOne: jest.fn().mockReturnValue(of({} as Sector)),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [FilterComponent],
|
imports: [FilterComponent],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -8,43 +8,20 @@ import { AuthRepository } from '@app/domain/authentification/auth.repository';
|
|||||||
import { AUTH_REPOSITORY_TOKEN } from '@app/infrastructure/authentification/auth-repository.token';
|
import { AUTH_REPOSITORY_TOKEN } from '@app/infrastructure/authentification/auth-repository.token';
|
||||||
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
||||||
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
||||||
|
import { mockAuthRepo } from '@app/testing/auth.mock';
|
||||||
|
import { mockProfileRepo } from '@app/testing/profile.mock';
|
||||||
|
import { mockToastR } from '@app/testing/toastr.mock';
|
||||||
|
|
||||||
describe('LoginComponent', () => {
|
describe('LoginComponent', () => {
|
||||||
let component: LoginComponent;
|
let component: LoginComponent;
|
||||||
let fixture: ComponentFixture<LoginComponent>;
|
let fixture: ComponentFixture<LoginComponent>;
|
||||||
|
|
||||||
// Mocks des services
|
// Mocks des services
|
||||||
let mockToastrService: Partial<ToastrService>;
|
let mockToastrService: Partial<ToastrService> = mockToastR;
|
||||||
let mockAuthRepository: jest.Mocked<Partial<AuthRepository>>;
|
let mockAuthRepository: jest.Mocked<Partial<AuthRepository>> = mockAuthRepo;
|
||||||
let mockProfileRepo: jest.Mocked<Partial<ProfileRepository>>;
|
let mockProfileRepository: jest.Mocked<Partial<ProfileRepository>> = mockProfileRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockToastrService = {
|
|
||||||
warning: jest.fn(),
|
|
||||||
success: jest.fn(),
|
|
||||||
info: jest.fn(),
|
|
||||||
error: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockAuthRepository = {
|
|
||||||
get: jest.fn(),
|
|
||||||
login: jest.fn(),
|
|
||||||
sendVerificationEmail: jest.fn(),
|
|
||||||
logout: jest.fn(),
|
|
||||||
isAuthenticated: jest.fn(),
|
|
||||||
isEmailVerified: jest.fn(),
|
|
||||||
register: jest.fn(),
|
|
||||||
sendRequestPasswordReset: jest.fn(),
|
|
||||||
confirmPasswordReset: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockProfileRepo = {
|
|
||||||
create: jest.fn(),
|
|
||||||
list: jest.fn(),
|
|
||||||
update: jest.fn(),
|
|
||||||
getByUserId: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [LoginComponent],
|
imports: [LoginComponent],
|
||||||
providers: [
|
providers: [
|
||||||
@@ -52,7 +29,7 @@ describe('LoginComponent', () => {
|
|||||||
provideRouter([]),
|
provideRouter([]),
|
||||||
{ provide: ToastrService, useValue: mockToastrService },
|
{ provide: ToastrService, useValue: mockToastrService },
|
||||||
{ provide: AUTH_REPOSITORY_TOKEN, useValue: mockAuthRepository },
|
{ provide: AUTH_REPOSITORY_TOKEN, useValue: mockAuthRepository },
|
||||||
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepo },
|
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepository },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
|
|||||||
@@ -7,47 +7,25 @@ import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
|||||||
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
||||||
import { AUTH_REPOSITORY_TOKEN } from '@app/infrastructure/authentification/auth-repository.token';
|
import { AUTH_REPOSITORY_TOKEN } from '@app/infrastructure/authentification/auth-repository.token';
|
||||||
import { AuthRepository } from '@app/domain/authentification/auth.repository';
|
import { AuthRepository } from '@app/domain/authentification/auth.repository';
|
||||||
|
import { mockToastR } from '@app/testing/toastr.mock';
|
||||||
|
import { mockProfileRepo } from '@app/testing/profile.mock';
|
||||||
|
import { mockAuthRepo } from '@app/testing/auth.mock';
|
||||||
|
|
||||||
describe('RegisterComponent', () => {
|
describe('RegisterComponent', () => {
|
||||||
let component: RegisterComponent;
|
let component: RegisterComponent;
|
||||||
let fixture: ComponentFixture<RegisterComponent>;
|
let fixture: ComponentFixture<RegisterComponent>;
|
||||||
|
|
||||||
let mockToastrService: jest.Mocked<Partial<ToastrService>>;
|
let mockToastrService: jest.Mocked<Partial<ToastrService>> = mockToastR;
|
||||||
let mockProfileRepo: jest.Mocked<Partial<ProfileRepository>>;
|
let mockProfileRepository: jest.Mocked<Partial<ProfileRepository>> = mockProfileRepo;
|
||||||
let mockAuthRepository: jest.Mocked<Partial<AuthRepository>>;
|
let mockAuthRepository: jest.Mocked<Partial<AuthRepository>> = mockAuthRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockProfileRepo = {
|
|
||||||
create: jest.fn(),
|
|
||||||
list: jest.fn(),
|
|
||||||
update: jest.fn(),
|
|
||||||
getByUserId: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockToastrService = {
|
|
||||||
success: jest.fn(),
|
|
||||||
error: jest.fn(),
|
|
||||||
warning: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockAuthRepository = {
|
|
||||||
get: jest.fn(),
|
|
||||||
login: jest.fn(),
|
|
||||||
sendVerificationEmail: jest.fn(),
|
|
||||||
logout: jest.fn(),
|
|
||||||
isAuthenticated: jest.fn(),
|
|
||||||
isEmailVerified: jest.fn(),
|
|
||||||
register: jest.fn(),
|
|
||||||
sendRequestPasswordReset: jest.fn(),
|
|
||||||
confirmPasswordReset: jest.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [RegisterComponent],
|
imports: [RegisterComponent],
|
||||||
providers: [
|
providers: [
|
||||||
provideRouter([]),
|
provideRouter([]),
|
||||||
{ provide: ToastrService, useValue: mockToastrService },
|
{ provide: ToastrService, useValue: mockToastrService },
|
||||||
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepo },
|
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepository },
|
||||||
{ provide: AUTH_REPOSITORY_TOKEN, useValue: mockAuthRepository },
|
{ provide: AUTH_REPOSITORY_TOKEN, useValue: mockAuthRepository },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|||||||
@@ -4,37 +4,25 @@ import { SearchComponent } from './search.component';
|
|||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
|
||||||
import { SECTOR_REPOSITORY_TOKEN } from '@app/infrastructure/sectors/sector-repository.token';
|
import { SECTOR_REPOSITORY_TOKEN } from '@app/infrastructure/sectors/sector-repository.token';
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { Profile } from '@app/domain/profiles/profile.model';
|
|
||||||
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
import { ProfileRepository } from '@app/domain/profiles/profile.repository';
|
||||||
import { SectorRepository } from '@app/domain/sectors/sector.repository';
|
import { SectorRepository } from '@app/domain/sectors/sector.repository';
|
||||||
import { Sector } from '@app/domain/sectors/sector.model';
|
import { mockProfileRepo } from '@app/testing/profile.mock';
|
||||||
|
import { mockSectorRepo } from '@app/testing/sector.mock';
|
||||||
|
|
||||||
describe('SearchComponent', () => {
|
describe('SearchComponent', () => {
|
||||||
let component: SearchComponent;
|
let component: SearchComponent;
|
||||||
let fixture: ComponentFixture<SearchComponent>;
|
let fixture: ComponentFixture<SearchComponent>;
|
||||||
|
|
||||||
let mockProfileRepo: jest.Mocked<Partial<ProfileRepository>>;
|
let mockProfileRepository: jest.Mocked<Partial<ProfileRepository>> = mockProfileRepo;
|
||||||
let mockSectorRepo: jest.Mocked<Partial<SectorRepository>>;
|
let mockSectorRepository: jest.Mocked<Partial<SectorRepository>> = mockSectorRepo;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockProfileRepo = {
|
|
||||||
create: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
list: jest.fn().mockReturnValue(of([])),
|
|
||||||
getByUserId: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
update: jest.fn().mockReturnValue(of({} as Profile)),
|
|
||||||
};
|
|
||||||
|
|
||||||
mockSectorRepo = {
|
|
||||||
list: jest.fn().mockReturnValue(of([])),
|
|
||||||
getOne: jest.fn().mockReturnValue(of({} as Sector)),
|
|
||||||
};
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [SearchComponent],
|
imports: [SearchComponent],
|
||||||
providers: [
|
providers: [
|
||||||
provideRouter([]),
|
provideRouter([]),
|
||||||
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepo },
|
{ provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepository },
|
||||||
{ provide: SECTOR_REPOSITORY_TOKEN, useValue: mockSectorRepo },
|
{ provide: SECTOR_REPOSITORY_TOKEN, useValue: mockSectorRepository },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
|
|||||||
@@ -5,28 +5,22 @@ import { provideRouter } from '@angular/router';
|
|||||||
import { UserRepository } from '@app/domain/users/user.repository';
|
import { UserRepository } from '@app/domain/users/user.repository';
|
||||||
import { USER_REPOSITORY_TOKEN } from '@app/infrastructure/users/user-repository.token';
|
import { USER_REPOSITORY_TOKEN } from '@app/infrastructure/users/user-repository.token';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
|
import { mockUserRepo } from '@app/testing/user.mock';
|
||||||
|
import { mockToastR } from '@app/testing/toastr.mock';
|
||||||
|
|
||||||
describe('UpdateUserComponent', () => {
|
describe('UpdateUserComponent', () => {
|
||||||
let component: UpdateUserComponent;
|
let component: UpdateUserComponent;
|
||||||
let fixture: ComponentFixture<UpdateUserComponent>;
|
let fixture: ComponentFixture<UpdateUserComponent>;
|
||||||
|
|
||||||
let mockUserRepo: jest.Mocked<Partial<UserRepository>>;
|
let mockUserRepository: jest.Mocked<Partial<UserRepository>> = mockUserRepo;
|
||||||
let mockToastrService: jest.Mocked<Partial<ToastrService>>;
|
let mockToastrService: jest.Mocked<Partial<ToastrService>> = mockToastR;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockUserRepo = {
|
|
||||||
getUserById: jest.fn(),
|
|
||||||
};
|
|
||||||
mockToastrService = {
|
|
||||||
warning: jest.fn(),
|
|
||||||
success: jest.fn(),
|
|
||||||
error: jest.fn(),
|
|
||||||
};
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [UpdateUserComponent],
|
imports: [UpdateUserComponent],
|
||||||
providers: [
|
providers: [
|
||||||
provideRouter([]),
|
provideRouter([]),
|
||||||
{ provide: USER_REPOSITORY_TOKEN, useValue: mockUserRepo },
|
{ provide: USER_REPOSITORY_TOKEN, useValue: mockUserRepository },
|
||||||
{ provide: ToastrService, useValue: mockToastrService },
|
{ provide: ToastrService, useValue: mockToastrService },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|||||||
11
src/app/testing/auth.mock.ts
Normal file
11
src/app/testing/auth.mock.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export const mockAuthRepo = {
|
||||||
|
get: jest.fn(),
|
||||||
|
login: jest.fn(),
|
||||||
|
sendVerificationEmail: jest.fn(),
|
||||||
|
logout: jest.fn(),
|
||||||
|
isAuthenticated: jest.fn(),
|
||||||
|
isEmailVerified: jest.fn(),
|
||||||
|
register: jest.fn(),
|
||||||
|
sendRequestPasswordReset: jest.fn(),
|
||||||
|
confirmPasswordReset: jest.fn(),
|
||||||
|
};
|
||||||
@@ -8,8 +8,8 @@ export class FakeProfileRepository implements ProfileRepository {
|
|||||||
return of(mockProfilePaginated);
|
return of(mockProfilePaginated);
|
||||||
}
|
}
|
||||||
|
|
||||||
getByUserId(userId: string): Observable<Profile> {
|
getById(profileId: string): Observable<Profile> {
|
||||||
const profile = mockProfiles.find((p) => p.utilisateur === userId) ?? ({} as Profile);
|
const profile = mockProfiles.find((p) => p.utilisateur === profileId) ?? ({} as Profile);
|
||||||
return of(profile);
|
return of(profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ describe('PbProfileRepository', () => {
|
|||||||
// Création d’un faux client PocketBase avec les méthodes dont on a besoin
|
// Création d’un faux client PocketBase avec les méthodes dont on a besoin
|
||||||
mockCollection = {
|
mockCollection = {
|
||||||
getList: jest.fn(),
|
getList: jest.fn(),
|
||||||
getFirstListItem: jest.fn(),
|
getOne: jest.fn(),
|
||||||
create: jest.fn(),
|
create: jest.fn(),
|
||||||
update: jest.fn(),
|
update: jest.fn(),
|
||||||
};
|
};
|
||||||
@@ -54,13 +54,13 @@ describe('PbProfileRepository', () => {
|
|||||||
// ------------------------------------------
|
// ------------------------------------------
|
||||||
// 🔹 TEST : getByUserId()
|
// 🔹 TEST : getByUserId()
|
||||||
// ------------------------------------------
|
// ------------------------------------------
|
||||||
it('devrait appeler pb.collection("profiles").getFirstListItem() avec le bon filtre utilisateur', () => {
|
it('devrait appeler pb.collection("profiles").getOne() avec le bon filtre utilisateur', () => {
|
||||||
const userId = '1';
|
const profileId = '1';
|
||||||
|
|
||||||
mockCollection.getFirstListItem.mockResolvedValue(mockProfiles);
|
mockCollection.getOne.mockResolvedValue(mockProfiles);
|
||||||
|
|
||||||
repo.getByUserId(userId).subscribe((result) => {
|
repo.getById(profileId).subscribe((result) => {
|
||||||
expect(mockCollection.getFirstListItem).toHaveBeenCalledWith(`utilisateur="${userId}"`);
|
expect(mockCollection.getOne).toHaveBeenCalledWith(`${profileId}`, { expand: 'utilisateur' });
|
||||||
expect(result).toEqual(mockProfiles[0]);
|
expect(result).toEqual(mockProfiles[0]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Profile, ProfilePaginated } from '@app/domain/profiles/profile.model';
|
import { Profile, ProfilePaginated } from '@app/domain/profiles/profile.model';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
|
||||||
export const mockProfiles: Profile[] = [
|
export const mockProfiles: Profile[] = [
|
||||||
{
|
{
|
||||||
@@ -38,3 +39,10 @@ export const mockProfilePaginated: ProfilePaginated = {
|
|||||||
totalItems: 1,
|
totalItems: 1,
|
||||||
items: mockProfiles,
|
items: mockProfiles,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const mockProfileRepo = {
|
||||||
|
create: jest.fn().mockReturnValue(of({} as Profile)),
|
||||||
|
list: jest.fn().mockReturnValue(of([])),
|
||||||
|
getById: jest.fn().mockReturnValue(of({} as Profile)),
|
||||||
|
update: jest.fn().mockReturnValue(of({} as Profile)),
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Project } from '@app/domain/projects/project.model';
|
import { Project } from '@app/domain/projects/project.model';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
|
||||||
export const fakeProjects: Project[] = [
|
export const fakeProjects: Project[] = [
|
||||||
{
|
{
|
||||||
@@ -57,3 +58,10 @@ export const fakeProjects: Project[] = [
|
|||||||
utilisateur: 'user_001',
|
utilisateur: 'user_001',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const mockProjectRepo = {
|
||||||
|
create: jest.fn().mockReturnValue(of({} as Project)),
|
||||||
|
list: jest.fn().mockReturnValue(of([])),
|
||||||
|
get: jest.fn().mockReturnValue(of({} as Project)),
|
||||||
|
update: jest.fn().mockReturnValue(of({} as Project)),
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Sector } from '@app/domain/sectors/sector.model';
|
import { Sector } from '@app/domain/sectors/sector.model';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
|
||||||
export const fakeSectors: Sector[] = [
|
export const fakeSectors: Sector[] = [
|
||||||
{
|
{
|
||||||
@@ -32,3 +33,8 @@ export const fakeSectors: Sector[] = [
|
|||||||
nom: 'Ressources humaines',
|
nom: 'Ressources humaines',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const mockSectorRepo = {
|
||||||
|
list: jest.fn().mockReturnValue(of([])),
|
||||||
|
getOne: jest.fn().mockReturnValue(of({} as Sector)),
|
||||||
|
};
|
||||||
|
|||||||
6
src/app/testing/theme.mock.ts
Normal file
6
src/app/testing/theme.mock.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { signal } from '@angular/core';
|
||||||
|
|
||||||
|
export const mockThemeService = {
|
||||||
|
darkModeSignal: signal<string>('null'),
|
||||||
|
updateDarkMode: jest.fn(),
|
||||||
|
};
|
||||||
6
src/app/testing/toastr.mock.ts
Normal file
6
src/app/testing/toastr.mock.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export const mockToastR = {
|
||||||
|
warning: jest.fn(),
|
||||||
|
success: jest.fn(),
|
||||||
|
info: jest.fn(),
|
||||||
|
error: jest.fn(),
|
||||||
|
};
|
||||||
8
src/app/testing/ui/authentification/auth.facade.mock.ts
Normal file
8
src/app/testing/ui/authentification/auth.facade.mock.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { signal } from '@angular/core';
|
||||||
|
import { ActionType } from '@app/domain/action-type.util';
|
||||||
|
|
||||||
|
export const mockAuthenticationFacade = {
|
||||||
|
sendRequestPasswordReset: jest.fn(),
|
||||||
|
loading: signal({ isLoading: false, action: ActionType.NONE }),
|
||||||
|
error: signal({ hasError: false }),
|
||||||
|
};
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { User } from '@app/domain/users/user.model';
|
import { User } from '@app/domain/users/user.model';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
|
||||||
export const fakeUsers: User[] = [
|
export const fakeUsers: User[] = [
|
||||||
{
|
{
|
||||||
@@ -13,3 +14,8 @@ export const fakeUsers: User[] = [
|
|||||||
verified: false,
|
verified: false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const mockUserRepo = {
|
||||||
|
getUserById: jest.fn().mockReturnValue(of({} as User)),
|
||||||
|
update: jest.fn(),
|
||||||
|
};
|
||||||
|
|||||||
@@ -67,9 +67,9 @@ export class ProfileFacade {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
loadOne(userId: string) {
|
loadOne(profileId: string) {
|
||||||
this.handleError(ActionType.READ, false, null, true);
|
this.handleError(ActionType.READ, false, null, true);
|
||||||
this.getUseCase.execute(userId).subscribe({
|
this.getUseCase.execute(profileId).subscribe({
|
||||||
next: (profile: Profile) => {
|
next: (profile: Profile) => {
|
||||||
this.profile.set(ProfilePresenter.toViewModel(profile));
|
this.profile.set(ProfilePresenter.toViewModel(profile));
|
||||||
this.handleError(ActionType.READ, false, null, false);
|
this.handleError(ActionType.READ, false, null, false);
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { User } from '@app/domain/users/user.model';
|
|||||||
export class UserPresenter {
|
export class UserPresenter {
|
||||||
toViewModel(user: User): UserViewModel {
|
toViewModel(user: User): UserViewModel {
|
||||||
const slug = user.name
|
const slug = user.name
|
||||||
? user.name.toLowerCase().replace(/\s/g, '-')
|
? this.generateProfileSlug(user.name, user.id)
|
||||||
: user.email.split('@')[0].toLowerCase().trim();
|
: this.generateProfileSlug('Non renséigné');
|
||||||
|
|
||||||
let userViewModel: UserViewModel = {
|
let userViewModel: UserViewModel = {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
@@ -30,4 +30,16 @@ export class UserPresenter {
|
|||||||
toViewModels(users: User[]): UserViewModel[] {
|
toViewModels(users: User[]): UserViewModel[] {
|
||||||
return users.map(this.toViewModel);
|
return users.map(this.toViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private generateProfileSlug(name: string, id?: string): string {
|
||||||
|
return name
|
||||||
|
.concat(id ? ` ${id}` : '')
|
||||||
|
.toLowerCase()
|
||||||
|
.normalize('NFD')
|
||||||
|
.replace(/[\u0300-\u036f]/g, '') // Enlève les accents
|
||||||
|
.trim()
|
||||||
|
.replace(/[^a-z0-9 -]/g, '') // Enlève les caractères spéciaux
|
||||||
|
.replace(/\s+/g, '-') // Remplace les espaces par des tirets
|
||||||
|
.replace(/-+/g, '-'); // Évite les tirets multiples
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Profile } from '@app/domain/profiles/profile.model';
|
|||||||
export class GetProfileUseCase {
|
export class GetProfileUseCase {
|
||||||
constructor(private readonly repo: ProfileRepository) {}
|
constructor(private readonly repo: ProfileRepository) {}
|
||||||
|
|
||||||
execute(userId: string): Observable<Profile> {
|
execute(profileId: string): Observable<Profile> {
|
||||||
return this.repo.getByUserId(userId);
|
return this.repo.getById(profileId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { UserRepository } from '@app/domain/users/user.repository';
|
import { UserRepository } from '@app/domain/users/user.repository';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { User } from '@app/domain/users/user.model';
|
||||||
|
|
||||||
export class GetUserUseCase {
|
export class GetUserUseCase {
|
||||||
constructor(private readonly repo: UserRepository) {}
|
constructor(private readonly repo: UserRepository) {}
|
||||||
execute(userId: string) {
|
execute(userId: string): Observable<User> {
|
||||||
return this.repo.getUserById(userId);
|
return this.repo.getUserById(userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
{
|
{
|
||||||
"compileOnSave": false,
|
"compileOnSave": false,
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"skipLibCheck": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
|
|||||||
Reference in New Issue
Block a user