@blackcode_sa/metaestetics-api 1.14.78 → 1.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/index.d.mts +5 -0
- package/dist/admin/index.d.ts +5 -0
- package/dist/admin/index.js +47 -5
- package/dist/admin/index.mjs +47 -5
- package/dist/index.d.mts +302 -1
- package/dist/index.d.ts +302 -1
- package/dist/index.js +2655 -1754
- package/dist/index.mjs +1880 -983
- package/package.json +1 -1
- package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +59 -6
- package/src/services/__tests__/auth/auth.mock.test.ts +2 -2
- package/src/services/__tests__/auth/auth.setup.ts +6 -1
- package/src/services/__tests__/auth.service.test.ts +8 -44
- package/src/services/__tests__/base.service.test.ts +4 -45
- package/src/services/__tests__/user.service.test.ts +6 -4
- package/src/services/appointment/utils/appointment.utils.ts +0 -3
- package/src/services/appointment/utils/extended-procedure.utils.ts +1 -0
- package/src/services/auth/auth.v2.service.ts +7 -7
- package/src/services/clinic/__tests__/clinic-admin.service.test.ts +11 -33
- package/src/services/clinic/__tests__/clinic-group.service.test.ts +21 -151
- package/src/services/clinic/__tests__/clinic.service.test.ts +17 -69
- package/src/services/clinic/utils/clinic-group.utils.ts +2 -2
- package/src/services/clinic/utils/clinic.utils.ts +28 -22
- package/src/services/clinic/utils/index.ts +0 -1
- package/src/services/notifications/__tests__/notification.service.test.ts +5 -5
- package/src/services/patient/__tests__/patient.service.test.ts +17 -25
- package/src/services/patient/patient.service.ts +136 -0
- package/src/services/patient/utils/body-assessment.utils.ts +159 -0
- package/src/services/patient/utils/docs.utils.ts +1 -1
- package/src/services/patient/utils/hair-scalp-assessment.utils.ts +158 -0
- package/src/services/patient/utils/pre-surgical-assessment.utils.ts +161 -0
- package/src/services/patient/utils/skin-quality-assessment.utils.ts +160 -0
- package/src/services/user/user.v2.service.ts +4 -3
- package/src/types/patient/body-assessment.types.ts +93 -0
- package/src/types/patient/hair-scalp-assessment.types.ts +98 -0
- package/src/types/patient/index.ts +4 -0
- package/src/types/patient/pre-surgical-assessment.types.ts +95 -0
- package/src/types/patient/skin-quality-assessment.types.ts +105 -0
- package/src/validations/patient/body-assessment.schema.ts +82 -0
- package/src/validations/patient/hair-scalp-assessment.schema.ts +70 -0
- package/src/validations/patient/pre-surgical-assessment.schema.ts +78 -0
- package/src/validations/patient/skin-quality-assessment.schema.ts +70 -0
package/package.json
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from '../../../types/patient/patient-requirements';
|
|
14
14
|
import {
|
|
15
15
|
Requirement as RequirementTemplate,
|
|
16
|
-
|
|
16
|
+
REQUIREMENTS_COLLECTION,
|
|
17
17
|
RequirementType,
|
|
18
18
|
TimeUnit, // Added import
|
|
19
19
|
} from '../../../backoffice/types/requirement.types';
|
|
@@ -671,12 +671,17 @@ export class AppointmentAggregationService {
|
|
|
671
671
|
// Store created instances for fallback direct creation if needed
|
|
672
672
|
let createdInstances = [];
|
|
673
673
|
|
|
674
|
+
// Resolve string IDs to full RequirementTemplate objects
|
|
675
|
+
const resolvedPreRequirements = await this.resolveRequirements(
|
|
676
|
+
appointment.preProcedureRequirements as any,
|
|
677
|
+
);
|
|
678
|
+
|
|
674
679
|
// Log more details about the pre-requirements
|
|
675
680
|
Logger.info(
|
|
676
681
|
`[AggService] Found ${
|
|
677
|
-
|
|
682
|
+
resolvedPreRequirements.length
|
|
678
683
|
} pre-requirements to process: ${JSON.stringify(
|
|
679
|
-
|
|
684
|
+
resolvedPreRequirements.map(r => ({
|
|
680
685
|
id: r.id,
|
|
681
686
|
name: r.name,
|
|
682
687
|
type: r.type,
|
|
@@ -687,7 +692,7 @@ export class AppointmentAggregationService {
|
|
|
687
692
|
)}`,
|
|
688
693
|
);
|
|
689
694
|
|
|
690
|
-
for (const template of
|
|
695
|
+
for (const template of resolvedPreRequirements) {
|
|
691
696
|
if (!template) {
|
|
692
697
|
Logger.warn(
|
|
693
698
|
`[AggService] Found null/undefined template in preProcedureRequirements array`,
|
|
@@ -933,6 +938,51 @@ export class AppointmentAggregationService {
|
|
|
933
938
|
}
|
|
934
939
|
}
|
|
935
940
|
|
|
941
|
+
/**
|
|
942
|
+
* Resolves an array of requirement items that may be string IDs or full Requirement objects.
|
|
943
|
+
* String IDs are batch-fetched from the backoffice_requirements collection.
|
|
944
|
+
*/
|
|
945
|
+
private async resolveRequirements(
|
|
946
|
+
items: (string | RequirementTemplate)[],
|
|
947
|
+
): Promise<RequirementTemplate[]> {
|
|
948
|
+
if (items.length === 0) return [];
|
|
949
|
+
|
|
950
|
+
const resolved: RequirementTemplate[] = [];
|
|
951
|
+
const idsToFetch: string[] = [];
|
|
952
|
+
|
|
953
|
+
for (const item of items) {
|
|
954
|
+
if (typeof item === 'string') {
|
|
955
|
+
idsToFetch.push(item);
|
|
956
|
+
} else if (item && typeof item === 'object' && item.id) {
|
|
957
|
+
resolved.push(item);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
if (idsToFetch.length > 0) {
|
|
962
|
+
Logger.info(
|
|
963
|
+
`[AggService] Resolving ${idsToFetch.length} requirement ID(s) from ${REQUIREMENTS_COLLECTION}`,
|
|
964
|
+
);
|
|
965
|
+
|
|
966
|
+
// Firestore getAll supports up to 500 docs per call
|
|
967
|
+
const refs = idsToFetch.map(id =>
|
|
968
|
+
this.db.collection(REQUIREMENTS_COLLECTION).doc(id),
|
|
969
|
+
);
|
|
970
|
+
const snapshots = await this.db.getAll(...refs);
|
|
971
|
+
|
|
972
|
+
for (const snap of snapshots) {
|
|
973
|
+
if (snap.exists) {
|
|
974
|
+
resolved.push({ id: snap.id, ...snap.data() } as RequirementTemplate);
|
|
975
|
+
} else {
|
|
976
|
+
Logger.warn(
|
|
977
|
+
`[AggService] Requirement template '${snap.id}' not found in ${REQUIREMENTS_COLLECTION}`,
|
|
978
|
+
);
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
return resolved;
|
|
984
|
+
}
|
|
985
|
+
|
|
936
986
|
/**
|
|
937
987
|
* Fetches post-requirements from a procedure document
|
|
938
988
|
* @param procedureId - The procedure ID to fetch requirements from
|
|
@@ -949,12 +999,15 @@ export class AppointmentAggregationService {
|
|
|
949
999
|
}
|
|
950
1000
|
|
|
951
1001
|
const procedure = procedureDoc.data() as Procedure;
|
|
952
|
-
const
|
|
1002
|
+
const rawPostRequirements = procedure.postRequirements || [];
|
|
953
1003
|
|
|
954
|
-
if (
|
|
1004
|
+
if (rawPostRequirements.length === 0) {
|
|
955
1005
|
return [];
|
|
956
1006
|
}
|
|
957
1007
|
|
|
1008
|
+
// Resolve string IDs to full Requirement objects if needed
|
|
1009
|
+
const postRequirements = await this.resolveRequirements(rawPostRequirements as any);
|
|
1010
|
+
|
|
958
1011
|
return postRequirements.map(req => ({
|
|
959
1012
|
requirement: req,
|
|
960
1013
|
sourceProcedures: [
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { setupService, mockFirebaseUser } from "./auth.setup";
|
|
2
2
|
|
|
3
3
|
describe("Firebase Mock Setup", () => {
|
|
4
4
|
beforeEach(() => {
|
|
5
|
-
|
|
5
|
+
setupService();
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
it("should properly initialize mock Firebase instance", async () => {
|
|
@@ -288,6 +288,11 @@ export const getMockUser = () => ({
|
|
|
288
288
|
|
|
289
289
|
// Setup service
|
|
290
290
|
export const setupService = () => {
|
|
291
|
-
const service = new AuthService(
|
|
291
|
+
const service = new AuthService(
|
|
292
|
+
mockDb as unknown as Firestore,
|
|
293
|
+
mockAuth as unknown as Auth,
|
|
294
|
+
{} as FirebaseApp,
|
|
295
|
+
mockUserService
|
|
296
|
+
);
|
|
292
297
|
return service;
|
|
293
298
|
};
|
|
@@ -121,6 +121,10 @@ jest.mock("../../config/firebase", () => ({
|
|
|
121
121
|
|
|
122
122
|
import { AuthService } from "../auth/auth.service";
|
|
123
123
|
import { User as FirebaseUser } from "firebase/auth";
|
|
124
|
+
import { Firestore } from "firebase/firestore";
|
|
125
|
+
import { Auth } from "firebase/auth";
|
|
126
|
+
import { FirebaseApp } from "firebase/app";
|
|
127
|
+
import { UserService } from "../user/user.service";
|
|
124
128
|
import { UserRole } from "../../types";
|
|
125
129
|
|
|
126
130
|
const mockFacebookUser = {
|
|
@@ -150,8 +154,10 @@ describe("AuthService", () => {
|
|
|
150
154
|
let service: AuthService;
|
|
151
155
|
|
|
152
156
|
beforeEach(async () => {
|
|
153
|
-
|
|
154
|
-
|
|
157
|
+
const mockDb = {} as Firestore;
|
|
158
|
+
const mockApp = {} as FirebaseApp;
|
|
159
|
+
const mockUserService = {} as UserService;
|
|
160
|
+
service = new AuthService(mockDb, mockAuth as unknown as Auth, mockApp, mockUserService);
|
|
155
161
|
});
|
|
156
162
|
|
|
157
163
|
afterEach(() => {
|
|
@@ -243,48 +249,6 @@ describe("AuthService", () => {
|
|
|
243
249
|
});
|
|
244
250
|
});
|
|
245
251
|
|
|
246
|
-
describe("signInWithFacebook", () => {
|
|
247
|
-
it("should sign in user with Facebook", async () => {
|
|
248
|
-
const expectedUser = {
|
|
249
|
-
uid: "facebook-uid",
|
|
250
|
-
email: "facebook@example.com",
|
|
251
|
-
roles: [UserRole.PATIENT],
|
|
252
|
-
isAnonymous: false,
|
|
253
|
-
createdAt: expect.any(Date),
|
|
254
|
-
updatedAt: expect.any(Date),
|
|
255
|
-
lastLoginAt: expect.any(Date),
|
|
256
|
-
patientProfile: null,
|
|
257
|
-
practitionerProfile: null,
|
|
258
|
-
adminProfile: null,
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
const result = await service.signInWithFacebook();
|
|
262
|
-
|
|
263
|
-
expect(result).toEqual(expectedUser);
|
|
264
|
-
});
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
describe("signInWithApple", () => {
|
|
268
|
-
it("should sign in user with Apple", async () => {
|
|
269
|
-
const expectedUser = {
|
|
270
|
-
uid: "apple-uid",
|
|
271
|
-
email: "apple@example.com",
|
|
272
|
-
roles: [UserRole.PATIENT],
|
|
273
|
-
isAnonymous: false,
|
|
274
|
-
createdAt: expect.any(Date),
|
|
275
|
-
updatedAt: expect.any(Date),
|
|
276
|
-
lastLoginAt: expect.any(Date),
|
|
277
|
-
patientProfile: null,
|
|
278
|
-
practitionerProfile: null,
|
|
279
|
-
adminProfile: null,
|
|
280
|
-
};
|
|
281
|
-
|
|
282
|
-
const result = await service.signInWithApple();
|
|
283
|
-
|
|
284
|
-
expect(result).toEqual(expectedUser);
|
|
285
|
-
});
|
|
286
|
-
});
|
|
287
|
-
|
|
288
252
|
describe("signInAnonymously", () => {
|
|
289
253
|
it("should sign in user anonymously", async () => {
|
|
290
254
|
const expectedUser = {
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { BaseService } from "../base.service";
|
|
2
|
-
import { getFirebaseInstance } from "../../config/firebase";
|
|
3
2
|
import { Auth } from "firebase/auth";
|
|
4
3
|
import { Firestore } from "firebase/firestore";
|
|
5
|
-
|
|
6
|
-
// Mock Firebase config
|
|
7
|
-
jest.mock("../../config/firebase");
|
|
4
|
+
import { FirebaseApp } from "firebase/app";
|
|
8
5
|
|
|
9
6
|
// Test implementacija BaseService klase
|
|
10
7
|
class TestService extends BaseService {
|
|
@@ -16,62 +13,24 @@ class TestService extends BaseService {
|
|
|
16
13
|
public getAuth(): Auth {
|
|
17
14
|
return this.auth;
|
|
18
15
|
}
|
|
19
|
-
|
|
20
|
-
// Expose initialize method for testing
|
|
21
|
-
public async testEnsureInitialized() {
|
|
22
|
-
await this.ensureInitialized();
|
|
23
|
-
}
|
|
24
16
|
}
|
|
25
17
|
|
|
26
18
|
describe("BaseService", () => {
|
|
27
19
|
let service: TestService;
|
|
28
20
|
const mockDb = {} as Firestore;
|
|
29
21
|
const mockAuth = {} as Auth;
|
|
22
|
+
const mockApp = {} as FirebaseApp;
|
|
30
23
|
|
|
31
24
|
beforeEach(() => {
|
|
32
25
|
jest.clearAllMocks();
|
|
33
|
-
(getFirebaseInstance as jest.Mock).mockResolvedValue({
|
|
34
|
-
db: mockDb,
|
|
35
|
-
auth: mockAuth,
|
|
36
|
-
});
|
|
37
26
|
});
|
|
38
27
|
|
|
39
28
|
describe("initialization", () => {
|
|
40
|
-
it("treba da inicijalizuje Firebase servise",
|
|
41
|
-
service = new TestService();
|
|
42
|
-
await service.testEnsureInitialized();
|
|
29
|
+
it("treba da inicijalizuje Firebase servise", () => {
|
|
30
|
+
service = new TestService(mockDb, mockAuth, mockApp);
|
|
43
31
|
|
|
44
|
-
expect(getFirebaseInstance).toHaveBeenCalled();
|
|
45
32
|
expect(service.getDb()).toBe(mockDb);
|
|
46
33
|
expect(service.getAuth()).toBe(mockAuth);
|
|
47
34
|
});
|
|
48
|
-
|
|
49
|
-
it("treba da hendla grešku pri inicijalizaciji", async () => {
|
|
50
|
-
const mockError = new Error("Firebase init error");
|
|
51
|
-
(getFirebaseInstance as jest.Mock).mockRejectedValue(mockError);
|
|
52
|
-
|
|
53
|
-
service = new TestService();
|
|
54
|
-
|
|
55
|
-
await expect(service.testEnsureInitialized()).rejects.toThrow(mockError);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it("treba da zadrži grešku inicijalizacije i baca je pri svakom pozivu", async () => {
|
|
59
|
-
const mockError = new Error("Firebase init error");
|
|
60
|
-
(getFirebaseInstance as jest.Mock).mockRejectedValue(mockError);
|
|
61
|
-
|
|
62
|
-
service = new TestService();
|
|
63
|
-
|
|
64
|
-
// Prvi pokušaj
|
|
65
|
-
await expect(service.testEnsureInitialized()).rejects.toThrow(mockError);
|
|
66
|
-
|
|
67
|
-
// Firebase je sada uspešno inicijalizovan
|
|
68
|
-
(getFirebaseInstance as jest.Mock).mockResolvedValue({
|
|
69
|
-
db: mockDb,
|
|
70
|
-
auth: mockAuth,
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
// Ali i dalje treba da dobijemo originalnu grešku
|
|
74
|
-
await expect(service.testEnsureInitialized()).rejects.toThrow(mockError);
|
|
75
|
-
});
|
|
76
35
|
});
|
|
77
36
|
});
|
|
@@ -131,9 +131,11 @@ describe("UserService", () => {
|
|
|
131
131
|
});
|
|
132
132
|
|
|
133
133
|
userService = new UserService(
|
|
134
|
+
mockDb,
|
|
134
135
|
mockAuth,
|
|
135
|
-
|
|
136
|
-
new
|
|
136
|
+
{} as any,
|
|
137
|
+
new PatientService(mockDb, mockAuth, {} as any),
|
|
138
|
+
new ClinicAdminService(mockDb, mockAuth, {} as any)
|
|
137
139
|
);
|
|
138
140
|
});
|
|
139
141
|
|
|
@@ -460,7 +462,7 @@ describe("UserService", () => {
|
|
|
460
462
|
});
|
|
461
463
|
});
|
|
462
464
|
|
|
463
|
-
describe("
|
|
465
|
+
describe("removeRoleAndProfile", () => {
|
|
464
466
|
it("treba da ukloni ulogu korisniku", async () => {
|
|
465
467
|
const userWithMultipleRoles = {
|
|
466
468
|
...mockUser,
|
|
@@ -487,7 +489,7 @@ describe("UserService", () => {
|
|
|
487
489
|
data: () => updatedUser,
|
|
488
490
|
});
|
|
489
491
|
|
|
490
|
-
await userService.
|
|
492
|
+
await userService.removeRoleAndProfile("test-uid", UserRole.PATIENT);
|
|
491
493
|
|
|
492
494
|
// Provera da li je pozvan updateDoc sa ispravnim parametrima
|
|
493
495
|
expect(updateDoc).toHaveBeenCalledWith(
|
|
@@ -33,9 +33,6 @@ import { PATIENTS_COLLECTION } from '../../../types/patient';
|
|
|
33
33
|
import { CLINICS_COLLECTION } from '../../../types/clinic';
|
|
34
34
|
import { BlockingCondition } from '../../../backoffice/types/static/blocking-condition.types';
|
|
35
35
|
import { Requirement } from '../../../backoffice/types/requirement.types';
|
|
36
|
-
import { PRACTITIONERS_COLLECTION } from '../../../types/practitioner';
|
|
37
|
-
import { CLINICS_COLLECTION } from '../../../types/clinic';
|
|
38
|
-
import { PATIENTS_COLLECTION } from '../../../types/patient';
|
|
39
36
|
import { PROCEDURES_COLLECTION } from '../../../types/procedure';
|
|
40
37
|
import { Technology, TECHNOLOGIES_COLLECTION } from '../../../backoffice/types/technology.types';
|
|
41
38
|
import type { ContraindicationDynamic } from '../../../backoffice';
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ExtendedProcedureInfo,
|
|
5
5
|
AppointmentProductMetadata,
|
|
6
6
|
APPOINTMENTS_COLLECTION,
|
|
7
|
+
LinkedFormInfo,
|
|
7
8
|
} from '../../../types/appointment';
|
|
8
9
|
import { getAppointmentOrThrow, initializeMetadata } from './zone-management.utils';
|
|
9
10
|
import { PROCEDURES_COLLECTION } from '../../../types/procedure';
|
|
@@ -424,7 +424,7 @@ export class AuthServiceV2 extends BaseService {
|
|
|
424
424
|
>(functions, "createAnonymousPatientProfile");
|
|
425
425
|
|
|
426
426
|
const result = await createAnonymousPatientProfile({});
|
|
427
|
-
return result.data.user;
|
|
427
|
+
return (result.data as any).user;
|
|
428
428
|
}
|
|
429
429
|
}
|
|
430
430
|
|
|
@@ -450,7 +450,7 @@ export class AuthServiceV2 extends BaseService {
|
|
|
450
450
|
);
|
|
451
451
|
|
|
452
452
|
const result = await createAnonymousPatientProfile({});
|
|
453
|
-
return result.data.user;
|
|
453
|
+
return (result.data as any).user;
|
|
454
454
|
}
|
|
455
455
|
}
|
|
456
456
|
|
|
@@ -468,7 +468,7 @@ export class AuthServiceV2 extends BaseService {
|
|
|
468
468
|
);
|
|
469
469
|
|
|
470
470
|
const result = await createAnonymousPatientProfile({});
|
|
471
|
-
return result.data.user;
|
|
471
|
+
return (result.data as any).user;
|
|
472
472
|
}
|
|
473
473
|
|
|
474
474
|
/**
|
|
@@ -545,7 +545,7 @@ export class AuthServiceV2 extends BaseService {
|
|
|
545
545
|
},
|
|
546
546
|
});
|
|
547
547
|
|
|
548
|
-
return result.data.user;
|
|
548
|
+
return (result.data as any).user;
|
|
549
549
|
} catch (error) {
|
|
550
550
|
if (error instanceof z.ZodError) {
|
|
551
551
|
throw AUTH_ERRORS.VALIDATION_ERROR;
|
|
@@ -598,7 +598,7 @@ export class AuthServiceV2 extends BaseService {
|
|
|
598
598
|
},
|
|
599
599
|
});
|
|
600
600
|
|
|
601
|
-
return result.data.user;
|
|
601
|
+
return (result.data as any).user;
|
|
602
602
|
} catch (error: unknown) {
|
|
603
603
|
const firebaseError = error as FirebaseError;
|
|
604
604
|
if (firebaseError.code === FirebaseErrorCode.POPUP_CLOSED_BY_USER) {
|
|
@@ -645,7 +645,7 @@ export class AuthServiceV2 extends BaseService {
|
|
|
645
645
|
},
|
|
646
646
|
});
|
|
647
647
|
|
|
648
|
-
return result.data.user;
|
|
648
|
+
return (result.data as any).user;
|
|
649
649
|
} catch (error: unknown) {
|
|
650
650
|
const firebaseError = error as FirebaseError;
|
|
651
651
|
if (firebaseError.code === FirebaseErrorCode.POPUP_CLOSED_BY_USER) {
|
|
@@ -693,7 +693,7 @@ export class AuthServiceV2 extends BaseService {
|
|
|
693
693
|
},
|
|
694
694
|
});
|
|
695
695
|
|
|
696
|
-
return result.data.user;
|
|
696
|
+
return (result.data as any).user;
|
|
697
697
|
} catch (error: unknown) {
|
|
698
698
|
const firebaseError = error as FirebaseError;
|
|
699
699
|
if (firebaseError.code === FirebaseErrorCode.POPUP_CLOSED_BY_USER) {
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
import {
|
|
15
15
|
CreateClinicAdminData,
|
|
16
16
|
ClinicAdmin,
|
|
17
|
-
} from "../../../types/clinic
|
|
17
|
+
} from "../../../types/clinic";
|
|
18
18
|
import { CLINIC_ADMIN_ERRORS } from "../../../errors/clinic.errors";
|
|
19
19
|
|
|
20
20
|
// Mock Firebase
|
|
@@ -30,6 +30,7 @@ describe("ClinicAdminService", () => {
|
|
|
30
30
|
clinicGroupId: "test-group-id",
|
|
31
31
|
isGroupOwner: false,
|
|
32
32
|
clinicsManaged: ["clinic-1", "clinic-2"],
|
|
33
|
+
clinicsManagedInfo: [],
|
|
33
34
|
contactInfo: {
|
|
34
35
|
firstName: "John",
|
|
35
36
|
lastName: "Doe",
|
|
@@ -39,8 +40,8 @@ describe("ClinicAdminService", () => {
|
|
|
39
40
|
},
|
|
40
41
|
roleTitle: "Clinic Administrator",
|
|
41
42
|
isActive: true,
|
|
42
|
-
createdAt: mockTimestamp.now()
|
|
43
|
-
updatedAt: mockTimestamp.now()
|
|
43
|
+
createdAt: mockTimestamp.now(),
|
|
44
|
+
updatedAt: mockTimestamp.now(),
|
|
44
45
|
};
|
|
45
46
|
|
|
46
47
|
beforeEach(() => {
|
|
@@ -53,7 +54,11 @@ describe("ClinicAdminService", () => {
|
|
|
53
54
|
analytics: null,
|
|
54
55
|
});
|
|
55
56
|
|
|
56
|
-
clinicAdminService = new ClinicAdminService(
|
|
57
|
+
clinicAdminService = new ClinicAdminService(
|
|
58
|
+
{} as any,
|
|
59
|
+
{} as any,
|
|
60
|
+
{} as any
|
|
61
|
+
);
|
|
57
62
|
|
|
58
63
|
// Mock Firestore functions
|
|
59
64
|
(doc as jest.Mock).mockReturnValue("doc-ref");
|
|
@@ -218,41 +223,15 @@ describe("ClinicAdminService", () => {
|
|
|
218
223
|
});
|
|
219
224
|
});
|
|
220
225
|
|
|
221
|
-
describe("setActive", () => {
|
|
222
|
-
it("treba da aktivira/deaktivira clinic admina", async () => {
|
|
223
|
-
await clinicAdminService.setActive(mockClinicAdmin.id, false);
|
|
224
|
-
|
|
225
|
-
expect(updateDoc).toHaveBeenCalled();
|
|
226
|
-
expect(updateDoc).toHaveBeenCalledWith(
|
|
227
|
-
"doc-ref",
|
|
228
|
-
expect.objectContaining({
|
|
229
|
-
isActive: false,
|
|
230
|
-
updatedAt: expect.any(Date),
|
|
231
|
-
})
|
|
232
|
-
);
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
it("treba da baci grešku ako admin ne postoji", async () => {
|
|
236
|
-
(getDoc as jest.Mock).mockResolvedValueOnce({
|
|
237
|
-
exists: () => false,
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
await expect(
|
|
241
|
-
clinicAdminService.setActive("non-existent", false)
|
|
242
|
-
).rejects.toThrow(CLINIC_ADMIN_ERRORS.NOT_FOUND);
|
|
243
|
-
});
|
|
244
|
-
});
|
|
245
|
-
|
|
246
226
|
describe("addClinicToManaged", () => {
|
|
247
227
|
it("treba da doda kliniku admin-u", async () => {
|
|
248
228
|
const clinicId = "new-clinic-id";
|
|
249
|
-
|
|
229
|
+
await clinicAdminService.addClinicToManaged(
|
|
250
230
|
mockClinicAdmin.id,
|
|
251
231
|
clinicId
|
|
252
232
|
);
|
|
253
233
|
|
|
254
234
|
expect(updateDoc).toHaveBeenCalled();
|
|
255
|
-
expect(result.clinicsManaged).toContain(clinicId);
|
|
256
235
|
});
|
|
257
236
|
|
|
258
237
|
it("treba da baci grešku ako klinika već postoji", async () => {
|
|
@@ -267,13 +246,12 @@ describe("ClinicAdminService", () => {
|
|
|
267
246
|
describe("removeClinicFromManaged", () => {
|
|
268
247
|
it("treba da ukloni kliniku iz admin-a", async () => {
|
|
269
248
|
const clinicId = mockClinicAdmin.clinicsManaged[0];
|
|
270
|
-
|
|
249
|
+
await clinicAdminService.removeClinicFromManaged(
|
|
271
250
|
mockClinicAdmin.id,
|
|
272
251
|
clinicId
|
|
273
252
|
);
|
|
274
253
|
|
|
275
254
|
expect(updateDoc).toHaveBeenCalled();
|
|
276
|
-
expect(result.clinicsManaged).not.toContain(clinicId);
|
|
277
255
|
});
|
|
278
256
|
|
|
279
257
|
it("treba da baci grešku ako klinika ne postoji", async () => {
|