@avleon/core 0.0.17 → 0.0.19

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.
@@ -1,4 +1,4 @@
1
- import { EntityTarget, FindOneOptions, ObjectLiteral, Repository as TypeOrmRepository } from "typeorm";
1
+ import { EntityTarget, FindOneOptions, ObjectLiteral, Repository } from "typeorm";
2
2
  type PaginationOptions = {
3
3
  take: number;
4
4
  skip?: number;
@@ -13,9 +13,6 @@ export type PaginationResult<T> = {
13
13
  last?: number | null;
14
14
  totalPage?: number;
15
15
  };
16
- export declare class Repository<Entity extends ObjectLiteral> extends TypeOrmRepository<Entity> {
17
- paginate(options?: PaginationOptions): Promise<PaginationResult<Entity>>;
18
- }
19
16
  type ICollection<T> = {
20
17
  findAll(): T[] | Promise<T[]>;
21
18
  };
@@ -49,4 +46,5 @@ export declare class Collection {
49
46
  static from<T>(items: T[]): BasicCollection<T>;
50
47
  static fromRepository<T extends ObjectLiteral>(entity: EntityTarget<T>): Repository<T>;
51
48
  }
49
+ export declare function InjectRepository<T extends Repository<T>>(model: EntityTarget<T>): (object: any, propertyName: string | undefined, index?: number) => void;
52
50
  export {};
@@ -3,7 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.Collection = exports.Repository = void 0;
6
+ exports.Collection = void 0;
7
+ exports.InjectRepository = InjectRepository;
7
8
  /**
8
9
  * @copyright 2024
9
10
  * @author Tareq Hossain
@@ -12,18 +13,6 @@ exports.Collection = exports.Repository = void 0;
12
13
  */
13
14
  const typedi_1 = __importDefault(require("typedi"));
14
15
  const exceptions_1 = require("./exceptions");
15
- const typeorm_1 = require("typeorm");
16
- class Repository extends typeorm_1.Repository {
17
- async paginate(options = { take: 10, skip: 0 }) {
18
- const total = await this.count();
19
- const data = await this.find({
20
- take: options.take || 10,
21
- skip: options.skip || 0,
22
- });
23
- return { total, data };
24
- }
25
- }
26
- exports.Repository = Repository;
27
16
  class BasicCollection {
28
17
  constructor(items) {
29
18
  this.items = items;
@@ -119,10 +108,9 @@ class AsynchronousCollection {
119
108
  }
120
109
  getRepository() {
121
110
  if (!this.repo) {
122
- const dataSource = typedi_1.default.get("idatasource");
123
- const repository = dataSource.getRepository(this.model).extend({
124
- paginate: this.paginate,
125
- });
111
+ const dataSourceKey = process.env.NODE_ENV === "test" ? "itestdatasource" : "idatasource";
112
+ const dataSource = typedi_1.default.get(dataSourceKey);
113
+ const repository = dataSource.getRepository(this.model);
126
114
  this.repo = repository;
127
115
  return repository;
128
116
  }
@@ -144,146 +132,56 @@ class AsynchronousCollection {
144
132
  data,
145
133
  };
146
134
  }
147
- createQueryBuilder(alias, queryRunner) {
148
- return this.getRepository().createQueryBuilder(alias, queryRunner);
149
- }
150
- hasId(entity) {
151
- return this.getRepository().hasId(entity);
152
- }
153
- getId(entity) {
154
- return this.getRepository().getId(entity);
155
- }
156
- create(entityLike) {
157
- return this.getRepository().create(entityLike);
158
- }
159
- merge(mergeIntoEntity, ...entityLikes) {
160
- return this.getRepository().merge(mergeIntoEntity, ...entityLikes);
161
- }
162
- async preload(entityLike) {
163
- return this.getRepository().preload(entityLike);
164
- }
165
- async save(entities, options) {
166
- return this.getRepository().save(entities, options);
167
- }
168
- async remove(entity) {
169
- return this.getRepository().remove(entity);
170
- }
171
- async softRemove(entity) {
172
- return this.getRepository().softRemove(entity);
173
- }
174
- async recover(entity) {
175
- return this.getRepository().recover(entity);
176
- }
177
- async insert(entity) {
178
- await this.getRepository().insert(entity);
179
- }
180
- async update(criteria, partialEntity) {
181
- return this.getRepository().update(criteria, partialEntity);
182
- }
183
- async upsert(entityOrEntities, conflictPathsOrOptions) {
184
- await this.getRepository().upsert(entityOrEntities, conflictPathsOrOptions);
185
- }
186
- async delete(criteria) {
187
- return this.getRepository().delete(criteria);
188
- }
189
- async softDelete(criteria) {
190
- return this.getRepository().softDelete(criteria);
191
- }
192
- async restore(criteria) {
193
- return this.getRepository().restore(criteria);
194
- }
195
- async exist(options) {
196
- return (await this.getRepository().count(options)) > 0;
197
- }
198
- async exists(options) {
199
- return this.exist(options);
200
- }
201
- async existsBy(where) {
202
- return (await this.getRepository().count({ where })) > 0;
203
- }
204
- async count(options) {
205
- return this.getRepository().count(options);
206
- }
207
- async countBy(where) {
208
- return this.getRepository().count({ where });
209
- }
210
- async sum(columnName, where) {
211
- return this.getRepository()
212
- .createQueryBuilder()
213
- .select(`SUM(${columnName})`, "sum")
214
- .where(where || {})
215
- .getRawOne()
216
- .then((res) => (res === null || res === void 0 ? void 0 : res.sum) || null);
217
- }
218
- async average(columnName, where) {
219
- return this.getRepository()
220
- .createQueryBuilder()
221
- .select(`AVG(${columnName})`, "average")
222
- .where(where || {})
223
- .getRawOne()
224
- .then((res) => (res === null || res === void 0 ? void 0 : res.average) || null);
225
- }
226
- async minimum(columnName, where) {
227
- return this.getRepository()
228
- .createQueryBuilder()
229
- .select(`MIN(${columnName})`, "minimum")
230
- .where(where || {})
231
- .getRawOne()
232
- .then((res) => (res === null || res === void 0 ? void 0 : res.minimum) || null);
233
- }
234
- async maximum(columnName, where) {
235
- return this.getRepository().maximum(columnName, where);
236
- }
237
- async find(options) {
238
- return await this.getRepository().find(options);
239
- }
240
- async findBy(where) {
241
- return this.getRepository().findBy(where);
242
- }
243
- async findAndCount(options) {
244
- return this.getRepository().findAndCount(options);
245
- }
246
- async findAndCountBy(where) {
247
- return this.getRepository().findAndCount({ where });
248
- }
249
- async findByIds(ids) {
250
- return this.getRepository().findBy(ids);
251
- }
252
- async findOne(options) {
253
- return this.getRepository().findOne(options);
254
- }
255
- async findOneBy(where) {
256
- return this.getRepository().findOneBy(where);
257
- }
258
- async findOneById(id) {
259
- return this.getRepository().findOneBy({ id });
260
- }
261
- async findOneOrFail(options) {
262
- return this.getRepository().findOneOrFail(options);
263
- }
264
- async findOneByOrFail(where) {
265
- return this.getRepository().findOneByOrFail(where);
266
- }
267
- async query(query, parameters) {
268
- return this.getRepository().query(query, parameters);
269
- }
270
- async clear() {
271
- await this.getRepository().clear();
272
- }
273
- async increment(conditions, propertyPath, value) {
274
- return this.getRepository().increment(conditions, propertyPath, value);
275
- }
276
- async decrement(conditions, propertyPath, value) {
277
- return this.getRepository().decrement(conditions, propertyPath, value);
278
- }
279
135
  }
280
136
  class Collection {
281
137
  constructor() { }
282
138
  static from(items) {
283
139
  return BasicCollection.from(items);
284
140
  }
141
+ // Example refactoring of Collection.fromRepository for better type safety
285
142
  static fromRepository(entity) {
286
- return AsynchronousCollection.fromRepository(entity);
143
+ const asyncCollection = AsynchronousCollection.fromRepository(entity);
144
+ // Assuming AsynchronousCollection has a method to get the Repository<T>
145
+ return asyncCollection.getRepository();
287
146
  }
288
147
  }
289
148
  exports.Collection = Collection;
149
+ function InjectRepository(model) {
150
+ return function (object, propertyName, index) {
151
+ let repo;
152
+ try {
153
+ typedi_1.default.registerHandler({
154
+ object,
155
+ propertyName,
156
+ index,
157
+ value: (containerInstance) => {
158
+ const dataSource = containerInstance.get("idatasource");
159
+ repo = dataSource
160
+ .getRepository(model)
161
+ .extend({ paginate: () => { } });
162
+ repo.paginate = async function (options = { take: 10, skip: 0 }) {
163
+ const [data, total] = await this.findAndCount({
164
+ take: options.take || 10,
165
+ skip: options.skip || 0,
166
+ });
167
+ return {
168
+ total,
169
+ totalPage: Math.ceil(total / (options.take || 10)),
170
+ next: options.skip + options.take < total
171
+ ? options.skip + options.take
172
+ : null,
173
+ data,
174
+ };
175
+ };
176
+ return repo;
177
+ },
178
+ });
179
+ }
180
+ catch (error) {
181
+ console.log(error);
182
+ if (error.name && error.name == "ServiceNotFoundError") {
183
+ console.log("Database didn't initialized.");
184
+ }
185
+ }
186
+ };
187
+ }
@@ -0,0 +1 @@
1
+ export declare const TEST_DATASOURCE_OPTIONS_KEY: unique symbol;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TEST_DATASOURCE_OPTIONS_KEY = void 0;
4
+ exports.TEST_DATASOURCE_OPTIONS_KEY = Symbol("itestdatasource");
package/dist/icore.d.ts CHANGED
@@ -40,6 +40,7 @@ export interface TestApplication {
40
40
  patch: (url: string, options?: InjectOptions) => TestResponse;
41
41
  delete: (url: string, options?: InjectOptions) => TestResponse;
42
42
  options: (url: string, options?: InjectOptions) => TestResponse;
43
+ getController?: <T>(controller: Constructor<T>) => T;
43
44
  }
44
45
  export interface ParamMetaOptions {
45
46
  index: number;
@@ -101,7 +102,7 @@ export interface IAvleonApplication {
101
102
  run(port?: number): Promise<void>;
102
103
  getTestApp(): TestApplication;
103
104
  }
104
- declare class AvleonApplication implements IAvleonApplication {
105
+ export declare class AvleonApplication implements IAvleonApplication {
105
106
  private static instance;
106
107
  private static buildOptions;
107
108
  private app;
@@ -120,6 +121,7 @@ declare class AvleonApplication implements IAvleonApplication {
120
121
  private metaCache;
121
122
  private multipartOptions;
122
123
  private constructor();
124
+ private isTest;
123
125
  static getInternalApp(buildOptions: any): AvleonApplication;
124
126
  isDevelopment(): boolean;
125
127
  private initSwagger;
@@ -202,8 +204,8 @@ export declare class TestBuilder {
202
204
  private constructor();
203
205
  static createBuilder(): TestBuilder;
204
206
  addDatasource(options: DataSourceOptions): void;
205
- getController<T>(controller: Constructor<T>): T;
206
- getService<T>(service: Constructor<T>): T;
207
+ private getController;
208
+ private getService;
207
209
  getTestApplication(options: TestAppOptions): TestApplication;
208
210
  build(app: IAvleonApplication): TestApplication;
209
211
  fromApplication(app: IAvleonApplication): TestApplication;
package/dist/icore.js CHANGED
@@ -54,7 +54,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
54
54
  return (mod && mod.__esModule) ? mod : { "default": mod };
55
55
  };
56
56
  Object.defineProperty(exports, "__esModule", { value: true });
57
- exports.Builder = exports.TestBuilder = void 0;
57
+ exports.Builder = exports.TestBuilder = exports.AvleonApplication = void 0;
58
58
  /**
59
59
  * @copyright 2024
60
60
  * @author Tareq Hossain
@@ -94,25 +94,23 @@ class AvleonApplication {
94
94
  this.authorizeMiddleware = undefined;
95
95
  this.dataSource = undefined;
96
96
  this.metaCache = new Map();
97
- this.app = (0, fastify_1.default)({
98
- frameworkErrors: (error, req, res) => { },
99
- });
97
+ this.app = (0, fastify_1.default)();
100
98
  this.appConfig = new config_1.AppConfig();
101
99
  // this.app.setValidatorCompiler(() => () => true);
102
100
  }
101
+ isTest() { }
103
102
  static getInternalApp(buildOptions) {
103
+ let isTestEnv = process.env.NODE_ENV == "test";
104
104
  if (!AvleonApplication.instance) {
105
105
  AvleonApplication.instance = new AvleonApplication();
106
106
  }
107
107
  AvleonApplication.buildOptions = buildOptions;
108
- if (buildOptions.controllers) {
109
- }
110
108
  if (buildOptions.dataSourceOptions) {
111
109
  AvleonApplication.instance.dataSourceOptions =
112
110
  buildOptions.dataSourceOptions;
113
111
  const typeorm = require("typeorm");
114
112
  const datasource = new typeorm.DataSource(buildOptions.dataSourceOptions);
115
- typedi_1.default.set("idatasource", datasource);
113
+ typedi_1.default.set(isTestEnv ? "itestdatasource" : "idatasource", datasource);
116
114
  AvleonApplication.instance.dataSource = datasource;
117
115
  }
118
116
  return AvleonApplication.instance;
@@ -590,22 +588,8 @@ class AvleonApplication {
590
588
  }
591
589
  getTestApp(buildOptions) {
592
590
  try {
593
- if (buildOptions && buildOptions.addDataSource) {
594
- const typeorm = Promise.resolve().then(() => __importStar(require("typeorm")));
595
- if (!typeorm) {
596
- throw new system_exception_1.SystemUseError("TypeOrm not installed");
597
- }
598
- typeorm.then(async (t) => {
599
- try {
600
- const datasource = new t.DataSource(buildOptions.addDataSource);
601
- typedi_1.default.set("idatasource", datasource);
602
- await datasource.initialize();
603
- }
604
- catch (error) {
605
- console.error("Database can't initialized.", error);
606
- }
607
- });
608
- }
591
+ // }
592
+ // this.initializeDatabase();
609
593
  this._mapControllers();
610
594
  this.rMap.forEach((value, key) => {
611
595
  const [m, r] = key.split(":");
@@ -632,23 +616,31 @@ class AvleonApplication {
632
616
  return res.status(handledErr.code).send(handledErr);
633
617
  });
634
618
  // return this.app as any;
619
+ //
635
620
  return {
636
- get: (url, options) => this.app.inject(Object.assign({ method: "GET", url }, options)),
637
- post: (url, options) => this.app.inject(Object.assign({ method: "POST", url }, options)),
638
- put: (url, options) => this.app.inject(Object.assign({ method: "PUT", url }, options)),
639
- patch: (url, options) => this.app.inject(Object.assign({ method: "PATCH", url }, options)),
640
- delete: (url, options) => this.app.inject(Object.assign({ method: "DELETE", url }, options)),
641
- options: (url, options) => this.app.inject(Object.assign({ method: "OPTIONS", url }, options)),
621
+ get: async (url, options) => this.app.inject(Object.assign({ method: "GET", url }, options)),
622
+ post: async (url, options) => this.app.inject(Object.assign({ method: "POST", url }, options)),
623
+ put: async (url, options) => this.app.inject(Object.assign({ method: "PUT", url }, options)),
624
+ patch: async (url, options) => this.app.inject(Object.assign({ method: "PATCH", url }, options)),
625
+ delete: async (url, options) => this.app.inject(Object.assign({ method: "DELETE", url }, options)),
626
+ options: async (url, options) => this.app.inject(Object.assign({ method: "OPTIONS", url }, options)),
627
+ getController: (controller) => {
628
+ return typedi_1.default.get(controller);
629
+ },
642
630
  };
643
631
  }
644
632
  catch (error) {
633
+ console.log(error);
645
634
  throw new system_exception_1.SystemUseError("Can't get test appliction");
646
635
  }
647
636
  }
648
637
  }
638
+ exports.AvleonApplication = AvleonApplication;
649
639
  AvleonApplication.buildOptions = {};
650
640
  class TestBuilder {
651
- constructor() { }
641
+ constructor() {
642
+ process.env.NODE_ENV = "test";
643
+ }
652
644
  static createBuilder() {
653
645
  if (!TestBuilder.instance) {
654
646
  TestBuilder.instance = new TestBuilder();
@@ -669,8 +661,7 @@ class TestBuilder {
669
661
  dataSourceOptions: this.dataSourceOptions,
670
662
  });
671
663
  app.mapControllers([...options.controllers]);
672
- const fa = app.getTestApp();
673
- return fa;
664
+ return app.getTestApp();
674
665
  }
675
666
  build(app) {
676
667
  return app.getTestApp();
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import * as sw from "./swagger-schema";
8
8
  export * from "./icore";
9
+ export * from "./testing";
9
10
  export { inject, validateRequestBody } from "./helpers";
10
11
  export * from "./decorators";
11
12
  export * from "./middleware";
package/dist/index.js CHANGED
@@ -48,6 +48,7 @@ exports.Container = exports.GetSchema = exports.validateRequestBody = exports.in
48
48
  */
49
49
  const sw = __importStar(require("./swagger-schema"));
50
50
  __exportStar(require("./icore"), exports);
51
+ __exportStar(require("./testing"), exports);
51
52
  var helpers_1 = require("./helpers");
52
53
  Object.defineProperty(exports, "inject", { enumerable: true, get: function () { return helpers_1.inject; } });
53
54
  Object.defineProperty(exports, "validateRequestBody", { enumerable: true, get: function () { return helpers_1.validateRequestBody; } });
@@ -0,0 +1,55 @@
1
+ import "reflect-metadata";
2
+ import { DataSourceOptions } from "typeorm";
3
+ export declare class AvleonTestUtility {
4
+ private static testDataSource;
5
+ private static testContainer;
6
+ /**
7
+ * Initialize test environment
8
+ */
9
+ static init(options?: {
10
+ dataSourceOptions?: DataSourceOptions;
11
+ resetContainer?: boolean;
12
+ }): Promise<typeof AvleonTestUtility>;
13
+ /**
14
+ * Mock a dependency for testing
15
+ * @param token Dependency token
16
+ * @param mockImplementation Mock implementation
17
+ */
18
+ static mockDependency<T>(token: any, mockImplementation: T): T;
19
+ /**
20
+ * Create an isolated test instance of a class
21
+ * @param ClassType Class to instantiate
22
+ * @param overrides Optional property overrides
23
+ */
24
+ static createTestInstance<T>(ClassType: new (...args: any[]) => T, overrides?: Partial<T>): T;
25
+ /**
26
+ * Cleanup test environment
27
+ */
28
+ static cleanup(): Promise<void>;
29
+ }
30
+ export declare class AvleonTestBuilder {
31
+ private controllers;
32
+ private testOptions;
33
+ private mocks;
34
+ /**
35
+ * Add controllers for testing
36
+ * @param controllers Controllers to add
37
+ */
38
+ addControllers(...controllers: any[]): this;
39
+ /**
40
+ * Mock a dependency
41
+ * @param token Dependency token
42
+ * @param mockImplementation Mock implementation
43
+ */
44
+ mockDependency(token: any, mockImplementation: any): this;
45
+ /**
46
+ * Set test options
47
+ * @param options Test configuration options
48
+ */
49
+ setOptions(options: any): this;
50
+ /**
51
+ * Build test application
52
+ */
53
+ build(): Promise<import("./icore").TestApplication>;
54
+ }
55
+ export declare function UnitTest(): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AvleonTestBuilder = exports.AvleonTestUtility = void 0;
4
+ exports.UnitTest = UnitTest;
5
+ require("reflect-metadata");
6
+ const typedi_1 = require("typedi");
7
+ const typeorm_1 = require("typeorm");
8
+ const icore_1 = require("./icore");
9
+ // Enhanced Test Utilities
10
+ class AvleonTestUtility {
11
+ /**
12
+ * Initialize test environment
13
+ */
14
+ static async init(options) {
15
+ // Reset container if specified
16
+ if (options === null || options === void 0 ? void 0 : options.resetContainer) {
17
+ this.testContainer = typedi_1.Container;
18
+ this.testContainer.reset();
19
+ }
20
+ // Initialize test database if options provided
21
+ if (options === null || options === void 0 ? void 0 : options.dataSourceOptions) {
22
+ this.testDataSource = new typeorm_1.DataSource(Object.assign(Object.assign({}, options.dataSourceOptions), { logging: false }));
23
+ await this.testDataSource.initialize();
24
+ await this.testDataSource.synchronize(true); // Create schema
25
+ }
26
+ return this;
27
+ }
28
+ /**
29
+ * Mock a dependency for testing
30
+ * @param token Dependency token
31
+ * @param mockImplementation Mock implementation
32
+ */
33
+ static mockDependency(token, mockImplementation) {
34
+ typedi_1.Container.set(token, mockImplementation);
35
+ return mockImplementation;
36
+ }
37
+ /**
38
+ * Create an isolated test instance of a class
39
+ * @param ClassType Class to instantiate
40
+ * @param overrides Optional property overrides
41
+ */
42
+ static createTestInstance(ClassType, overrides = {}) {
43
+ const instance = typedi_1.Container.get(ClassType);
44
+ // Apply overrides
45
+ Object.keys(overrides).forEach((key) => {
46
+ instance[key] = overrides[key];
47
+ });
48
+ return instance;
49
+ }
50
+ /**
51
+ * Cleanup test environment
52
+ */
53
+ static async cleanup() {
54
+ if (this.testDataSource) {
55
+ await this.testDataSource.dropDatabase();
56
+ await this.testDataSource.destroy();
57
+ this.testDataSource = null;
58
+ }
59
+ // Reset container
60
+ typedi_1.Container.reset();
61
+ }
62
+ }
63
+ exports.AvleonTestUtility = AvleonTestUtility;
64
+ AvleonTestUtility.testDataSource = null;
65
+ // Enhanced Test Builder
66
+ class AvleonTestBuilder {
67
+ constructor() {
68
+ this.controllers = [];
69
+ this.testOptions = {};
70
+ this.mocks = new Map();
71
+ }
72
+ /**
73
+ * Add controllers for testing
74
+ * @param controllers Controllers to add
75
+ */
76
+ addControllers(...controllers) {
77
+ this.controllers.push(...controllers);
78
+ return this;
79
+ }
80
+ /**
81
+ * Mock a dependency
82
+ * @param token Dependency token
83
+ * @param mockImplementation Mock implementation
84
+ */
85
+ mockDependency(token, mockImplementation) {
86
+ this.mocks.set(token, mockImplementation);
87
+ return this;
88
+ }
89
+ /**
90
+ * Set test options
91
+ * @param options Test configuration options
92
+ */
93
+ setOptions(options) {
94
+ this.testOptions = Object.assign(Object.assign({}, this.testOptions), options);
95
+ return this;
96
+ }
97
+ /**
98
+ * Build test application
99
+ */
100
+ async build() {
101
+ // Apply mocks
102
+ this.mocks.forEach((mock, token) => {
103
+ typedi_1.Container.set(token, mock);
104
+ });
105
+ // Initialize test utility
106
+ await AvleonTestUtility.init({
107
+ dataSourceOptions: this.testOptions.dataSourceOptions,
108
+ resetContainer: true,
109
+ });
110
+ // Create test application
111
+ const app = icore_1.AvleonApplication.getInternalApp({
112
+ dataSourceOptions: this.testOptions.dataSourceOptions,
113
+ });
114
+ // Map controllers
115
+ app.mapControllers(this.controllers);
116
+ // Get test application
117
+ return app.getTestApp();
118
+ }
119
+ }
120
+ exports.AvleonTestBuilder = AvleonTestBuilder;
121
+ // Example Usage Decorator
122
+ function UnitTest() {
123
+ return (target, propertyKey, descriptor) => {
124
+ const originalMethod = descriptor.value;
125
+ descriptor.value = async function (...args) {
126
+ try {
127
+ // Pre-test setup
128
+ await AvleonTestUtility.init();
129
+ // Execute test
130
+ const result = await originalMethod.apply(this, args);
131
+ // Post-test cleanup
132
+ await AvleonTestUtility.cleanup();
133
+ return result;
134
+ }
135
+ catch (error) {
136
+ // Ensure cleanup even if test fails
137
+ await AvleonTestUtility.cleanup();
138
+ throw error;
139
+ }
140
+ };
141
+ return descriptor;
142
+ };
143
+ }
144
+ //
145
+ // // Example of Unit and Integration Test
146
+ // class UserServiceTest {
147
+ // @UnitTest()
148
+ // async testUserCreation() {
149
+ // // Mock UserRepository
150
+ // const mockRepo = AvleonTestUtility.mockDependency(
151
+ // UserRepository,
152
+ // { create: jest.fn() }
153
+ // );
154
+ //
155
+ // // Create test instance
156
+ // const userService = AvleonTestUtility.createTestInstance(UserService);
157
+ //
158
+ // // Perform test
159
+ // const result = await userService.createUser({
160
+ // name: 'Test User',
161
+ // email: 'test@example.com'
162
+ // });
163
+ //
164
+ // // Assertions
165
+ // expect(mockRepo.create).toHaveBeenCalledWith(expect.any(Object));
166
+ // }
167
+ // }
168
+ //
169
+ // // Enhanced E2E Testing Example
170
+ // class E2EUserControllerTest {
171
+ // async testUserRegistration() {
172
+ // // Build test application
173
+ // const testApp = await new AvleonTestBuilder()
174
+ // .addControllers(UserController)
175
+ // .mockDependency(AuthService, mockAuthService)
176
+ // .setOptions({
177
+ // dataSourceOptions: testDatabaseConfig
178
+ // })
179
+ // .build();
180
+ //
181
+ // // Perform HTTP request
182
+ // const response = await testApp.post('/users/register', {
183
+ // payload: {
184
+ // name: 'John Doe',
185
+ // email: 'john@example.com'
186
+ // }
187
+ // });
188
+ //
189
+ // // Assertions
190
+ // expect(response.statusCode).toBe(201);
191
+ // expect(response.json()).toHaveProperty('userId');
192
+ // }
193
+ // }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@avleon/core",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "main": "./dist/index.js",
5
5
  "scripts": {
6
6
  "build": "rimraf dist && tsc",