@trailmix-cms/cms 0.4.4 → 0.7.1
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/auth.guard.d.ts +5 -13
- package/dist/auth.guard.d.ts.map +1 -1
- package/dist/auth.guard.js +23 -91
- package/dist/auth.guard.js.map +1 -1
- package/dist/collections/account.collection.d.ts +5 -3
- package/dist/collections/account.collection.d.ts.map +1 -1
- package/dist/collections/account.collection.js +15 -8
- package/dist/collections/account.collection.js.map +1 -1
- package/dist/collections/api-key.collection.d.ts +54 -0
- package/dist/collections/api-key.collection.d.ts.map +1 -0
- package/dist/collections/api-key.collection.js +142 -0
- package/dist/collections/api-key.collection.js.map +1 -0
- package/dist/collections/index.d.ts +4 -2
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/collections/index.js +9 -5
- package/dist/collections/index.js.map +1 -1
- package/dist/collections/organization.collection.d.ts +20 -0
- package/dist/collections/organization.collection.d.ts.map +1 -0
- package/dist/collections/{file.collection.js → organization.collection.js} +17 -17
- package/dist/collections/organization.collection.js.map +1 -0
- package/dist/collections/role.collection.d.ts +32 -0
- package/dist/collections/role.collection.d.ts.map +1 -0
- package/dist/collections/role.collection.js +90 -0
- package/dist/collections/role.collection.js.map +1 -0
- package/dist/collections/security-audit.collection.d.ts +30 -0
- package/dist/collections/security-audit.collection.d.ts.map +1 -0
- package/dist/collections/security-audit.collection.js +79 -0
- package/dist/collections/security-audit.collection.js.map +1 -0
- package/dist/constants/cms-collection-names.d.ts +4 -2
- package/dist/constants/cms-collection-names.d.ts.map +1 -1
- package/dist/constants/cms-collection-names.js +4 -2
- package/dist/constants/cms-collection-names.js.map +1 -1
- package/dist/constants/provider-symbols.d.ts +10 -12
- package/dist/constants/provider-symbols.d.ts.map +1 -1
- package/dist/constants/provider-symbols.js +10 -12
- package/dist/constants/provider-symbols.js.map +1 -1
- package/dist/controllers/account.controller.d.ts +11 -15
- package/dist/controllers/account.controller.d.ts.map +1 -1
- package/dist/controllers/account.controller.js +69 -13
- package/dist/controllers/account.controller.js.map +1 -1
- package/dist/controllers/api-keys.controller.d.ts +13 -0
- package/dist/controllers/api-keys.controller.d.ts.map +1 -0
- package/dist/controllers/api-keys.controller.js +125 -0
- package/dist/controllers/api-keys.controller.js.map +1 -0
- package/dist/controllers/audit.controller.d.ts.map +1 -1
- package/dist/controllers/audit.controller.js +3 -3
- package/dist/controllers/audit.controller.js.map +1 -1
- package/dist/controllers/audits.controller.d.ts +10 -0
- package/dist/controllers/audits.controller.d.ts.map +1 -0
- package/dist/controllers/audits.controller.js +107 -0
- package/dist/controllers/audits.controller.js.map +1 -0
- package/dist/controllers/global-roles.controller.d.ts +16 -0
- package/dist/controllers/global-roles.controller.d.ts.map +1 -0
- package/dist/controllers/global-roles.controller.js +137 -0
- package/dist/controllers/global-roles.controller.js.map +1 -0
- package/dist/controllers/index.d.ts +6 -1
- package/dist/controllers/index.d.ts.map +1 -1
- package/dist/controllers/index.js +6 -1
- package/dist/controllers/index.js.map +1 -1
- package/dist/controllers/organization-roles.controller.d.ts +16 -0
- package/dist/controllers/organization-roles.controller.d.ts.map +1 -0
- package/dist/controllers/organization-roles.controller.js +145 -0
- package/dist/controllers/organization-roles.controller.js.map +1 -0
- package/dist/controllers/organizations.controller.d.ts +65 -0
- package/dist/controllers/organizations.controller.d.ts.map +1 -0
- package/dist/controllers/organizations.controller.js +140 -0
- package/dist/controllers/organizations.controller.js.map +1 -0
- package/dist/controllers/security-audits.controller.d.ts +11 -0
- package/dist/controllers/security-audits.controller.d.ts.map +1 -0
- package/dist/controllers/security-audits.controller.js +130 -0
- package/dist/controllers/security-audits.controller.js.map +1 -0
- package/dist/decorators/account.decorator.d.ts +1 -3
- package/dist/decorators/account.decorator.d.ts.map +1 -1
- package/dist/decorators/account.decorator.js +3 -10
- package/dist/decorators/account.decorator.js.map +1 -1
- package/dist/decorators/audit-context.decorator.d.ts +6 -0
- package/dist/decorators/audit-context.decorator.d.ts.map +1 -1
- package/dist/decorators/audit-context.decorator.js +12 -3
- package/dist/decorators/audit-context.decorator.js.map +1 -1
- package/dist/decorators/auth.decorator.d.ts +5 -3
- package/dist/decorators/auth.decorator.d.ts.map +1 -1
- package/dist/decorators/auth.decorator.js +38 -3
- package/dist/decorators/auth.decorator.js.map +1 -1
- package/dist/decorators/index.d.ts +4 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +20 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/dto/account.dto.d.ts +33 -0
- package/dist/dto/account.dto.d.ts.map +1 -0
- package/dist/dto/account.dto.js +14 -0
- package/dist/dto/account.dto.js.map +1 -0
- package/dist/dto/api-key.dto.d.ts +89 -0
- package/dist/dto/api-key.dto.d.ts.map +1 -0
- package/dist/dto/api-key.dto.js +27 -0
- package/dist/dto/api-key.dto.js.map +1 -0
- package/dist/dto/audit.dto.d.ts +11 -5
- package/dist/dto/audit.dto.d.ts.map +1 -1
- package/dist/dto/audit.dto.js +1 -1
- package/dist/dto/audit.dto.js.map +1 -1
- package/dist/dto/global-role.dto.d.ts +99 -0
- package/dist/dto/global-role.dto.d.ts.map +1 -0
- package/dist/dto/global-role.dto.js +26 -0
- package/dist/dto/global-role.dto.js.map +1 -0
- package/dist/dto/organization-role.dto.d.ts +107 -0
- package/dist/dto/organization-role.dto.d.ts.map +1 -0
- package/dist/dto/organization-role.dto.js +26 -0
- package/dist/dto/organization-role.dto.js.map +1 -0
- package/dist/dto/organization.dto.d.ts +57 -0
- package/dist/dto/organization.dto.d.ts.map +1 -0
- package/dist/dto/organization.dto.js +32 -0
- package/dist/dto/organization.dto.js.map +1 -0
- package/dist/dto/security-audit.dto.d.ts +95 -0
- package/dist/dto/security-audit.dto.d.ts.map +1 -0
- package/dist/dto/security-audit.dto.js +26 -0
- package/dist/dto/security-audit.dto.js.map +1 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/managers/global-role.manager.d.ts +42 -0
- package/dist/managers/global-role.manager.d.ts.map +1 -0
- package/dist/managers/global-role.manager.js +117 -0
- package/dist/managers/global-role.manager.js.map +1 -0
- package/dist/managers/index.d.ts +4 -0
- package/dist/managers/index.d.ts.map +1 -0
- package/dist/managers/index.js +20 -0
- package/dist/managers/index.js.map +1 -0
- package/dist/managers/organization-role.manager.d.ts +47 -0
- package/dist/managers/organization-role.manager.d.ts.map +1 -0
- package/dist/managers/organization-role.manager.js +218 -0
- package/dist/managers/organization-role.manager.js.map +1 -0
- package/dist/managers/organization.manager.d.ts +39 -0
- package/dist/managers/organization.manager.d.ts.map +1 -0
- package/dist/managers/organization.manager.js +196 -0
- package/dist/managers/organization.manager.js.map +1 -0
- package/dist/module.d.ts +92 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +137 -0
- package/dist/module.js.map +1 -0
- package/dist/pipes/api-key.pipe.d.ts +8 -0
- package/dist/pipes/api-key.pipe.d.ts.map +1 -0
- package/dist/pipes/api-key.pipe.js +28 -0
- package/dist/pipes/api-key.pipe.js.map +1 -0
- package/dist/pipes/organization.pipe.d.ts +8 -0
- package/dist/pipes/organization.pipe.d.ts.map +1 -0
- package/dist/pipes/organization.pipe.js +28 -0
- package/dist/pipes/organization.pipe.js.map +1 -0
- package/dist/pipes/role.pipe.d.ts +8 -0
- package/dist/pipes/{file.pipe.d.ts.map → role.pipe.d.ts.map} +1 -1
- package/dist/pipes/{file.pipe.js → role.pipe.js} +8 -8
- package/dist/pipes/{file.pipe.js.map → role.pipe.js.map} +1 -1
- package/dist/services/account.service.d.ts +0 -2
- package/dist/services/account.service.d.ts.map +1 -1
- package/dist/services/account.service.js +1 -37
- package/dist/services/account.service.js.map +1 -1
- package/dist/services/api-key.service.d.ts +42 -0
- package/dist/services/api-key.service.d.ts.map +1 -0
- package/dist/services/api-key.service.js +306 -0
- package/dist/services/api-key.service.js.map +1 -0
- package/dist/services/auth.service.d.ts +40 -0
- package/dist/services/auth.service.d.ts.map +1 -0
- package/dist/services/auth.service.js +227 -0
- package/dist/services/auth.service.js.map +1 -0
- package/dist/services/authorization.service.d.ts +44 -9
- package/dist/services/authorization.service.d.ts.map +1 -1
- package/dist/services/authorization.service.js +107 -41
- package/dist/services/authorization.service.js.map +1 -1
- package/dist/services/feature.service.d.ts +23 -0
- package/dist/services/feature.service.d.ts.map +1 -0
- package/dist/services/feature.service.js +49 -0
- package/dist/services/feature.service.js.map +1 -0
- package/dist/services/global-role.service.d.ts +17 -0
- package/dist/services/global-role.service.d.ts.map +1 -0
- package/dist/services/global-role.service.js +99 -0
- package/dist/services/global-role.service.js.map +1 -0
- package/dist/services/index.d.ts +9 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +25 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/organization-role.service.d.ts +33 -0
- package/dist/services/organization-role.service.d.ts.map +1 -0
- package/dist/services/organization-role.service.js +102 -0
- package/dist/services/organization-role.service.js.map +1 -0
- package/dist/services/organization.service.d.ts +29 -0
- package/dist/services/organization.service.d.ts.map +1 -0
- package/dist/services/organization.service.js +95 -0
- package/dist/services/organization.service.js.map +1 -0
- package/dist/types/feature-config.d.ts +9 -0
- package/dist/types/feature-config.d.ts.map +1 -0
- package/dist/types/feature-config.js +3 -0
- package/dist/types/feature-config.js.map +1 -0
- package/dist/types/hooks/auth-guard-hook.d.ts.map +1 -0
- package/dist/types/hooks/auth-guard-hook.js.map +1 -0
- package/dist/types/hooks/index.d.ts +3 -0
- package/dist/types/hooks/index.d.ts.map +1 -0
- package/dist/types/hooks/index.js +19 -0
- package/dist/types/hooks/index.js.map +1 -0
- package/dist/types/hooks/organization-delete-hook.d.ts +20 -0
- package/dist/types/hooks/organization-delete-hook.d.ts.map +1 -0
- package/dist/types/hooks/organization-delete-hook.js +3 -0
- package/dist/types/hooks/organization-delete-hook.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +21 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/request-principal.d.ts +9 -0
- package/dist/types/request-principal.d.ts.map +1 -0
- package/dist/types/request-principal.js +3 -0
- package/dist/types/request-principal.js.map +1 -0
- package/dist/utils/provider-helpers.d.ts +6 -1
- package/dist/utils/provider-helpers.d.ts.map +1 -1
- package/dist/utils/provider-helpers.js +11 -1
- package/dist/utils/provider-helpers.js.map +1 -1
- package/package.json +52 -17
- package/test/unit/collections/api-key.collection.spec.ts +416 -0
- package/test/unit/managers/global-role.manager.spec.ts +269 -0
- package/test/unit/managers/organization-role.manager.spec.ts +632 -0
- package/test/unit/managers/organization.manager.spec.ts +395 -0
- package/test/unit/module.spec.ts +596 -0
- package/test/unit/services/account.service.spec.ts +90 -0
- package/test/unit/services/api-key.service.spec.ts +1244 -0
- package/test/unit/services/auth.service.spec.ts +790 -0
- package/test/unit/services/authorization.service.spec.ts +636 -0
- package/test/unit/services/feature.service.spec.ts +56 -0
- package/test/unit/services/global-role.service.spec.ts +289 -0
- package/test/unit/services/organization-role.service.spec.ts +300 -0
- package/test/unit/services/organization.service.spec.ts +385 -0
- package/test/utils/auth-guard.ts +114 -0
- package/test/utils/base.ts +16 -0
- package/test/utils/entities/account.ts +13 -0
- package/test/utils/entities/api-key.ts +15 -0
- package/test/utils/entities/audit.ts +18 -0
- package/test/utils/entities/index.ts +6 -0
- package/test/utils/entities/mapping.ts +20 -0
- package/test/utils/entities/organization.ts +13 -0
- package/test/utils/entities/role.ts +21 -0
- package/test/utils/entities/security-audit.ts +16 -0
- package/test/utils/index.ts +4 -0
- package/test/utils/models/audit-context.ts +10 -0
- package/test/utils/models/authorization.ts +7 -0
- package/test/utils/models/global-role.ts +22 -0
- package/test/utils/models/index.ts +5 -0
- package/test/utils/models/organization-role.ts +23 -0
- package/test/utils/models/publishable.ts +7 -0
- package/tsconfig.build.json +36 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/dist/auth-guard-hook.d.ts.map +0 -1
- package/dist/auth-guard-hook.js.map +0 -1
- package/dist/cms.module.d.ts +0 -8
- package/dist/cms.module.d.ts.map +0 -1
- package/dist/cms.module.js +0 -44
- package/dist/cms.module.js.map +0 -1
- package/dist/cms.providers.d.ts +0 -120
- package/dist/cms.providers.d.ts.map +0 -1
- package/dist/cms.providers.js +0 -126
- package/dist/cms.providers.js.map +0 -1
- package/dist/collections/file.collection.d.ts +0 -21
- package/dist/collections/file.collection.d.ts.map +0 -1
- package/dist/collections/file.collection.js.map +0 -1
- package/dist/collections/text.collection.d.ts +0 -20
- package/dist/collections/text.collection.d.ts.map +0 -1
- package/dist/collections/text.collection.js +0 -56
- package/dist/collections/text.collection.js.map +0 -1
- package/dist/pipes/file.pipe.d.ts +0 -8
- /package/dist/{auth-guard-hook.d.ts → types/hooks/auth-guard-hook.d.ts} +0 -0
- /package/dist/{auth-guard-hook.js → types/hooks/auth-guard-hook.js} +0 -0
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
import { Test, TestingModule } from '@nestjs/testing';
|
|
2
|
+
import { Collection } from 'mongodb';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import * as models from '@trailmix-cms/models';
|
|
5
|
+
import { PROVIDER_SYMBOLS } from '@/constants/provider-symbols';
|
|
6
|
+
import { CMSCollectionName } from '@/constants/cms-collection-names';
|
|
7
|
+
|
|
8
|
+
// Mock the database module
|
|
9
|
+
jest.mock('@trailmix-cms/db', () => {
|
|
10
|
+
class MockBaseCollection { }
|
|
11
|
+
class MockAuditedCollection extends MockBaseCollection { }
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
createDatabaseProviders: jest.fn(() => [
|
|
15
|
+
{ provide: 'MOCK_DB_PROVIDER', useValue: 'mock' }
|
|
16
|
+
]),
|
|
17
|
+
collectionFactory: jest.fn((name: string) => ({
|
|
18
|
+
provide: `COLLECTION_${name}`,
|
|
19
|
+
useValue: name
|
|
20
|
+
})),
|
|
21
|
+
BaseCollection: MockBaseCollection,
|
|
22
|
+
AuditedCollection: MockAuditedCollection,
|
|
23
|
+
DocumentCollection: jest.fn(() => () => { }),
|
|
24
|
+
DatabaseService: class DatabaseService { },
|
|
25
|
+
Collections: {
|
|
26
|
+
AuditCollection: class AuditCollection { }
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Mock collections, services, managers, and controllers to avoid dependency issues
|
|
32
|
+
jest.mock('@/collections', () => ({
|
|
33
|
+
AccountCollection: class AccountCollection { },
|
|
34
|
+
OrganizationCollection: class OrganizationCollection { },
|
|
35
|
+
RoleCollection: class RoleCollection { },
|
|
36
|
+
SecurityAuditCollection: class SecurityAuditCollection { },
|
|
37
|
+
ApiKeyCollection: class ApiKeyCollection { },
|
|
38
|
+
}));
|
|
39
|
+
|
|
40
|
+
jest.mock('@/services', () => ({
|
|
41
|
+
FeatureService: jest.fn().mockImplementation((features) => ({
|
|
42
|
+
constructor: { name: 'FeatureService' },
|
|
43
|
+
features
|
|
44
|
+
})),
|
|
45
|
+
AccountService: class AccountService { },
|
|
46
|
+
AuthService: class AuthService { },
|
|
47
|
+
GlobalRoleService: class GlobalRoleService { },
|
|
48
|
+
OrganizationService: class OrganizationService { },
|
|
49
|
+
OrganizationRoleService: class OrganizationRoleService { },
|
|
50
|
+
AuthorizationService: class AuthorizationService { },
|
|
51
|
+
ApiKeyService: class ApiKeyService { },
|
|
52
|
+
}));
|
|
53
|
+
|
|
54
|
+
jest.mock('@/managers', () => ({
|
|
55
|
+
GlobalRoleManager: class GlobalRoleManager { },
|
|
56
|
+
OrganizationRoleManager: class OrganizationRoleManager { },
|
|
57
|
+
OrganizationManager: class OrganizationManager { },
|
|
58
|
+
}));
|
|
59
|
+
|
|
60
|
+
jest.mock('@/controllers', () => {
|
|
61
|
+
const AccountController = class AccountController { };
|
|
62
|
+
const AuditsController = class AuditsController { };
|
|
63
|
+
const GlobalRolesController = class GlobalRolesController { };
|
|
64
|
+
const SecurityAuditsController = class SecurityAuditsController { };
|
|
65
|
+
const OrganizationsController = class OrganizationsController { };
|
|
66
|
+
const OrganizationRolesController = class OrganizationRolesController { };
|
|
67
|
+
const ApiKeysController = class ApiKeysController { };
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
AccountController,
|
|
71
|
+
AuditsController,
|
|
72
|
+
GlobalRolesController,
|
|
73
|
+
SecurityAuditsController,
|
|
74
|
+
OrganizationsController,
|
|
75
|
+
OrganizationRolesController,
|
|
76
|
+
ApiKeysController,
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
import { setupTrailmixCMS, TrailmixCMSOptions } from '@/module';
|
|
81
|
+
import * as Collections from '@/collections';
|
|
82
|
+
import * as Services from '@/services';
|
|
83
|
+
import * as Managers from '@/managers';
|
|
84
|
+
import * as Controllers from '@/controllers';
|
|
85
|
+
|
|
86
|
+
describe('setupTrailmixCMS', () => {
|
|
87
|
+
beforeEach(() => {
|
|
88
|
+
jest.clearAllMocks();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('default behavior (no options)', () => {
|
|
92
|
+
let module: TestingModule;
|
|
93
|
+
let providers: any[];
|
|
94
|
+
let controllers: any[];
|
|
95
|
+
beforeEach(async () => {
|
|
96
|
+
jest.clearAllMocks();
|
|
97
|
+
const result = setupTrailmixCMS();
|
|
98
|
+
providers = result.providers;
|
|
99
|
+
controllers = result.controllers;
|
|
100
|
+
module = await Test.createTestingModule({
|
|
101
|
+
providers,
|
|
102
|
+
controllers,
|
|
103
|
+
}).compile();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should return providers and controllers with default configuration', () => {
|
|
107
|
+
expect(providers).toBeDefined();
|
|
108
|
+
expect(controllers).toBeDefined();
|
|
109
|
+
expect(Array.isArray(providers)).toBe(true);
|
|
110
|
+
expect(Array.isArray(controllers)).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('should create a valid NestJS TestingModule with default providers', () => {
|
|
114
|
+
expect(module).toBeDefined();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should include default account providers', () => {
|
|
118
|
+
const accountSchema = module.get(PROVIDER_SYMBOLS.ACCOUNT_SCHEMA);
|
|
119
|
+
const accountConfig = module.get(PROVIDER_SYMBOLS.ACCOUNT_CONFIG);
|
|
120
|
+
const accountMapEntity = module.get(PROVIDER_SYMBOLS.ACCOUNT_MAP_ENTITY);
|
|
121
|
+
|
|
122
|
+
expect(accountSchema).toBe(models.Account.schema);
|
|
123
|
+
expect(accountConfig).toBeDefined();
|
|
124
|
+
expect(accountMapEntity).toBeDefined();
|
|
125
|
+
// Account setup should not be available when not provided
|
|
126
|
+
expect(() => module.get(PROVIDER_SYMBOLS.ACCOUNT_SETUP)).toThrow();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('should not include account setup provider when not provided', () => {
|
|
130
|
+
expect(() => module.get(PROVIDER_SYMBOLS.ACCOUNT_SETUP)).toThrow();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should use default account config when not provided', () => {
|
|
134
|
+
const accountConfig = module.get(PROVIDER_SYMBOLS.ACCOUNT_CONFIG);
|
|
135
|
+
expect(accountConfig).toBeDefined();
|
|
136
|
+
expect(accountConfig).toEqual({ disableDefaultIndexes: false });
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should use default account mapEntity function that returns entity as-is', () => {
|
|
140
|
+
const accountMapEntity = module.get(PROVIDER_SYMBOLS.ACCOUNT_MAP_ENTITY);
|
|
141
|
+
expect(accountMapEntity).toBeDefined();
|
|
142
|
+
|
|
143
|
+
const testEntity = { _id: 'test-id', email: 'test@example.com' };
|
|
144
|
+
const mapperFn = accountMapEntity as (entity: any) => any;
|
|
145
|
+
expect(mapperFn(testEntity)).toBe(testEntity);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should include default services', () => {
|
|
149
|
+
const accountService = module.get(Services.AccountService);
|
|
150
|
+
const authService = module.get(Services.AuthService);
|
|
151
|
+
const globalRoleService = module.get(Services.GlobalRoleService);
|
|
152
|
+
|
|
153
|
+
expect(accountService).toBeDefined();
|
|
154
|
+
expect(authService).toBeDefined();
|
|
155
|
+
expect(globalRoleService).toBeDefined();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should include default managers', () => {
|
|
159
|
+
const globalRoleManager = module.get(Managers.GlobalRoleManager);
|
|
160
|
+
|
|
161
|
+
expect(globalRoleManager).toBeDefined();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('should include default collections', () => {
|
|
165
|
+
const accountCollection = module.get(Collections.AccountCollection);
|
|
166
|
+
const roleCollection = module.get(Collections.RoleCollection);
|
|
167
|
+
const securityAuditCollection = module.get(Collections.SecurityAuditCollection);
|
|
168
|
+
|
|
169
|
+
expect(accountCollection).toBeDefined();
|
|
170
|
+
expect(roleCollection).toBeDefined();
|
|
171
|
+
expect(securityAuditCollection).toBeDefined();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('should include default controllers', () => {
|
|
175
|
+
expect(controllers).toContain(Controllers.AccountController);
|
|
176
|
+
expect(controllers).toContain(Controllers.AuditsController);
|
|
177
|
+
expect(controllers).toContain(Controllers.GlobalRolesController);
|
|
178
|
+
expect(controllers).toContain(Controllers.SecurityAuditsController);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should not include organization-related providers when organizations are disabled', () => {
|
|
182
|
+
expect(() => module.get(PROVIDER_SYMBOLS.ORGANIZATION_SCHEMA)).toThrow();
|
|
183
|
+
expect(() => module.get(Collections.OrganizationCollection)).toThrow();
|
|
184
|
+
expect(() => module.get(Services.OrganizationService)).toThrow();
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('should not include API key-related providers when API keys are disabled', () => {
|
|
188
|
+
expect(() => module.get(Collections.ApiKeyCollection)).toThrow();
|
|
189
|
+
expect(() => module.get(Services.ApiKeyService)).toThrow();
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
describe('with organizations enabled', () => {
|
|
194
|
+
let module: TestingModule;
|
|
195
|
+
let providers: any[];
|
|
196
|
+
let controllers: any[];
|
|
197
|
+
beforeEach(async () => {
|
|
198
|
+
jest.clearAllMocks();
|
|
199
|
+
const options: TrailmixCMSOptions = {
|
|
200
|
+
features: {
|
|
201
|
+
enableOrganizations: true
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
const result = setupTrailmixCMS(options);
|
|
205
|
+
providers = result.providers;
|
|
206
|
+
controllers = result.controllers;
|
|
207
|
+
module = await Test.createTestingModule({
|
|
208
|
+
providers,
|
|
209
|
+
controllers,
|
|
210
|
+
}).compile();
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('should include organization controllers when enableOrganizations is true', () => {
|
|
214
|
+
expect(controllers).toContain(Controllers.OrganizationsController);
|
|
215
|
+
expect(controllers).toContain(Controllers.OrganizationRolesController);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('should include organization providers when enableOrganizations is true', async () => {
|
|
219
|
+
const organizationSchema = module.get(PROVIDER_SYMBOLS.ORGANIZATION_SCHEMA);
|
|
220
|
+
const organizationConfig = module.get(PROVIDER_SYMBOLS.ORGANIZATION_CONFIG);
|
|
221
|
+
const organizationMapEntity = module.get(PROVIDER_SYMBOLS.ORGANIZATION_MAP_ENTITY);
|
|
222
|
+
|
|
223
|
+
expect(organizationSchema).toBe(models.Organization.schema);
|
|
224
|
+
expect(organizationConfig).toBeDefined();
|
|
225
|
+
expect(organizationMapEntity).toBeDefined();
|
|
226
|
+
// Organization setup should not be available when not provided
|
|
227
|
+
expect(() => module.get(PROVIDER_SYMBOLS.ORGANIZATION_SETUP)).toThrow();
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it('should not include organization setup provider when not provided', async () => {
|
|
231
|
+
expect(() => module.get(PROVIDER_SYMBOLS.ORGANIZATION_SETUP)).toThrow();
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('should use default organization config when not provided', async () => {
|
|
235
|
+
const organizationConfig = module.get(PROVIDER_SYMBOLS.ORGANIZATION_CONFIG);
|
|
236
|
+
expect(organizationConfig).toBeDefined();
|
|
237
|
+
expect(organizationConfig).toEqual({ disableDefaultIndexes: false });
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('should use default organization mapEntity function that returns entity as-is', async () => {
|
|
241
|
+
const organizationMapEntity = module.get(PROVIDER_SYMBOLS.ORGANIZATION_MAP_ENTITY);
|
|
242
|
+
expect(organizationMapEntity).toBeDefined();
|
|
243
|
+
|
|
244
|
+
const testEntity = { _id: 'test-id', name: 'Test Organization' };
|
|
245
|
+
const mapperFn = organizationMapEntity as (entity: any) => any;
|
|
246
|
+
expect(mapperFn(testEntity)).toBe(testEntity);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('should include organization services and managers when enableOrganizations is true', async () => {
|
|
250
|
+
const organizationCollection = module.get(Collections.OrganizationCollection);
|
|
251
|
+
const organizationService = module.get(Services.OrganizationService);
|
|
252
|
+
const organizationRoleService = module.get(Services.OrganizationRoleService);
|
|
253
|
+
const organizationRoleManager = module.get(Managers.OrganizationRoleManager);
|
|
254
|
+
const organizationManager = module.get(Managers.OrganizationManager);
|
|
255
|
+
const authorizationService = module.get(Services.AuthorizationService);
|
|
256
|
+
|
|
257
|
+
expect(organizationCollection).toBeDefined();
|
|
258
|
+
expect(organizationService).toBeDefined();
|
|
259
|
+
expect(organizationRoleService).toBeDefined();
|
|
260
|
+
expect(organizationRoleManager).toBeDefined();
|
|
261
|
+
expect(organizationManager).toBeDefined();
|
|
262
|
+
expect(authorizationService).toBeDefined();
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
describe('with API keys enabled', () => {
|
|
267
|
+
let module: TestingModule;
|
|
268
|
+
let providers: any[];
|
|
269
|
+
let controllers: any[];
|
|
270
|
+
beforeEach(async () => {
|
|
271
|
+
jest.clearAllMocks();
|
|
272
|
+
const options: TrailmixCMSOptions = {
|
|
273
|
+
features: {
|
|
274
|
+
apiKeys: {
|
|
275
|
+
enabled: true
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
const result = setupTrailmixCMS(options);
|
|
280
|
+
providers = result.providers;
|
|
281
|
+
controllers = result.controllers;
|
|
282
|
+
module = await Test.createTestingModule({
|
|
283
|
+
providers,
|
|
284
|
+
controllers,
|
|
285
|
+
}).compile();
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('should include API key providers when apiKeys.enabled is true', () => {
|
|
289
|
+
const apiKeyCollection = module.get(Collections.ApiKeyCollection);
|
|
290
|
+
const apiKeyService = module.get(Services.ApiKeyService);
|
|
291
|
+
|
|
292
|
+
expect(apiKeyCollection).toBeDefined();
|
|
293
|
+
expect(apiKeyService).toBeDefined();
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('should include API keys controller when apiKeys.enabled is true', () => {
|
|
297
|
+
expect(controllers).toContain(Controllers.ApiKeysController);
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
describe('with both features enabled', () => {
|
|
302
|
+
let module: TestingModule;
|
|
303
|
+
let providers: any[];
|
|
304
|
+
let controllers: any[];
|
|
305
|
+
beforeEach(async () => {
|
|
306
|
+
jest.clearAllMocks();
|
|
307
|
+
const options: TrailmixCMSOptions = {
|
|
308
|
+
features: {
|
|
309
|
+
enableOrganizations: true,
|
|
310
|
+
apiKeys: {
|
|
311
|
+
enabled: true
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
const result = setupTrailmixCMS(options);
|
|
316
|
+
providers = result.providers;
|
|
317
|
+
controllers = result.controllers;
|
|
318
|
+
module = await Test.createTestingModule({
|
|
319
|
+
providers,
|
|
320
|
+
controllers,
|
|
321
|
+
}).compile();
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
it('should include both organization and API key providers', () => {
|
|
325
|
+
const organizationCollection = module.get(Collections.OrganizationCollection);
|
|
326
|
+
const apiKeyCollection = module.get(Collections.ApiKeyCollection);
|
|
327
|
+
const organizationService = module.get(Services.OrganizationService);
|
|
328
|
+
const apiKeyService = module.get(Services.ApiKeyService);
|
|
329
|
+
|
|
330
|
+
expect(organizationCollection).toBeDefined();
|
|
331
|
+
expect(apiKeyCollection).toBeDefined();
|
|
332
|
+
expect(organizationService).toBeDefined();
|
|
333
|
+
expect(apiKeyService).toBeDefined();
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
describe('custom account configuration', () => {
|
|
338
|
+
it('should use custom account schema when provided', async () => {
|
|
339
|
+
const customSchema = z.object({
|
|
340
|
+
_id: z.any().optional(),
|
|
341
|
+
email: z.string(),
|
|
342
|
+
customField: z.string()
|
|
343
|
+
}) as any; // Type assertion for test schema
|
|
344
|
+
const options: TrailmixCMSOptions = {
|
|
345
|
+
entities: {
|
|
346
|
+
accountSchema: customSchema
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
const result = setupTrailmixCMS(options);
|
|
350
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
351
|
+
providers: result.providers,
|
|
352
|
+
controllers: result.controllers,
|
|
353
|
+
}).compile();
|
|
354
|
+
|
|
355
|
+
const accountSchema = module.get(PROVIDER_SYMBOLS.ACCOUNT_SCHEMA);
|
|
356
|
+
expect(accountSchema).toBe(customSchema);
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
it('should use custom account setup when provided', async () => {
|
|
360
|
+
const customSetup = jest.fn(async (collection: Collection<any>) => {
|
|
361
|
+
await collection.createIndex({ email: 1 });
|
|
362
|
+
});
|
|
363
|
+
const options: TrailmixCMSOptions = {
|
|
364
|
+
entities: {
|
|
365
|
+
accountSetup: customSetup
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
const result = setupTrailmixCMS(options);
|
|
369
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
370
|
+
providers: result.providers,
|
|
371
|
+
controllers: result.controllers,
|
|
372
|
+
}).compile();
|
|
373
|
+
|
|
374
|
+
const accountSetup = module.get(PROVIDER_SYMBOLS.ACCOUNT_SETUP);
|
|
375
|
+
expect(accountSetup).toBe(customSetup);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
it('should use custom account config when provided', async () => {
|
|
379
|
+
const customConfig = {
|
|
380
|
+
disableDefaultIndexes: true
|
|
381
|
+
};
|
|
382
|
+
const options: TrailmixCMSOptions = {
|
|
383
|
+
entities: {
|
|
384
|
+
accountConfig: customConfig
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
const result = setupTrailmixCMS(options);
|
|
388
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
389
|
+
providers: result.providers,
|
|
390
|
+
controllers: result.controllers,
|
|
391
|
+
}).compile();
|
|
392
|
+
|
|
393
|
+
const accountConfig = module.get(PROVIDER_SYMBOLS.ACCOUNT_CONFIG);
|
|
394
|
+
expect(accountConfig).toEqual(customConfig);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
it('should use custom account mapEntity when provided', async () => {
|
|
398
|
+
const customMapper = (entity: any) => ({ ...entity, mapped: true });
|
|
399
|
+
const options: TrailmixCMSOptions = {
|
|
400
|
+
entities: {
|
|
401
|
+
accountMapEntity: customMapper
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
const result = setupTrailmixCMS(options);
|
|
405
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
406
|
+
providers: result.providers,
|
|
407
|
+
controllers: result.controllers,
|
|
408
|
+
}).compile();
|
|
409
|
+
|
|
410
|
+
const accountMapEntity = module.get(PROVIDER_SYMBOLS.ACCOUNT_MAP_ENTITY);
|
|
411
|
+
expect(accountMapEntity).toBe(customMapper);
|
|
412
|
+
});
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
describe('custom organization configuration', () => {
|
|
416
|
+
it('should use custom organization schema when provided', async () => {
|
|
417
|
+
const customSchema = z.object({
|
|
418
|
+
_id: z.any().optional(),
|
|
419
|
+
name: z.string(),
|
|
420
|
+
customField: z.string()
|
|
421
|
+
}) as any; // Type assertion for test schema
|
|
422
|
+
const options: TrailmixCMSOptions = {
|
|
423
|
+
features: {
|
|
424
|
+
enableOrganizations: true
|
|
425
|
+
},
|
|
426
|
+
entities: {
|
|
427
|
+
organizationSchema: customSchema
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
const result = setupTrailmixCMS(options);
|
|
431
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
432
|
+
providers: result.providers,
|
|
433
|
+
controllers: result.controllers,
|
|
434
|
+
}).compile();
|
|
435
|
+
|
|
436
|
+
const organizationSchema = module.get(PROVIDER_SYMBOLS.ORGANIZATION_SCHEMA);
|
|
437
|
+
expect(organizationSchema).toBe(customSchema);
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
it('should use custom organization setup when provided', async () => {
|
|
441
|
+
const customSetup = jest.fn(async (collection: Collection<any>) => {
|
|
442
|
+
await collection.createIndex({ name: 1 });
|
|
443
|
+
});
|
|
444
|
+
const options: TrailmixCMSOptions = {
|
|
445
|
+
features: {
|
|
446
|
+
enableOrganizations: true
|
|
447
|
+
},
|
|
448
|
+
entities: {
|
|
449
|
+
organizationSetup: customSetup
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
const result = setupTrailmixCMS(options);
|
|
453
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
454
|
+
providers: result.providers,
|
|
455
|
+
controllers: result.controllers,
|
|
456
|
+
}).compile();
|
|
457
|
+
|
|
458
|
+
const organizationSetup = module.get(PROVIDER_SYMBOLS.ORGANIZATION_SETUP);
|
|
459
|
+
expect(organizationSetup).toBe(customSetup);
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
it('should use custom organization config when provided', async () => {
|
|
463
|
+
const customConfig = {
|
|
464
|
+
disableDefaultIndexes: true
|
|
465
|
+
};
|
|
466
|
+
const options: TrailmixCMSOptions = {
|
|
467
|
+
features: {
|
|
468
|
+
enableOrganizations: true
|
|
469
|
+
},
|
|
470
|
+
entities: {
|
|
471
|
+
organizationConfig: customConfig
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
const result = setupTrailmixCMS(options);
|
|
475
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
476
|
+
providers: result.providers,
|
|
477
|
+
controllers: result.controllers,
|
|
478
|
+
}).compile();
|
|
479
|
+
|
|
480
|
+
const organizationConfig = module.get(PROVIDER_SYMBOLS.ORGANIZATION_CONFIG);
|
|
481
|
+
expect(organizationConfig).toEqual(customConfig);
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
it('should use custom organization mapEntity when provided', async () => {
|
|
485
|
+
const customMapper = (entity: any) => ({ ...entity, mapped: true });
|
|
486
|
+
const options: TrailmixCMSOptions = {
|
|
487
|
+
features: {
|
|
488
|
+
enableOrganizations: true
|
|
489
|
+
},
|
|
490
|
+
entities: {
|
|
491
|
+
organizationMapEntity: customMapper
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
const result = setupTrailmixCMS(options);
|
|
495
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
496
|
+
providers: result.providers,
|
|
497
|
+
controllers: result.controllers,
|
|
498
|
+
}).compile();
|
|
499
|
+
|
|
500
|
+
const organizationMapEntity = module.get(PROVIDER_SYMBOLS.ORGANIZATION_MAP_ENTITY);
|
|
501
|
+
expect(organizationMapEntity).toBe(customMapper);
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
it('should not include organization providers when enableOrganizations is false', async () => {
|
|
505
|
+
const customSchema = z.object({
|
|
506
|
+
_id: z.any().optional(),
|
|
507
|
+
name: z.string()
|
|
508
|
+
}) as any; // Type assertion for test schema
|
|
509
|
+
const options: TrailmixCMSOptions = {
|
|
510
|
+
features: {
|
|
511
|
+
enableOrganizations: false
|
|
512
|
+
},
|
|
513
|
+
entities: {
|
|
514
|
+
organizationSchema: customSchema
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
const result = setupTrailmixCMS(options);
|
|
518
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
519
|
+
providers: result.providers,
|
|
520
|
+
controllers: result.controllers,
|
|
521
|
+
}).compile();
|
|
522
|
+
|
|
523
|
+
expect(() => module.get(PROVIDER_SYMBOLS.ORGANIZATION_SCHEMA)).toThrow();
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
describe('FeatureService initialization', () => {
|
|
528
|
+
it('should initialize FeatureService with provided features', async () => {
|
|
529
|
+
const features = {
|
|
530
|
+
enableOrganizations: true,
|
|
531
|
+
apiKeys: {
|
|
532
|
+
enabled: true as const
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
const options: TrailmixCMSOptions = {
|
|
536
|
+
features
|
|
537
|
+
};
|
|
538
|
+
const result = setupTrailmixCMS(options);
|
|
539
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
540
|
+
providers: result.providers,
|
|
541
|
+
controllers: result.controllers,
|
|
542
|
+
}).compile();
|
|
543
|
+
|
|
544
|
+
const featureService = module.get(Services.FeatureService);
|
|
545
|
+
expect(featureService).toBeDefined();
|
|
546
|
+
expect((featureService as any).features).toEqual(features);
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
it('should initialize FeatureService with undefined when no features provided', async () => {
|
|
550
|
+
const result = setupTrailmixCMS();
|
|
551
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
552
|
+
providers: result.providers,
|
|
553
|
+
controllers: result.controllers,
|
|
554
|
+
}).compile();
|
|
555
|
+
|
|
556
|
+
const featureService = module.get(Services.FeatureService);
|
|
557
|
+
expect(featureService).toBeDefined();
|
|
558
|
+
expect((featureService as any).features).toBeUndefined();
|
|
559
|
+
});
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
describe('collection factory calls', () => {
|
|
563
|
+
it('should call collectionFactory for default collections', () => {
|
|
564
|
+
const { collectionFactory } = require('@trailmix-cms/db');
|
|
565
|
+
setupTrailmixCMS();
|
|
566
|
+
|
|
567
|
+
expect(collectionFactory).toHaveBeenCalledWith(CMSCollectionName.Account);
|
|
568
|
+
expect(collectionFactory).toHaveBeenCalledWith(CMSCollectionName.Role);
|
|
569
|
+
expect(collectionFactory).toHaveBeenCalledWith(CMSCollectionName.SecurityAudit);
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
it('should call collectionFactory for organization collection when enabled', () => {
|
|
573
|
+
const { collectionFactory } = require('@trailmix-cms/db');
|
|
574
|
+
setupTrailmixCMS({
|
|
575
|
+
features: {
|
|
576
|
+
enableOrganizations: true
|
|
577
|
+
}
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
expect(collectionFactory).toHaveBeenCalledWith(CMSCollectionName.Organization);
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
it('should call collectionFactory for API key collection when enabled', () => {
|
|
584
|
+
const { collectionFactory } = require('@trailmix-cms/db');
|
|
585
|
+
setupTrailmixCMS({
|
|
586
|
+
features: {
|
|
587
|
+
apiKeys: {
|
|
588
|
+
enabled: true
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
expect(collectionFactory).toHaveBeenCalledWith(CMSCollectionName.ApiKey);
|
|
594
|
+
});
|
|
595
|
+
});
|
|
596
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Test, TestingModule } from '@nestjs/testing';
|
|
2
|
+
import { Logger } from '@nestjs/common';
|
|
3
|
+
import { faker } from '@faker-js/faker';
|
|
4
|
+
|
|
5
|
+
import * as TestUtils from '../../utils';
|
|
6
|
+
|
|
7
|
+
import { AccountService } from '@/services';
|
|
8
|
+
import { AccountCollection } from '@/collections';
|
|
9
|
+
|
|
10
|
+
describe('AccountService', () => {
|
|
11
|
+
let service: AccountService;
|
|
12
|
+
let accountCollection: jest.Mocked<AccountCollection>;
|
|
13
|
+
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
// Mock Logger methods to prevent console output during tests
|
|
16
|
+
jest.spyOn(Logger.prototype, 'log').mockImplementation();
|
|
17
|
+
jest.spyOn(Logger.prototype, 'error').mockImplementation();
|
|
18
|
+
jest.spyOn(Logger.prototype, 'warn').mockImplementation();
|
|
19
|
+
jest.spyOn(Logger.prototype, 'debug').mockImplementation();
|
|
20
|
+
jest.spyOn(Logger.prototype, 'verbose').mockImplementation();
|
|
21
|
+
|
|
22
|
+
const mockAccountCollection = {
|
|
23
|
+
findOne: jest.fn(),
|
|
24
|
+
upsertOne: jest.fn(),
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
28
|
+
providers: [
|
|
29
|
+
AccountService,
|
|
30
|
+
{
|
|
31
|
+
provide: AccountCollection,
|
|
32
|
+
useValue: mockAccountCollection,
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
}).compile();
|
|
36
|
+
|
|
37
|
+
service = module.get<AccountService>(AccountService);
|
|
38
|
+
accountCollection = module.get(AccountCollection);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
jest.clearAllMocks();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
afterAll(() => {
|
|
46
|
+
// Restore Logger methods after all tests
|
|
47
|
+
jest.restoreAllMocks();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('getAccount', () => {
|
|
51
|
+
it('calls findOne with correct query and returns result', async () => {
|
|
52
|
+
const userId = faker.string.uuid();
|
|
53
|
+
const account = TestUtils.Entities.createAccount({ user_id: userId });
|
|
54
|
+
|
|
55
|
+
accountCollection.findOne.mockResolvedValue(account);
|
|
56
|
+
|
|
57
|
+
const result = await service.getAccount(userId);
|
|
58
|
+
|
|
59
|
+
expect(accountCollection.findOne).toHaveBeenCalledWith({ user_id: userId });
|
|
60
|
+
expect(result).toEqual(account);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('upsertAccount', () => {
|
|
65
|
+
it('calls upsertOne with correct parameters and returns result', async () => {
|
|
66
|
+
const userId = faker.string.uuid();
|
|
67
|
+
const account = TestUtils.Entities.createAccount({ user_id: userId });
|
|
68
|
+
|
|
69
|
+
accountCollection.upsertOne.mockResolvedValue(account);
|
|
70
|
+
|
|
71
|
+
const result = await service.upsertAccount(userId);
|
|
72
|
+
|
|
73
|
+
expect(accountCollection.upsertOne).toHaveBeenCalledWith(
|
|
74
|
+
{ user_id: userId },
|
|
75
|
+
{
|
|
76
|
+
$set: {
|
|
77
|
+
user_id: userId,
|
|
78
|
+
},
|
|
79
|
+
$setOnInsert: {},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
system: true,
|
|
83
|
+
message: 'Account upserted',
|
|
84
|
+
source: AccountService.name,
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
expect(result).toEqual(account);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|