@solidxai/core 0.1.10-beta.6 → 0.1.10-beta.7
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/seeders/module-test-data.service.d.ts +7 -0
- package/dist/seeders/module-test-data.service.d.ts.map +1 -1
- package/dist/seeders/module-test-data.service.js +94 -18
- package/dist/seeders/module-test-data.service.js.map +1 -1
- package/dist/testing/reporter/console-reporter.d.ts +10 -0
- package/dist/testing/reporter/console-reporter.d.ts.map +1 -1
- package/dist/testing/reporter/console-reporter.js +21 -0
- package/dist/testing/reporter/console-reporter.js.map +1 -1
- package/dist/testing/reporter/reporter.types.d.ts +7 -0
- package/dist/testing/reporter/reporter.types.d.ts.map +1 -1
- package/dist/testing/reporter/reporter.types.js.map +1 -1
- package/dist/testing/runner/run-from-metadata.d.ts.map +1 -1
- package/dist/testing/runner/run-from-metadata.js +20 -1
- package/dist/testing/runner/run-from-metadata.js.map +1 -1
- package/package.json +1 -1
- package/src/seeders/module-test-data.service.ts +107 -15
- package/src/testing/reporter/console-reporter.ts +27 -0
- package/src/testing/reporter/reporter.types.ts +7 -0
- package/src/testing/runner/run-from-metadata.ts +19 -1
|
@@ -5,6 +5,7 @@ export declare class ModuleTestDataService {
|
|
|
5
5
|
private readonly discoveryService;
|
|
6
6
|
private readonly solidRegistry;
|
|
7
7
|
private readonly logger;
|
|
8
|
+
private static readonly TEARDOWN_RETRY_ATTEMPTS;
|
|
8
9
|
constructor(moduleRef: ModuleRef, discoveryService: DiscoveryService, solidRegistry: SolidRegistry);
|
|
9
10
|
setupTestData(modulesToTest?: string[]): Promise<void>;
|
|
10
11
|
createTestDatasources(): Promise<void>;
|
|
@@ -27,6 +28,12 @@ export declare class ModuleTestDataService {
|
|
|
27
28
|
private resolveDataSourceByName;
|
|
28
29
|
private updateTestManifest;
|
|
29
30
|
private dropTestDatabaseObjects;
|
|
31
|
+
private dropTestDatabaseObjectsWithRetry;
|
|
32
|
+
private teardownRetryDelayMs;
|
|
33
|
+
private sleep;
|
|
34
|
+
private dropSingleTestDatabaseObject;
|
|
35
|
+
private dropPostgresDatabase;
|
|
36
|
+
private resolvePostgresMaintenanceDatabase;
|
|
30
37
|
private dropMssqlSchema;
|
|
31
38
|
}
|
|
32
39
|
//# sourceMappingURL=module-test-data.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-test-data.service.d.ts","sourceRoot":"","sources":["../../src/seeders/module-test-data.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAY3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAU3D,qBACa,qBAAqB;
|
|
1
|
+
{"version":3,"file":"module-test-data.service.d.ts","sourceRoot":"","sources":["../../src/seeders/module-test-data.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAY3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAU3D,qBACa,qBAAqB;IAK9B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa;IANhC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAK;gBAGjC,SAAS,EAAE,SAAS,EACpB,gBAAgB,EAAE,gBAAgB,EAClC,aAAa,EAAE,aAAa;IAGzC,aAAa,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBtD,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAqEtC,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAoD5C,OAAO,KAAK,aAAa,GAexB;YAEa,YAAY;YA4HZ,aAAa;YAoCb,qBAAqB;YA6BrB,aAAa;YAmBb,kBAAkB;YAsDlB,eAAe;IAsD7B,OAAO,KAAK,aAAa,GAExB;IAED,OAAO,KAAK,oBAAoB,GAE/B;IAED,OAAO,KAAK,eAAe,GAE1B;IAED,OAAO,CAAC,iBAAiB;IAqBzB,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,oBAAoB;YA4Bd,yBAAyB;IA6BvC,OAAO,CAAC,uBAAuB;IAa/B,OAAO,CAAC,kBAAkB;YAmCZ,uBAAuB;YAOvB,gCAAgC;IAsB9C,OAAO,CAAC,oBAAoB;YAOd,KAAK;YAIL,4BAA4B;YA2B5B,oBAAoB;IAsClC,OAAO,CAAC,kCAAkC;YAc5B,eAAe;CA4B9B"}
|
|
@@ -599,31 +599,106 @@ let ModuleTestDataService = ModuleTestDataService_1 = class ModuleTestDataServic
|
|
|
599
599
|
async dropTestDatabaseObjects(databases) {
|
|
600
600
|
const entries = Object.entries(databases);
|
|
601
601
|
for (const [dsName, dbName] of entries) {
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
602
|
+
await this.dropTestDatabaseObjectsWithRetry(dsName, dbName);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
async dropTestDatabaseObjectsWithRetry(dsName, dbName) {
|
|
606
|
+
let lastError;
|
|
607
|
+
for (let attempt = 1; attempt <= ModuleTestDataService_1.TEARDOWN_RETRY_ATTEMPTS; attempt += 1) {
|
|
608
|
+
console.log(`Attempting to tear down "${dbName}" on datasource "${dsName}" (${attempt}/${ModuleTestDataService_1.TEARDOWN_RETRY_ATTEMPTS})...`);
|
|
608
609
|
try {
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
else if (type === 'mysql' || type === 'mariadb') {
|
|
617
|
-
await queryRunner.query(`DROP DATABASE IF EXISTS \`${dbName}\``);
|
|
618
|
-
}
|
|
619
|
-
else {
|
|
620
|
-
throw new Error(`Unsupported database type for test data deletion: ${type}`);
|
|
610
|
+
await this.dropSingleTestDatabaseObject(dsName, dbName);
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
catch (error) {
|
|
614
|
+
lastError = error;
|
|
615
|
+
if (attempt >= ModuleTestDataService_1.TEARDOWN_RETRY_ATTEMPTS) {
|
|
616
|
+
throw error;
|
|
621
617
|
}
|
|
618
|
+
await this.sleep(this.teardownRetryDelayMs(attempt));
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
622
|
+
}
|
|
623
|
+
teardownRetryDelayMs(attempt) {
|
|
624
|
+
const baseMs = 500;
|
|
625
|
+
const incrementMs = 350;
|
|
626
|
+
const jitterMs = Math.floor(Math.random() * 250);
|
|
627
|
+
return baseMs + ((attempt - 1) * incrementMs) + jitterMs;
|
|
628
|
+
}
|
|
629
|
+
async sleep(ms) {
|
|
630
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
631
|
+
}
|
|
632
|
+
async dropSingleTestDatabaseObject(dsName, dbName) {
|
|
633
|
+
const dataSource = this.resolveDataSourceByName(dsName);
|
|
634
|
+
if (dataSource.options.type === 'postgres') {
|
|
635
|
+
await this.dropPostgresDatabase(dataSource, dbName);
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
if (!dataSource.isInitialized) {
|
|
639
|
+
await dataSource.initialize();
|
|
640
|
+
}
|
|
641
|
+
const queryRunner = dataSource.createQueryRunner();
|
|
642
|
+
try {
|
|
643
|
+
const type = dataSource.options.type;
|
|
644
|
+
if (type === 'mssql') {
|
|
645
|
+
await this.dropMssqlSchema(queryRunner, dbName);
|
|
646
|
+
}
|
|
647
|
+
else if (type === 'mysql' || type === 'mariadb') {
|
|
648
|
+
await queryRunner.query(`DROP DATABASE IF EXISTS \`${dbName}\``);
|
|
649
|
+
}
|
|
650
|
+
else {
|
|
651
|
+
throw new Error(`Unsupported database type for test data deletion: ${type}`);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
finally {
|
|
655
|
+
await queryRunner.release();
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
async dropPostgresDatabase(dataSource, dbName) {
|
|
659
|
+
if (dataSource.isInitialized) {
|
|
660
|
+
await dataSource.destroy();
|
|
661
|
+
}
|
|
662
|
+
const adminDataSource = new typeorm_2.DataSource({
|
|
663
|
+
...dataSource.options,
|
|
664
|
+
database: this.resolvePostgresMaintenanceDatabase(dataSource),
|
|
665
|
+
name: `${String(dataSource.name ?? 'default')}_teardown_admin_${Date.now()}`,
|
|
666
|
+
synchronize: false,
|
|
667
|
+
migrationsRun: false,
|
|
668
|
+
entities: [],
|
|
669
|
+
subscribers: [],
|
|
670
|
+
migrations: [],
|
|
671
|
+
});
|
|
672
|
+
try {
|
|
673
|
+
await adminDataSource.initialize();
|
|
674
|
+
const queryRunner = adminDataSource.createQueryRunner();
|
|
675
|
+
try {
|
|
676
|
+
await queryRunner.query(`SELECT pg_terminate_backend(pid)
|
|
677
|
+
FROM pg_stat_activity
|
|
678
|
+
WHERE datname = $1
|
|
679
|
+
AND pid <> pg_backend_pid()`, [dbName]);
|
|
680
|
+
await queryRunner.query(`DROP DATABASE IF EXISTS "${dbName}"`);
|
|
622
681
|
}
|
|
623
682
|
finally {
|
|
624
683
|
await queryRunner.release();
|
|
625
684
|
}
|
|
626
685
|
}
|
|
686
|
+
finally {
|
|
687
|
+
if (adminDataSource.isInitialized) {
|
|
688
|
+
await adminDataSource.destroy();
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
resolvePostgresMaintenanceDatabase(dataSource) {
|
|
693
|
+
const configured = process.env.POSTGRES_MAINTENANCE_DATABASE?.trim();
|
|
694
|
+
if (configured) {
|
|
695
|
+
return configured;
|
|
696
|
+
}
|
|
697
|
+
const currentDb = String(dataSource.options?.database ?? '').trim();
|
|
698
|
+
if (currentDb && currentDb !== 'postgres') {
|
|
699
|
+
return 'postgres';
|
|
700
|
+
}
|
|
701
|
+
return 'template1';
|
|
627
702
|
}
|
|
628
703
|
async dropMssqlSchema(queryRunner, schemaName) {
|
|
629
704
|
const foreignKeys = await queryRunner.query(`SELECT fk.name AS fk_name, t.name AS table_name
|
|
@@ -646,6 +721,7 @@ let ModuleTestDataService = ModuleTestDataService_1 = class ModuleTestDataServic
|
|
|
646
721
|
}
|
|
647
722
|
};
|
|
648
723
|
exports.ModuleTestDataService = ModuleTestDataService;
|
|
724
|
+
ModuleTestDataService.TEARDOWN_RETRY_ATTEMPTS = 5;
|
|
649
725
|
exports.ModuleTestDataService = ModuleTestDataService = ModuleTestDataService_1 = __decorate([
|
|
650
726
|
(0, common_1.Injectable)(),
|
|
651
727
|
__metadata("design:paramtypes", [core_1.ModuleRef,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-test-data.service.js","sourceRoot":"","sources":["../../src/seeders/module-test-data.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,uCAA2D;AAC3D,6CAAqD;AACrD,4DAAoD;AACpD,qCAAoD;AACpD,uCAAyB;AACzB,2CAA6B;AAE7B,oGAAqE;AAGrE,mHAA+F;AAC/F,4DAAiF;AACjF,8DAA2D;AAC3D,qEAAkE;AAClE,iGAA6F;AAC7F,+EAA4E;AAC5E,+EAA2E;AAC3E,6EAAyE;AACzE,2DAAwD;AACxD,6EAA6E;AAItE,IAAM,qBAAqB,6BAA3B,MAAM,qBAAqB;IAGhC,YACmB,SAAoB,EACpB,gBAAkC,EAClC,aAA4B;QAF5B,cAAS,GAAT,SAAS,CAAW;QACpB,qBAAgB,GAAhB,gBAAgB,CAAkB;QAClC,kBAAa,GAAb,aAAa,CAAe;QAL9B,WAAM,GAAG,IAAI,eAAM,CAAC,uBAAqB,CAAC,IAAI,CAAC,CAAC;IAM9D,CAAC;IAEJ,KAAK,CAAC,aAAa,CAAC,aAAwB;QAC1C,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;QACzC,MAAM,aAAa,GAAG,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;QAEhJ,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;YACxE,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;YACnE,OAAO;QACT,CAAC;QAED,KAAK,MAAM,eAAe,IAAI,aAAa,EAAE,CAAC;YAC5C,MAAM,UAAU,GAAG,eAAe,EAAE,cAAc,EAAE,IAAI,IAAI,SAAS,CAAC;YACtE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,oCAAoC,UAAU,EAAE,CAAC,CAAC;YAClE,OAAO,CAAC,GAAG,CAAC,oCAAoC,UAAU,EAAE,CAAC,CAAC;YAC9D,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,0CAA0C,UAAU,EAAE,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAED,KAAK,CAAC,qBAAqB;QACzB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,uBAAuB,CAAC,CAAC;QACvE,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC,0EAA0E,CAAC,CAAC;YACxF,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;QACjD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,+BAA+B,OAAO,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,eAAe,GAAG,IAAI,CAAC,aAAa;aACvC,uBAAuB,EAAE;aACzB,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;aAC5C,MAAM,CAAC,OAAO,CAAC;aACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAa,CAAC;QAEjD,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;QAC3F,CAAC;QAED,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAkB,CAAC;QACrD,KAAK,MAAM,MAAM,IAAI,eAAe,EAAE,CAAC;YACrC,kBAAkB,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,MAAM,IAAI,SAAS,IAAI,SAAS,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,oBAAoB,CAC9C,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,EACjC,kBAAkB,CACnB,CAAC;QAEF,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,eAAe,SAAS,EAAE,CAAC,CAAC;QAC3E,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QACxC,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,iDAAiD,CAAC,CAAC;QAEhH,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC;QAElE,MAAM,IAAI,CAAC,yBAAyB,CAAC,kBAAkB,CAAC,CAAC;QAEzD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,CAAC;aACpD,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,KAAK,MAAM,KAAK,MAAM,EAAE,CAAC;aACnD,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,MAAM,YAAY,GAAG;YACnB,EAAE;YACF,8DAA8D;YAC9D,uCAAuC;YACvC,8DAA8D;YAC9D,gBAAgB,SAAS,EAAE;YAC3B,kBAAkB,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE;YAChD,EAAE;YACF,mCAAmC;YACnC,MAAM,IAAI,UAAU;YACpB,EAAE;YACF,eAAe;YACf,oDAAoD;YACpD,8BAA8B;YAC9B,kDAAkD;YAClD,8DAA8D;YAC9D,EAAE;SACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEb,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,qBAAqB;QACzB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,uBAAuB,CAAC,CAAC;QACvE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YACjC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;YACtE,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;YAClE,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAEjE,CAAC;QACF,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;YAC5B,OAAO;QACT,CAAC;QAED,MAAM,aAAa,GAAG,QAAQ;aAC3B,KAAK,EAAE;aACP,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACb,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,IAAI,EAAE,CAAC;YAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,IAAI,EAAE,CAAC;YAC1C,OAAO,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC1C,CAAC,CAAC;aACD,GAAG,EAAE,CAAC;QACT,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,eAAe,aAAa,EAAE,CAAC,CAAC;YAC/E,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;gBACjC,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;gBACjE,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;gBACnE,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QAED,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,WAAW,GAAG,QAAQ,OAAO,EAAE,CAAC;YACtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;YACtD,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3B,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QAED,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,SAAS,IAAI,EAAE,CAAC;YACjD,MAAM,IAAI,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC;QAChD,CAAC;QAED,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,2EAA2E,CAAC,CAAC;IAC3F,CAAC;IAED,IAAY,aAAa;QACvB,MAAM,sBAAsB,GAAG,eAAe,CAAC,kCAAiB,CAAC,CAAC;QAClE,MAAM,aAAa,GAAG,CAAC,sBAAsB,CAAC,CAAC;QAC/C,MAAM,cAAc,GAAG,IAAA,oDAAoC,GAAE,CAAC;QAC9D,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;YAC3C,MAAM,qBAAqB,GAAG,mBAAmB,aAAa,IAAI,aAAa,gBAAgB,CAAC;YAChG,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,qBAAqB,CAAC,CAAC;YAEjE,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;gBACvE,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QAED,OAAO,aAAa,CAAC;IACvB,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,eAAoB;QAC7C,MAAM,cAAc,GAA4B,eAAe,CAAC,cAAc,CAAC;QAC/E,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,CAAC;QAID,MAAM,YAAY,GAAsB,eAAe,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC;QAC9E,MAAM,YAAY,GAAsB,eAAe,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC;QAC9E,MAAM,WAAW,GAA+D,eAAe,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC;QAErH,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QACzC,CAAC;QAED,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;YACnE,OAAO;QACT,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,GAAG,CAC1B,CAAC,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAC9D,CAAC;QAEF,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;YAChC,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;YACxC,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAChD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,iDAAiD,YAAY,EAAE,CAAC,CAAC;YACnF,CAAC;YAED,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;YACxD,MAAM,OAAO,GAAwB,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;YAE/D,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;gBAC1C,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,KAAK,CAAC,YAAY,KAAK,aAAa,EAAE,CAAC;oBACtE,MAAM,WAAW,GAAG,GAAG,KAAK,CAAC,IAAI,SAAS,CAAC;oBAC3C,IAAI,CAAC,CAAC,WAAW,IAAI,OAAO,CAAC,EAAE,CAAC;wBAC9B,SAAS;oBACX,CAAC;oBAED,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;oBAC1C,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,KAAK,EAAE,EAAE,CAAC;wBAC/E,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC;wBAC5B,SAAS;oBACX,CAAC;oBAED,MAAM,WAAW,GAAG,KAAK,CAAC,2BAA2B,CAAC;oBACtD,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;oBACtE,IAAI,CAAC,UAAU,EAAE,CAAC;wBAChB,MAAM,IAAI,KAAK,CAAC,4BAA4B,WAAW,4DAA4D,QAAQ,CAAC,YAAY,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;oBAC5J,CAAC;oBACD,MAAM,cAAc,GAAG,UAAU,CAAC,mBAAmB,CAAC;oBACtD,IAAI,CAAC,cAAc,EAAE,CAAC;wBACpB,MAAM,IAAI,KAAK,CAAC,4BAA4B,WAAW,qEAAqE,QAAQ,CAAC,YAAY,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;oBACrK,CAAC;oBAED,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;oBACnD,MAAM,OAAO,GAAG,OAAO,MAAM,CAAC,gBAAgB,KAAK,UAAU;wBAC3D,CAAC,CAAC,MAAM,MAAM,CAAC,gBAAgB,CAAC,YAAY,CAAC;wBAC7C,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;oBACxE,IAAI,CAAC,OAAO,EAAE,CAAC;wBACb,MAAM,IAAI,KAAK,CAAC,iCAAiC,WAAW,IAAI,cAAc,IAAI,YAAY,EAAE,CAAC,CAAC;oBACpG,CAAC;oBAED,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;oBAC9B,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;YAGD,MAAM,YAAY,GAA2B,EAAE,CAAC;YAChD,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;gBAC1C,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;oBAC1G,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAW,CAAC;oBACzD,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC7B,CAAC;YACH,CAAC;YAGD,MAAM,oBAAoB,GAA8C,EAAE,CAAC;YAC3E,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;gBAC1C,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;oBAAE,SAAS;gBACxC,IAAI,KAAK,CAAC,YAAY,KAAK,cAAc,IAAI,KAAK,CAAC,YAAY,KAAK,aAAa;oBAAE,SAAS;gBAE5F,MAAM,YAAY,GAAG,GAAG,KAAK,CAAC,IAAI,UAAU,CAAC;gBAC7C,IAAI,YAAY,IAAI,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;oBACpE,oBAAoB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;oBACtE,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC;gBAC/B,CAAC;gBAED,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC7B,CAAC;YAGD,IAAI,WAAgB,CAAC;YACrB,MAAM,YAAY,GAAG,QAAQ,CAAC,mBAAmB,CAAC;YAClD,IAAI,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC,KAAK,SAAS,EAAE,CAAC;gBACxD,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC;oBACxC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE;iBACjD,CAAC,CAAC;gBACH,IAAI,QAAQ,EAAE,CAAC;oBACb,WAAW,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;gBAC3E,CAAC;qBAAM,CAAC;oBACN,WAAW,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;gBAClE,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,WAAW,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;YAClE,CAAC;YAED,IAAI,oBAAoB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpC,MAAM,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,EAAE,EAAE,YAAY,EAAE,oBAAoB,EAAE,YAAY,CAAC,CAAC;YAClG,CAAC;YAED,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzC,MAAM,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,EAAE,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,KAAwB;QAClD,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,2CAAmB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/E,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;QACjF,CAAC;QAED,MAAM,WAAW,CAAC,sBAAsB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAU,CAAA,CAAC,CAAC,CAAC;QAEtF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC;YACrC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAEjC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;gBACjC,MAAM,WAAW,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,uCAAuC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;gBACrE,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;YACzD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,IAAI,kEAAkE,CAAC,CAAC;gBAC5G,SAAS;YACX,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,WAAW,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YAC9D,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,MAAM,IAAI,KAAK,CACb,4CAA4C,IAAI,CAAC,IAAI,MAAM,GAAG,EAAE,OAAO,IAAI,GAAG,IAAI;oBAClF,0EAA0E,CAC3E,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,QAAQ,CAAC,MAAM,8BAA8B,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,qBAAqB,CAAC,WAAqB;QACvD,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,6DAA4B,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3F,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,oFAAoF,CAAC,CAAC;QACxG,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;QAChC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;YAChC,IAAI,CAAC,KAAK;gBAAE,SAAS;YACrB,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACpC,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,cAAc,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,CAAC;YACnD,KAAK,MAAM,CAAC,IAAI,cAAc,EAAE,CAAC;gBAC/B,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;oBACzD,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBACpB,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,KAAwB;QAClD,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,0BAAW,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACvE,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,8CAAqB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACjF,IAAI,CAAC,WAAW,IAAI,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;QACjG,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACpE,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,IAAI,CAAC,QAAQ,qCAAqC,CAAC,CAAC;gBACpF,SAAS;YACX,CAAC;YAED,MAAM,WAAW,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;YACtC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,sBAAsB,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,gBAAgB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/H,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAC9B,QAAgB,EAChB,YAAoB,EACpB,SAAoD,EACpD,YAAiD;QAEjD,KAAK,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,SAAS,EAAE,CAAC;YAC5C,IAAI,CAAC,QAAQ,CAAC,MAAM;gBAAE,SAAS;YAE/B,MAAM,WAAW,GAAG,KAAK,CAAC,2BAA2B,CAAC;YACtD,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACjD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,mBAAmB,WAAW,qCAAqC,YAAY,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACnH,CAAC;YACD,MAAM,cAAc,GAAG,UAAU,CAAC,mBAAmB,CAAC;YACtD,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,mBAAmB,WAAW,uDAAuD,YAAY,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACrI,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACnD,MAAM,WAAW,GAAa,EAAE,CAAC;YACjC,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAC1B,MAAM,OAAO,GAAG,OAAO,MAAM,CAAC,gBAAgB,KAAK,UAAU;oBAC3D,CAAC,CAAC,MAAM,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC;oBACnC,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;gBAC9D,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,MAAM,IAAI,KAAK,CAAC,6BAA6B,WAAW,IAAI,cAAc,IAAI,EAAE,EAAE,CAAC,CAAC;gBACtF,CAAC;gBACD,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC/B,CAAC;YAGD,MAAM,eAAe,GAAU,MAAM,IAAI,CAAC,aAAa;iBACpD,kBAAkB,EAAE;iBACpB,QAAQ,CAAC,IAAA,wBAAQ,EAAC,YAAY,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC;iBAC5C,EAAE,CAAC,QAAQ,CAAC;iBACZ,QAAQ,EAAE,CAAC;YACd,MAAM,WAAW,GAAa,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAE/D,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;YACpE,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;YAEvE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5C,MAAM,IAAI,CAAC,aAAa;qBACrB,kBAAkB,EAAE;qBACpB,QAAQ,CAAC,IAAA,wBAAQ,EAAC,YAAY,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC;qBAC5C,EAAE,CAAC,QAAQ,CAAC;qBACZ,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YACnC,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,KAAK,CAAC,YAAY,aAAa,YAAY,IAAI,KAAK,CAAC,IAAI,aAAa,QAAQ,MAAM,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACtJ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,eAAe,CAC3B,QAAgB,EAChB,YAAoB,EACpB,YAAoC;QAEpC,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC;QAC/D,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;QACtF,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,qBAAqB,CAAC,YAAY,EAAE;YACxF,MAAM,EAAE;gBACN,KAAK,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;gBAC7B,oBAAoB,EAAE,IAAI;aAC3B;SACF,CAAC,CAAC;QAEH,KAAK,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YACjE,IAAI,CAAC,QAAQ;gBAAE,SAAS;YAExB,MAAM,aAAa,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;YAC7E,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,gBAAgB,SAAS,4CAA4C,YAAY,EAAE,CAAC,CAAC;YACvG,CAAC;YACD,IAAI,CAAC,aAAa,CAAC,oBAAoB,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,gBAAgB,SAAS,cAAc,YAAY,qCAAqC,CAAC,CAAC;YAC5G,CAAC;YAED,MAAM,mBAAmB,GAAG,aAAa,CAAC,oBAAoB,CAAC,IAAgC,CAAC;YAChG,IAAI,mBAAmB,KAAK,qEAAwB,CAAC,UAAU,EAAE,CAAC;gBAChE,MAAM,IAAI,KAAK,CAAC,+DAA+D,SAAS,WAAW,mBAAmB,IAAI,CAAC,CAAC;YAC9H,CAAC;YAGD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,0CAA0C,CACpF,QAAQ,EAAE,aAAa,CAAC,EAAE,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,CACnD,CAAC;YACF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,YAAY,IAAI,SAAS,aAAa,QAAQ,YAAY,CAAC,CAAC;gBAC1G,SAAS;YACX,CAAC;YAED,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;YACtD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,8BAA8B,UAAU,EAAE,CAAC,CAAC;YAC9D,CAAC;YAED,MAAM,eAAe,GAAG,MAAM,IAAA,+CAAuB,EAAC,IAAI,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;YAC3F,MAAM,MAAM,GAAG,EAAE,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;YAC/C,MAAM,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,aAAa,CAAC,CAAC;YAC1F,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,YAAY,IAAI,SAAS,aAAa,QAAQ,SAAS,QAAQ,EAAE,CAAC,CAAC;QAC3G,CAAC;IACH,CAAC;IAED,IAAY,aAAa;QACvB,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,uBAAa,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,IAAY,oBAAoB;QAC9B,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,6CAAoB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,IAAY,eAAe;QACzB,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,kCAAe,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAChE,CAAC;IAEO,iBAAiB,CAAC,YAAoB;QAC5C,MAAM,QAAQ,GAAG,GAAG,IAAA,wBAAQ,EAAC,YAAY,CAAC,YAAY,CAAC;QACvD,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE,CAAC;QACvD,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QACzE,MAAM,IAAI,GAAG,OAAO,EAAE,QAAQ,CAAC;QAC/B,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAe,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;YACxE,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;QAET,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,kCAAkC,YAAY,wBAAwB,QAAQ,EAAE,CAAC,CAAC;IACpG,CAAC;IAEO,iBAAiB;QACvB,MAAM,UAAU,GAAG;YACjB,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ;YAC/F,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;SACvF,CAAC;QACF,MAAM,OAAO,GAAG;YACd,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ;YACvF,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM;SAC/F,CAAC;QACF,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5E,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QACnE,OAAO,GAAG,SAAS,IAAI,MAAM,EAAE,CAAC;IAClC,CAAC;IAEO,YAAY;QAClB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACjE,OAAO,GAAG,GAAG,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC;IACrJ,CAAC;IAEO,oBAAoB,CAAC,OAAe,EAAE,kBAAuC;QACnF,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACzE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO,KAAK;aACT,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACZ,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClE,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACjC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBACpC,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;YAChE,MAAM,iBAAiB,GAAG,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;YACxF,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBACvB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;YACzD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,GAAG,GAAG,IAAI,MAAM,EAAE,CAAC;QAC5B,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,yBAAyB,CAAC,kBAAuC;QAC7E,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,kBAAkB,CAAC,OAAO,EAAE,EAAE,CAAC;YAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;YACxD,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC;gBAC9B,MAAM,UAAU,CAAC,UAAU,EAAE,CAAC;YAChC,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,kCAAkC,MAAM,oBAAoB,MAAM,MAAM,CAAC,CAAC;YAEtF,MAAM,WAAW,GAAG,UAAU,CAAC,iBAAiB,EAAE,CAAC;YACnD,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC;gBACrC,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;oBACxB,MAAM,WAAW,CAAC,KAAK,CAAC,oBAAoB,MAAM,GAAG,CAAC,CAAC;gBACzD,CAAC;qBAAM,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;oBAC5B,MAAM,WAAW,CAAC,KAAK,CACrB,0DAA0D,MAAM,2BAA2B,MAAM,KAAK,CACvG,CAAC;gBACJ,CAAC;qBAAM,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;oBAClD,MAAM,WAAW,CAAC,KAAK,CAAC,mCAAmC,MAAM,IAAI,CAAC,CAAC;gBACzE,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,KAAK,CAAC,qDAAqD,IAAI,EAAE,CAAC,CAAC;gBAC/E,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,MAAM,WAAW,CAAC,OAAO,EAAE,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAEO,uBAAuB,CAAC,cAAsB;QACpD,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,CAAC,IAAA,4BAAkB,EAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAA,4BAAkB,GAAE,CAAC;QACzF,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAa,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;YACpE,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,MAAM,IAAI,KAAK,CAAC,4BAA4B,cAAc,GAAG,CAAC,CAAC;YACjE,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,iCAAiC,cAAc,MAAM,GAAG,EAAE,OAAO,IAAI,GAAG,EAAE,CAAC,CAAC;QAC9F,CAAC;IACH,CAAC;IAEO,kBAAkB,CACxB,SAAiB,EACjB,SAAiB,EACjB,kBAAuC;QAEvC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,uBAAuB,CAAC,CAAC;QACvE,IAAI,QAAQ,GAAwB,EAAE,CAAC;QACvC,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;gBAClE,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;oBACzC,QAAQ,GAAG,MAAM,CAAC;gBACpB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;YAET,CAAC;QACH,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACxD,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAC;QACrB,CAAC;QAED,MAAM,SAAS,GAA2B,EAAE,CAAC;QAC7C,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,kBAAkB,CAAC,OAAO,EAAE,EAAE,CAAC;YAC5D,SAAS,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;QAC7B,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG;YACzB,SAAS,EAAE,SAAS;YACpB,SAAS;SACV,CAAC;QAEF,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACpE,CAAC;IAEO,KAAK,CAAC,uBAAuB,CAAC,SAAiC;QACrE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC1C,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACvC,MAAM,UAAU,GAAG,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;YACxD,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC;gBAC9B,MAAM,UAAU,CAAC,UAAU,EAAE,CAAC;YAChC,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,kCAAkC,MAAM,oBAAoB,MAAM,MAAM,CAAC,CAAC;YAEtF,MAAM,WAAW,GAAG,UAAU,CAAC,iBAAiB,EAAE,CAAC;YACnD,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC;gBACrC,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;oBACxB,MAAM,WAAW,CAAC,KAAK,CAAC,4BAA4B,MAAM,GAAG,CAAC,CAAC;gBACjE,CAAC;qBAAM,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;oBAC5B,MAAM,IAAI,CAAC,eAAe,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;gBAClD,CAAC;qBAAM,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;oBAClD,MAAM,WAAW,CAAC,KAAK,CAAC,6BAA6B,MAAM,IAAI,CAAC,CAAC;gBACnE,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,KAAK,CAAC,qDAAqD,IAAI,EAAE,CAAC,CAAC;gBAC/E,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,MAAM,WAAW,CAAC,OAAO,EAAE,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,eAAe,CAAC,WAAwD,EAAE,UAAkB;QACxG,MAAM,WAAW,GAAmD,MAAM,WAAW,CAAC,KAAK,CACzF;;;;yBAImB,UAAU,GAAG,CACjC,CAAC;QACF,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;YAC7B,MAAM,WAAW,CAAC,KAAK,CAAC,gBAAgB,UAAU,MAAM,EAAE,CAAC,UAAU,sBAAsB,EAAE,CAAC,OAAO,GAAG,CAAC,CAAC;QAC5G,CAAC;QAED,MAAM,MAAM,GAAkC,MAAM,WAAW,CAAC,KAAK,CACnE,0EAA0E,UAAU,GAAG,CACxF,CAAC;QACF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,WAAW,CAAC,KAAK,CAAC,eAAe,UAAU,MAAM,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC;QAC9E,CAAC;QAED,MAAM,KAAK,GAAkC,MAAM,WAAW,CAAC,KAAK,CAClE,yEAAyE,UAAU,GAAG,CACvF,CAAC;QACF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,WAAW,CAAC,KAAK,CAAC,cAAc,UAAU,MAAM,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QAC5E,CAAC;QAED,MAAM,WAAW,CAAC,KAAK,CAAC,gBAAgB,UAAU,GAAG,CAAC,CAAC;IACzD,CAAC;CACF,CAAA;AAxrBY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,mBAAU,GAAE;qCAKmB,gBAAS;QACF,uBAAgB;QACnB,8BAAa;GANpC,qBAAqB,CAwrBjC","sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\nimport { DiscoveryService, ModuleRef } from '@nestjs/core';\nimport { getDataSourceToken } from '@nestjs/typeorm';\nimport { classify } from '../helpers/string.helper';\nimport { DataSource, EntityManager } from 'typeorm';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport solidCoreMetadata from './seed-data/solid-core-metadata.json';\nimport { CreateModuleMetadataDto } from 'src/dtos/create-module-metadata.dto';\nimport { CreateModelMetadataDto } from 'src/dtos/create-model-metadata.dto';\nimport { MediaStorageProviderType } from 'src/dtos/create-media-storage-provider-metadata.dto';\nimport { getDynamicModuleNamesBasedOnMetadata } from 'src/helpers/module.helper';\nimport { SolidRegistry } from 'src/helpers/solid-registry';\nimport { MediaRepository } from 'src/repository/media.repository';\nimport { PermissionMetadataRepository } from 'src/repository/permission-metadata.repository';\nimport { AuthenticationService } from 'src/services/authentication.service';\nimport { ModelMetadataService } from 'src/services/model-metadata.service';\nimport { RoleMetadataService } from 'src/services/role-metadata.service';\nimport { UserService } from 'src/services/user.service';\nimport { getMediaStorageProvider } from 'src/services/mediaStorageProviders';\nimport { TestingRoleSpec, TestingUserSpec } from 'src/testing/contracts/testing-metadata.types';\n\n@Injectable()\nexport class ModuleTestDataService {\n private readonly logger = new Logger(ModuleTestDataService.name);\n\n constructor(\n private readonly moduleRef: ModuleRef,\n private readonly discoveryService: DiscoveryService,\n private readonly solidRegistry: SolidRegistry,\n ) {}\n\n async setupTestData(modulesToTest?: string[]): Promise<void> {\n const testDataFiles = this.testDataFiles;\n const filteredFiles = modulesToTest?.length ? testDataFiles.filter((file) => modulesToTest.includes(file.moduleMetadata?.name)) : testDataFiles;\n\n if (filteredFiles.length === 0) {\n this.logger.warn('No modules matched the provided modulesToTest list.');\n console.log('No modules matched the provided modulesToTest list.');\n return;\n }\n\n for (const overallMetadata of filteredFiles) {\n const moduleName = overallMetadata?.moduleMetadata?.name ?? 'unknown';\n this.logger.log(`Processing test data for module: ${moduleName}`);\n console.log(`Processing test data for module: ${moduleName}`);\n await this.seedTestData(overallMetadata);\n console.log(`✔ Test data setup complete for module: ${moduleName}`);\n }\n }\n\n async createTestDatasources(): Promise<void> {\n const manifestPath = path.join(process.cwd(), '.solidx-test-manifest');\n if (fs.existsSync(manifestPath)) {\n console.log('Existing .solidx-test-manifest found; skipping test datasource creation.');\n return;\n }\n\n const dbRunName = this.generateDbRunName();\n const timestamp = this.getTimestamp();\n const envPath = path.join(process.cwd(), '.env');\n if (!fs.existsSync(envPath)) {\n throw new Error(`Base .env file not found at ${envPath}`);\n }\n\n const datasourceNames = this.solidRegistry\n .getSolidDatabaseModules()\n .map((wrapper) => wrapper.instance?.name?.())\n .filter(Boolean)\n .map((name) => name.toLowerCase()) as string[];\n\n if (datasourceNames.length === 0) {\n throw new Error('No solid database modules registered; cannot create test datasources.');\n }\n\n const dbNameByDatasource = new Map<string, string>();\n for (const dsName of datasourceNames) {\n dbNameByDatasource.set(dsName, `${dsName}_${timestamp}_${dbRunName}`);\n }\n\n const newEnvContents = this.buildTestEnvContents(\n fs.readFileSync(envPath, 'utf-8'),\n dbNameByDatasource,\n );\n\n const backupEnvPath = path.join(process.cwd(), `.env.backup.${dbRunName}`);\n fs.copyFileSync(envPath, backupEnvPath);\n fs.writeFileSync(envPath, newEnvContents);\n console.log(`Backed up .env to ${path.basename(backupEnvPath)} and applied new test datasource names to .env.`);\n\n this.updateTestManifest(dbRunName, timestamp, dbNameByDatasource);\n\n await this.createTestDatabaseObjects(dbNameByDatasource);\n\n const dbList = Array.from(dbNameByDatasource.entries())\n .map(([dsName, dbName]) => `- ${dsName}: ${dbName}`)\n .join('\\n');\n\n const instructions = [\n '',\n '============================================================',\n ' TEST DATASOURCE ENVIRONMENT CREATED',\n '------------------------------------------------------------',\n ` Run name : ${dbRunName}`,\n ` Env backup : ${path.basename(backupEnvPath)}`,\n '',\n ' Test databases/schemas created:',\n dbList || ' (none)',\n '',\n ' Next steps:',\n ' 1) Using updated .env with test datasource names',\n ' 2) Run solid seed as usual',\n ' 3) Proceed with the next steps in the workflow',\n '============================================================',\n '',\n ].join('\\n');\n\n console.log(instructions);\n }\n\n async deleteTestDatasources(): Promise<void> {\n const manifestPath = path.join(process.cwd(), '.solidx-test-manifest');\n if (!fs.existsSync(manifestPath)) {\n this.logger.log('No .solidx-test-manifest found; nothing to delete.');\n console.log('No .solidx-test-manifest found; nothing to delete.');\n return;\n }\n\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) as {\n runs?: Record<string, { databases?: Record<string, string>; createdAt?: string }>;\n };\n const runs = manifest?.runs ?? {};\n const runNames = Object.keys(runs);\n if (runNames.length === 0) {\n fs.unlinkSync(manifestPath);\n return;\n }\n\n const latestRunName = runNames\n .slice()\n .sort((a, b) => {\n const aCreated = runs[a]?.createdAt ?? '';\n const bCreated = runs[b]?.createdAt ?? '';\n return aCreated.localeCompare(bCreated);\n })\n .pop();\n if (latestRunName) {\n const backupEnvPath = path.join(process.cwd(), `.env.backup.${latestRunName}`);\n if (fs.existsSync(backupEnvPath)) {\n fs.copyFileSync(backupEnvPath, path.join(process.cwd(), '.env'));\n console.log(`Restored .env from ${path.basename(backupEnvPath)}.`);\n fs.unlinkSync(backupEnvPath);\n }\n }\n\n for (const runName of runNames) {\n const envFileName = `.env.${runName}`;\n const envPath = path.join(process.cwd(), envFileName);\n if (fs.existsSync(envPath)) {\n fs.unlinkSync(envPath);\n }\n }\n\n for (const runName of runNames) {\n const databases = runs[runName]?.databases ?? {};\n await this.dropTestDatabaseObjects(databases);\n }\n\n fs.unlinkSync(manifestPath);\n console.log('✔ Test datasource env files and manifest deleted; test databases dropped.');\n }\n\n private get testDataFiles(): any[] {\n const typedSolidCoreMetadata = structuredClone(solidCoreMetadata);\n const testDataFiles = [typedSolidCoreMetadata];\n const enabledModules = getDynamicModuleNamesBasedOnMetadata();\n for (const enabledModule of enabledModules) {\n const enabledModuleSeedFile = `module-metadata/${enabledModule}/${enabledModule}-metadata.json`;\n const fullPath = path.join(process.cwd(), enabledModuleSeedFile);\n\n if (fs.existsSync(fullPath)) {\n const overallMetadata = JSON.parse(fs.readFileSync(fullPath, 'utf-8'));\n testDataFiles.push(overallMetadata);\n }\n }\n\n return testDataFiles;\n }\n\n private async seedTestData(overallMetadata: any): Promise<void> {\n const moduleMetadata: CreateModuleMetadataDto = overallMetadata.moduleMetadata;\n if (!moduleMetadata) {\n throw new Error('Module metadata missing from test data payload.');\n }\n\n // console.log(JSON.stringify(moduleMetadata, null, 2));\n\n const testingRoles: TestingRoleSpec[] = overallMetadata?.testing?.roles ?? [];\n const testingUsers: TestingUserSpec[] = overallMetadata?.testing?.users ?? [];\n const testingData: Array<{ modelUserKey: string; data: Record<string, any> }> = overallMetadata?.testing?.data ?? [];\n\n if (testingRoles.length > 0) {\n await this.seedTestRoles(testingRoles);\n }\n if (testingUsers.length > 0) {\n await this.seedTestUsers(testingUsers);\n }\n\n if (testingData.length === 0) {\n this.logger.debug(`No test data found for ${moduleMetadata.name}`);\n return;\n }\n\n const modelsByName = new Map<string, CreateModelMetadataDto>(\n (moduleMetadata.models ?? []).map((m) => [m.singularName, m]),\n );\n\n for (const entry of testingData) {\n const modelUserKey = entry.modelUserKey;\n const modelDef = modelsByName.get(modelUserKey);\n if (!modelDef) {\n throw new Error(`Test data modelUserKey not found in metadata: ${modelUserKey}`);\n }\n\n const entityRepo = this.resolveRepository(modelUserKey);\n const payload: Record<string, any> = { ...(entry.data ?? {}) };\n\n for (const field of modelDef.fields ?? []) {\n if (field.type === 'relation' && field.relationType === 'many-to-one') {\n const userKeyProp = `${field.name}UserKey`;\n if (!(userKeyProp in payload)) {\n continue;\n }\n\n const userKeyValue = payload[userKeyProp];\n if (userKeyValue === null || userKeyValue === undefined || userKeyValue === '') {\n delete payload[userKeyProp];\n continue;\n }\n\n const coModelName = field.relationCoModelSingularName;\n const coModelDef = coModelName ? modelsByName.get(coModelName) : null;\n if (!coModelDef) {\n throw new Error(`Test data relation model ${coModelName} not found in metadata, when attempting to resolve field ${modelDef.singularName}.${field.name}`);\n }\n const coUserKeyField = coModelDef.userKeyFieldUserKey;\n if (!coUserKeyField) {\n throw new Error(`Test data relation model ${coModelName} is missing userKeyFieldUserKey, when attempting to resolve field ${modelDef.singularName}.${field.name}`);\n }\n\n const coRepo = this.resolveRepository(coModelName);\n const related = typeof coRepo.findOneByUserKey === 'function'\n ? await coRepo.findOneByUserKey(userKeyValue)\n : await coRepo.findOne({ where: { [coUserKeyField]: userKeyValue } });\n if (!related) {\n throw new Error(`Test data relation not found: ${coModelName}.${coUserKeyField}=${userKeyValue}`);\n }\n\n payload[field.name] = related;\n delete payload[userKeyProp];\n }\n }\n\n // Strip media fields from entity payload — file paths cannot be saved as columns\n const mediaPayload: Record<string, string> = {};\n for (const field of modelDef.fields ?? []) {\n if ((field.type === 'mediaSingle' || field.type === 'mediaMultiple') && payload[field.name] !== undefined) {\n mediaPayload[field.name] = payload[field.name] as string;\n delete payload[field.name];\n }\n }\n\n // Strip many-to-many and one-to-many fields — these are resolved post-save via the relation builder\n const multiRelationPayload: Array<{ field: any; userKeys: string[] }> = [];\n for (const field of modelDef.fields ?? []) {\n if (field.type !== 'relation') continue;\n if (field.relationType !== 'many-to-many' && field.relationType !== 'one-to-many') continue;\n\n const userKeysProp = `${field.name}UserKeys`;\n if (userKeysProp in payload && Array.isArray(payload[userKeysProp])) {\n multiRelationPayload.push({ field, userKeys: payload[userKeysProp] });\n delete payload[userKeysProp];\n }\n // Remove raw field value if accidentally present\n delete payload[field.name];\n }\n\n // Upsert entity, capturing the saved result for post-save steps\n let savedEntity: any;\n const userKeyField = modelDef.userKeyFieldUserKey;\n if (userKeyField && payload[userKeyField] !== undefined) {\n const existing = await entityRepo.findOne({\n where: { [userKeyField]: payload[userKeyField] },\n });\n if (existing) {\n savedEntity = await entityRepo.save(entityRepo.merge(existing, payload));\n } else {\n savedEntity = await entityRepo.save(entityRepo.create(payload));\n }\n } else {\n savedEntity = await entityRepo.save(entityRepo.create(payload));\n }\n\n if (multiRelationPayload.length > 0) {\n await this.seedMultiRelations(savedEntity.id, modelUserKey, multiRelationPayload, modelsByName);\n }\n\n if (Object.keys(mediaPayload).length > 0) {\n await this.seedEntityMedia(savedEntity.id, modelUserKey, mediaPayload);\n }\n }\n }\n\n private async seedTestRoles(roles: TestingRoleSpec[]): Promise<void> {\n const roleService = this.moduleRef.get(RoleMetadataService, { strict: false });\n if (!roleService) {\n throw new Error('RoleMetadataService not available — cannot seed test roles.');\n }\n\n await roleService.createRolesIfNotExists(roles.map((r) => ({ name: r.name } as any)));\n\n for (const role of roles) {\n const perms = role.permissions ?? [];\n if (perms.length === 0) continue;\n\n if (perms.some((p) => p === '*')) {\n await roleService.addAllPermissionsToRole(role.name);\n this.logger.log(`Bound all permissions to test role \"${role.name}\"`);\n continue;\n }\n\n const expanded = await this.expandPermissionNames(perms);\n if (expanded.length === 0) {\n this.logger.warn(`Test role \"${role.name}\" has permissions declared but none resolved — skipping binding.`);\n continue;\n }\n\n try {\n await roleService.addPermissionsToRole(role.name, expanded);\n } catch (err: any) {\n throw new Error(\n `Failed to bind permissions to test role \"${role.name}\": ${err?.message ?? err}. ` +\n `Did you run \"solid seed\" first so controller permissions are registered?`,\n );\n }\n this.logger.log(`Bound ${expanded.length} permissions to test role \"${role.name}\"`);\n }\n }\n\n private async expandPermissionNames(permissions: string[]): Promise<string[]> {\n const permissionRepo = this.moduleRef.get(PermissionMetadataRepository, { strict: false });\n if (!permissionRepo) {\n throw new Error('PermissionMetadataRepository not available — cannot resolve test role permissions.');\n }\n\n const exact = new Set<string>();\n const prefixes: string[] = [];\n for (const entry of permissions) {\n if (!entry) continue;\n if (entry.endsWith('.*')) {\n prefixes.push(entry.slice(0, -1));\n } else {\n exact.add(entry);\n }\n }\n\n if (prefixes.length > 0) {\n const allPermissions = await permissionRepo.find();\n for (const p of allPermissions) {\n if (prefixes.some((prefix) => p.name.startsWith(prefix))) {\n exact.add(p.name);\n }\n }\n }\n\n return Array.from(exact);\n }\n\n private async seedTestUsers(users: TestingUserSpec[]): Promise<void> {\n const userService = this.moduleRef.get(UserService, { strict: false });\n const authService = this.moduleRef.get(AuthenticationService, { strict: false });\n if (!userService || !authService) {\n throw new Error('UserService / AuthenticationService not available — cannot seed test users.');\n }\n\n for (const user of users) {\n const existing = await userService.findOneByUsername(user.username);\n if (existing) {\n this.logger.debug(`Test user \"${user.username}\" already exists — skipping signUp.`);\n continue;\n }\n\n await authService.signUp({ ...user });\n this.logger.log(`Created test user \"${user.username}\"${user.roles?.length ? ` with roles [${user.roles.join(', ')}]` : ''}`);\n }\n }\n\n private async seedMultiRelations(\n entityId: number,\n modelUserKey: string,\n relations: Array<{ field: any; userKeys: string[] }>,\n modelsByName: Map<string, CreateModelMetadataDto>,\n ): Promise<void> {\n for (const { field, userKeys } of relations) {\n if (!userKeys.length) continue;\n\n const coModelName = field.relationCoModelSingularName;\n const coModelDef = modelsByName.get(coModelName);\n if (!coModelDef) {\n throw new Error(`Relation model \"${coModelName}\" not found in metadata for field ${modelUserKey}.${field.name}`);\n }\n const coUserKeyField = coModelDef.userKeyFieldUserKey;\n if (!coUserKeyField) {\n throw new Error(`Relation model \"${coModelName}\" is missing userKeyFieldUserKey, needed to resolve ${modelUserKey}.${field.name}`);\n }\n\n const coRepo = this.resolveRepository(coModelName);\n const resolvedIds: number[] = [];\n for (const uk of userKeys) {\n const related = typeof coRepo.findOneByUserKey === 'function'\n ? await coRepo.findOneByUserKey(uk)\n : await coRepo.findOne({ where: { [coUserKeyField]: uk } });\n if (!related) {\n throw new Error(`Related entity not found: ${coModelName}.${coUserKeyField}=${uk}`);\n }\n resolvedIds.push(related.id);\n }\n\n // Load currently associated entities to diff (set semantics — idempotent)\n const existingRelated: any[] = await this.entityManager\n .createQueryBuilder()\n .relation(classify(modelUserKey), field.name)\n .of(entityId)\n .loadMany();\n const existingIds: number[] = existingRelated.map((e) => e.id);\n\n const toAdd = resolvedIds.filter((id) => !existingIds.includes(id));\n const toRemove = existingIds.filter((id) => !resolvedIds.includes(id));\n\n if (toAdd.length > 0 || toRemove.length > 0) {\n await this.entityManager\n .createQueryBuilder()\n .relation(classify(modelUserKey), field.name)\n .of(entityId)\n .addAndRemove(toAdd, toRemove);\n }\n\n this.logger.debug(`Seeded ${field.relationType} relation ${modelUserKey}.${field.name} entityId=${entityId}: +${toAdd.length} -${toRemove.length}`);\n }\n }\n\n private async seedEntityMedia(\n entityId: number,\n modelUserKey: string,\n mediaPayload: Record<string, string>,\n ): Promise<void> {\n const mediaBasePath = process.env.TEST_UPLOADS_MEDIA_FILE_PATH;\n if (!mediaBasePath) {\n throw new Error('TEST_UPLOADS_MEDIA_FILE_PATH is not set. Cannot seed test media.');\n }\n\n const modelMetadata = await this.modelMetadataService.findOneBySingularName(modelUserKey, {\n fields: {\n model: { userKeyField: true },\n mediaStorageProvider: true,\n },\n });\n\n for (const [fieldName, fileName] of Object.entries(mediaPayload)) {\n if (!fileName) continue;\n\n const fieldMetadata = modelMetadata.fields.find((f) => f.name === fieldName);\n if (!fieldMetadata) {\n throw new Error(`Media field \"${fieldName}\" not found in loaded metadata for model ${modelUserKey}`);\n }\n if (!fieldMetadata.mediaStorageProvider) {\n throw new Error(`Media field \"${fieldName}\" in model ${modelUserKey} has no storage provider configured`);\n }\n\n const storageProviderType = fieldMetadata.mediaStorageProvider.type as MediaStorageProviderType;\n if (storageProviderType !== MediaStorageProviderType.Filesystem) {\n throw new Error(`Test media seeding supports filesystem storage only. Field \"${fieldName}\" uses \"${storageProviderType}\".`);\n }\n\n // Idempotency: skip if media already exists for this entity + field\n const existing = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(\n entityId, fieldMetadata.id, fieldMetadata.model.id,\n );\n if (existing.length > 0) {\n this.logger.debug(`Media already seeded for ${modelUserKey}.${fieldName} entityId=${entityId}, skipping`);\n continue;\n }\n\n const sourcePath = path.join(mediaBasePath, fileName);\n if (!fs.existsSync(sourcePath)) {\n throw new Error(`Test media file not found: ${sourcePath}`);\n }\n\n const storageProvider = await getMediaStorageProvider(this.moduleRef, storageProviderType);\n const stream = fs.createReadStream(sourcePath);\n await storageProvider.storeStreams([[stream, fileName]], { id: entityId }, fieldMetadata);\n this.logger.debug(`Seeded media for ${modelUserKey}.${fieldName} entityId=${entityId} file=${fileName}`);\n }\n }\n\n private get entityManager(): EntityManager {\n return this.moduleRef.get(EntityManager, { strict: false });\n }\n\n private get modelMetadataService(): ModelMetadataService {\n return this.moduleRef.get(ModelMetadataService, { strict: false });\n }\n\n private get mediaRepository(): MediaRepository {\n return this.moduleRef.get(MediaRepository, { strict: false });\n }\n\n private resolveRepository(modelUserKey: string): any {\n const repoName = `${classify(modelUserKey)}Repository`;\n const providers = this.discoveryService.getProviders();\n const wrapper = providers.find((provider) => provider.name === repoName);\n const repo = wrapper?.instance;\n if (repo) {\n return repo;\n }\n\n try {\n const resolved = this.moduleRef.get(repoName as any, { strict: false });\n if (resolved) {\n return resolved;\n }\n } catch {\n // fall through\n }\n\n throw new Error(`Repository not found for model ${modelUserKey}. Expected provider: ${repoName}`);\n }\n\n private generateDbRunName(): string {\n const adjectives = [\n 'brave', 'bright', 'calm', 'clever', 'curious', 'gentle', 'jolly', 'lively', 'mighty', 'nimble',\n 'proud', 'quick', 'quiet', 'sharp', 'sly', 'steady', 'swift', 'wise', 'witty', 'zesty',\n ];\n const animals = [\n 'lion', 'tiger', 'panther', 'eagle', 'falcon', 'otter', 'wolf', 'fox', 'bear', 'badger',\n 'monkey', 'panda', 'leopard', 'whale', 'dolphin', 'rhino', 'giraffe', 'camel', 'koala', 'lynx',\n ];\n const adjective = adjectives[Math.floor(Math.random() * adjectives.length)];\n const animal = animals[Math.floor(Math.random() * animals.length)];\n return `${adjective}_${animal}`;\n }\n\n private getTimestamp(): string {\n const now = new Date();\n const pad = (value: number) => value.toString().padStart(2, '0');\n return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;\n }\n\n private buildTestEnvContents(baseEnv: string, dbNameByDatasource: Map<string, string>): string {\n const datasourceNameSet = new Set(Array.from(dbNameByDatasource.keys()));\n const lines = baseEnv.split(/\\r?\\n/);\n return lines\n .map((line) => {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#') || !trimmed.includes('=')) {\n return line;\n }\n const [rawKey] = line.split('=');\n const key = rawKey.trim();\n if (!key.endsWith('_DATABASE_NAME')) {\n return line;\n }\n const prefix = key.replace(/_DATABASE_NAME$/, '').toLowerCase();\n const matchedDatasource = Array.from(datasourceNameSet).find((name) => name === prefix);\n if (!matchedDatasource) {\n return line;\n }\n const dbName = dbNameByDatasource.get(matchedDatasource);\n if (!dbName) {\n return line;\n }\n return `${key}=${dbName}`;\n })\n .join('\\n');\n }\n\n private async createTestDatabaseObjects(dbNameByDatasource: Map<string, string>): Promise<void> {\n for (const [dsName, dbName] of dbNameByDatasource.entries()) {\n const dataSource = this.resolveDataSourceByName(dsName);\n if (!dataSource.isInitialized) {\n await dataSource.initialize();\n }\n\n console.log(`Creating test database/schema \"${dbName}\" on datasource \"${dsName}\"...`);\n\n const queryRunner = dataSource.createQueryRunner();\n try {\n const type = dataSource.options.type;\n if (type === 'postgres') {\n await queryRunner.query(`CREATE DATABASE \"${dbName}\"`);\n } else if (type === 'mssql') {\n await queryRunner.query(\n `IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = '${dbName}') EXEC('CREATE SCHEMA [${dbName}]')`,\n );\n } else if (type === 'mysql' || type === 'mariadb') {\n await queryRunner.query(`CREATE DATABASE IF NOT EXISTS \\`${dbName}\\``);\n } else {\n throw new Error(`Unsupported database type for test data creation: ${type}`);\n }\n } finally {\n await queryRunner.release();\n }\n }\n }\n\n private resolveDataSourceByName(datasourceName: string): DataSource {\n const token = datasourceName ? getDataSourceToken(datasourceName) : getDataSourceToken();\n try {\n const ds = this.moduleRef.get<DataSource>(token, { strict: false });\n if (!ds) {\n throw new Error(`No DataSource found for \"${datasourceName}\"`);\n }\n return ds;\n } catch (err: any) {\n throw new Error(`Failed to resolve DataSource \"${datasourceName}\": ${err?.message ?? err}`);\n }\n }\n\n private updateTestManifest(\n dbRunName: string,\n timestamp: string,\n dbNameByDatasource: Map<string, string>,\n ): void {\n const manifestPath = path.join(process.cwd(), '.solidx-test-manifest');\n let manifest: Record<string, any> = {};\n if (fs.existsSync(manifestPath)) {\n try {\n const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));\n if (parsed && typeof parsed === 'object') {\n manifest = parsed;\n }\n } catch {\n // fall through with empty manifest\n }\n }\n\n if (!manifest.runs || typeof manifest.runs !== 'object') {\n manifest.runs = {};\n }\n\n const databases: Record<string, string> = {};\n for (const [dsName, dbName] of dbNameByDatasource.entries()) {\n databases[dsName] = dbName;\n }\n\n manifest.runs[dbRunName] = {\n createdAt: timestamp,\n databases,\n };\n\n fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));\n }\n\n private async dropTestDatabaseObjects(databases: Record<string, string>): Promise<void> {\n const entries = Object.entries(databases);\n for (const [dsName, dbName] of entries) {\n const dataSource = this.resolveDataSourceByName(dsName);\n if (!dataSource.isInitialized) {\n await dataSource.initialize();\n }\n\n console.log(`Dropping test database/schema \"${dbName}\" on datasource \"${dsName}\"...`);\n\n const queryRunner = dataSource.createQueryRunner();\n try {\n const type = dataSource.options.type;\n if (type === 'postgres') {\n await queryRunner.query(`DROP DATABASE IF EXISTS \"${dbName}\"`);\n } else if (type === 'mssql') {\n await this.dropMssqlSchema(queryRunner, dbName);\n } else if (type === 'mysql' || type === 'mariadb') {\n await queryRunner.query(`DROP DATABASE IF EXISTS \\`${dbName}\\``);\n } else {\n throw new Error(`Unsupported database type for test data deletion: ${type}`);\n }\n } finally {\n await queryRunner.release();\n }\n }\n }\n\n private async dropMssqlSchema(queryRunner: ReturnType<DataSource['createQueryRunner']>, schemaName: string): Promise<void> {\n const foreignKeys: Array<{ fk_name: string; table_name: string }> = await queryRunner.query(\n `SELECT fk.name AS fk_name, t.name AS table_name\n FROM sys.foreign_keys fk\n INNER JOIN sys.tables t ON fk.parent_object_id = t.object_id\n INNER JOIN sys.schemas s ON t.schema_id = s.schema_id\n WHERE s.name = '${schemaName}'`,\n );\n for (const fk of foreignKeys) {\n await queryRunner.query(`ALTER TABLE [${schemaName}].[${fk.table_name}] DROP CONSTRAINT [${fk.fk_name}]`);\n }\n\n const tables: Array<{ TABLE_NAME: string }> = await queryRunner.query(\n `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '${schemaName}'`,\n );\n for (const table of tables) {\n await queryRunner.query(`DROP TABLE [${schemaName}].[${table.TABLE_NAME}]`);\n }\n\n const views: Array<{ TABLE_NAME: string }> = await queryRunner.query(\n `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '${schemaName}'`,\n );\n for (const view of views) {\n await queryRunner.query(`DROP VIEW [${schemaName}].[${view.TABLE_NAME}]`);\n }\n\n await queryRunner.query(`DROP SCHEMA [${schemaName}]`);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"module-test-data.service.js","sourceRoot":"","sources":["../../src/seeders/module-test-data.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\nimport { DiscoveryService, ModuleRef } from '@nestjs/core';\nimport { getDataSourceToken } from '@nestjs/typeorm';\nimport { classify } from '../helpers/string.helper';\nimport { DataSource, EntityManager } from 'typeorm';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport solidCoreMetadata from './seed-data/solid-core-metadata.json';\nimport { CreateModuleMetadataDto } from 'src/dtos/create-module-metadata.dto';\nimport { CreateModelMetadataDto } from 'src/dtos/create-model-metadata.dto';\nimport { MediaStorageProviderType } from 'src/dtos/create-media-storage-provider-metadata.dto';\nimport { getDynamicModuleNamesBasedOnMetadata } from 'src/helpers/module.helper';\nimport { SolidRegistry } from 'src/helpers/solid-registry';\nimport { MediaRepository } from 'src/repository/media.repository';\nimport { PermissionMetadataRepository } from 'src/repository/permission-metadata.repository';\nimport { AuthenticationService } from 'src/services/authentication.service';\nimport { ModelMetadataService } from 'src/services/model-metadata.service';\nimport { RoleMetadataService } from 'src/services/role-metadata.service';\nimport { UserService } from 'src/services/user.service';\nimport { getMediaStorageProvider } from 'src/services/mediaStorageProviders';\nimport { TestingRoleSpec, TestingUserSpec } from 'src/testing/contracts/testing-metadata.types';\n\n@Injectable()\nexport class ModuleTestDataService {\n private readonly logger = new Logger(ModuleTestDataService.name);\n private static readonly TEARDOWN_RETRY_ATTEMPTS = 5;\n\n constructor(\n private readonly moduleRef: ModuleRef,\n private readonly discoveryService: DiscoveryService,\n private readonly solidRegistry: SolidRegistry,\n ) {}\n\n async setupTestData(modulesToTest?: string[]): Promise<void> {\n const testDataFiles = this.testDataFiles;\n const filteredFiles = modulesToTest?.length ? testDataFiles.filter((file) => modulesToTest.includes(file.moduleMetadata?.name)) : testDataFiles;\n\n if (filteredFiles.length === 0) {\n this.logger.warn('No modules matched the provided modulesToTest list.');\n console.log('No modules matched the provided modulesToTest list.');\n return;\n }\n\n for (const overallMetadata of filteredFiles) {\n const moduleName = overallMetadata?.moduleMetadata?.name ?? 'unknown';\n this.logger.log(`Processing test data for module: ${moduleName}`);\n console.log(`Processing test data for module: ${moduleName}`);\n await this.seedTestData(overallMetadata);\n console.log(`✔ Test data setup complete for module: ${moduleName}`);\n }\n }\n\n async createTestDatasources(): Promise<void> {\n const manifestPath = path.join(process.cwd(), '.solidx-test-manifest');\n if (fs.existsSync(manifestPath)) {\n console.log('Existing .solidx-test-manifest found; skipping test datasource creation.');\n return;\n }\n\n const dbRunName = this.generateDbRunName();\n const timestamp = this.getTimestamp();\n const envPath = path.join(process.cwd(), '.env');\n if (!fs.existsSync(envPath)) {\n throw new Error(`Base .env file not found at ${envPath}`);\n }\n\n const datasourceNames = this.solidRegistry\n .getSolidDatabaseModules()\n .map((wrapper) => wrapper.instance?.name?.())\n .filter(Boolean)\n .map((name) => name.toLowerCase()) as string[];\n\n if (datasourceNames.length === 0) {\n throw new Error('No solid database modules registered; cannot create test datasources.');\n }\n\n const dbNameByDatasource = new Map<string, string>();\n for (const dsName of datasourceNames) {\n dbNameByDatasource.set(dsName, `${dsName}_${timestamp}_${dbRunName}`);\n }\n\n const newEnvContents = this.buildTestEnvContents(\n fs.readFileSync(envPath, 'utf-8'),\n dbNameByDatasource,\n );\n\n const backupEnvPath = path.join(process.cwd(), `.env.backup.${dbRunName}`);\n fs.copyFileSync(envPath, backupEnvPath);\n fs.writeFileSync(envPath, newEnvContents);\n console.log(`Backed up .env to ${path.basename(backupEnvPath)} and applied new test datasource names to .env.`);\n\n this.updateTestManifest(dbRunName, timestamp, dbNameByDatasource);\n\n await this.createTestDatabaseObjects(dbNameByDatasource);\n\n const dbList = Array.from(dbNameByDatasource.entries())\n .map(([dsName, dbName]) => `- ${dsName}: ${dbName}`)\n .join('\\n');\n\n const instructions = [\n '',\n '============================================================',\n ' TEST DATASOURCE ENVIRONMENT CREATED',\n '------------------------------------------------------------',\n ` Run name : ${dbRunName}`,\n ` Env backup : ${path.basename(backupEnvPath)}`,\n '',\n ' Test databases/schemas created:',\n dbList || ' (none)',\n '',\n ' Next steps:',\n ' 1) Using updated .env with test datasource names',\n ' 2) Run solid seed as usual',\n ' 3) Proceed with the next steps in the workflow',\n '============================================================',\n '',\n ].join('\\n');\n\n console.log(instructions);\n }\n\n async deleteTestDatasources(): Promise<void> {\n const manifestPath = path.join(process.cwd(), '.solidx-test-manifest');\n if (!fs.existsSync(manifestPath)) {\n this.logger.log('No .solidx-test-manifest found; nothing to delete.');\n console.log('No .solidx-test-manifest found; nothing to delete.');\n return;\n }\n\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) as {\n runs?: Record<string, { databases?: Record<string, string>; createdAt?: string }>;\n };\n const runs = manifest?.runs ?? {};\n const runNames = Object.keys(runs);\n if (runNames.length === 0) {\n fs.unlinkSync(manifestPath);\n return;\n }\n\n const latestRunName = runNames\n .slice()\n .sort((a, b) => {\n const aCreated = runs[a]?.createdAt ?? '';\n const bCreated = runs[b]?.createdAt ?? '';\n return aCreated.localeCompare(bCreated);\n })\n .pop();\n if (latestRunName) {\n const backupEnvPath = path.join(process.cwd(), `.env.backup.${latestRunName}`);\n if (fs.existsSync(backupEnvPath)) {\n fs.copyFileSync(backupEnvPath, path.join(process.cwd(), '.env'));\n console.log(`Restored .env from ${path.basename(backupEnvPath)}.`);\n fs.unlinkSync(backupEnvPath);\n }\n }\n\n for (const runName of runNames) {\n const envFileName = `.env.${runName}`;\n const envPath = path.join(process.cwd(), envFileName);\n if (fs.existsSync(envPath)) {\n fs.unlinkSync(envPath);\n }\n }\n\n for (const runName of runNames) {\n const databases = runs[runName]?.databases ?? {};\n await this.dropTestDatabaseObjects(databases);\n }\n\n fs.unlinkSync(manifestPath);\n console.log('✔ Test datasource env files and manifest deleted; test databases dropped.');\n }\n\n private get testDataFiles(): any[] {\n const typedSolidCoreMetadata = structuredClone(solidCoreMetadata);\n const testDataFiles = [typedSolidCoreMetadata];\n const enabledModules = getDynamicModuleNamesBasedOnMetadata();\n for (const enabledModule of enabledModules) {\n const enabledModuleSeedFile = `module-metadata/${enabledModule}/${enabledModule}-metadata.json`;\n const fullPath = path.join(process.cwd(), enabledModuleSeedFile);\n\n if (fs.existsSync(fullPath)) {\n const overallMetadata = JSON.parse(fs.readFileSync(fullPath, 'utf-8'));\n testDataFiles.push(overallMetadata);\n }\n }\n\n return testDataFiles;\n }\n\n private async seedTestData(overallMetadata: any): Promise<void> {\n const moduleMetadata: CreateModuleMetadataDto = overallMetadata.moduleMetadata;\n if (!moduleMetadata) {\n throw new Error('Module metadata missing from test data payload.');\n }\n\n // console.log(JSON.stringify(moduleMetadata, null, 2));\n\n const testingRoles: TestingRoleSpec[] = overallMetadata?.testing?.roles ?? [];\n const testingUsers: TestingUserSpec[] = overallMetadata?.testing?.users ?? [];\n const testingData: Array<{ modelUserKey: string; data: Record<string, any> }> = overallMetadata?.testing?.data ?? [];\n\n if (testingRoles.length > 0) {\n await this.seedTestRoles(testingRoles);\n }\n if (testingUsers.length > 0) {\n await this.seedTestUsers(testingUsers);\n }\n\n if (testingData.length === 0) {\n this.logger.debug(`No test data found for ${moduleMetadata.name}`);\n return;\n }\n\n const modelsByName = new Map<string, CreateModelMetadataDto>(\n (moduleMetadata.models ?? []).map((m) => [m.singularName, m]),\n );\n\n for (const entry of testingData) {\n const modelUserKey = entry.modelUserKey;\n const modelDef = modelsByName.get(modelUserKey);\n if (!modelDef) {\n throw new Error(`Test data modelUserKey not found in metadata: ${modelUserKey}`);\n }\n\n const entityRepo = this.resolveRepository(modelUserKey);\n const payload: Record<string, any> = { ...(entry.data ?? {}) };\n\n for (const field of modelDef.fields ?? []) {\n if (field.type === 'relation' && field.relationType === 'many-to-one') {\n const userKeyProp = `${field.name}UserKey`;\n if (!(userKeyProp in payload)) {\n continue;\n }\n\n const userKeyValue = payload[userKeyProp];\n if (userKeyValue === null || userKeyValue === undefined || userKeyValue === '') {\n delete payload[userKeyProp];\n continue;\n }\n\n const coModelName = field.relationCoModelSingularName;\n const coModelDef = coModelName ? modelsByName.get(coModelName) : null;\n if (!coModelDef) {\n throw new Error(`Test data relation model ${coModelName} not found in metadata, when attempting to resolve field ${modelDef.singularName}.${field.name}`);\n }\n const coUserKeyField = coModelDef.userKeyFieldUserKey;\n if (!coUserKeyField) {\n throw new Error(`Test data relation model ${coModelName} is missing userKeyFieldUserKey, when attempting to resolve field ${modelDef.singularName}.${field.name}`);\n }\n\n const coRepo = this.resolveRepository(coModelName);\n const related = typeof coRepo.findOneByUserKey === 'function'\n ? await coRepo.findOneByUserKey(userKeyValue)\n : await coRepo.findOne({ where: { [coUserKeyField]: userKeyValue } });\n if (!related) {\n throw new Error(`Test data relation not found: ${coModelName}.${coUserKeyField}=${userKeyValue}`);\n }\n\n payload[field.name] = related;\n delete payload[userKeyProp];\n }\n }\n\n // Strip media fields from entity payload — file paths cannot be saved as columns\n const mediaPayload: Record<string, string> = {};\n for (const field of modelDef.fields ?? []) {\n if ((field.type === 'mediaSingle' || field.type === 'mediaMultiple') && payload[field.name] !== undefined) {\n mediaPayload[field.name] = payload[field.name] as string;\n delete payload[field.name];\n }\n }\n\n // Strip many-to-many and one-to-many fields — these are resolved post-save via the relation builder\n const multiRelationPayload: Array<{ field: any; userKeys: string[] }> = [];\n for (const field of modelDef.fields ?? []) {\n if (field.type !== 'relation') continue;\n if (field.relationType !== 'many-to-many' && field.relationType !== 'one-to-many') continue;\n\n const userKeysProp = `${field.name}UserKeys`;\n if (userKeysProp in payload && Array.isArray(payload[userKeysProp])) {\n multiRelationPayload.push({ field, userKeys: payload[userKeysProp] });\n delete payload[userKeysProp];\n }\n // Remove raw field value if accidentally present\n delete payload[field.name];\n }\n\n // Upsert entity, capturing the saved result for post-save steps\n let savedEntity: any;\n const userKeyField = modelDef.userKeyFieldUserKey;\n if (userKeyField && payload[userKeyField] !== undefined) {\n const existing = await entityRepo.findOne({\n where: { [userKeyField]: payload[userKeyField] },\n });\n if (existing) {\n savedEntity = await entityRepo.save(entityRepo.merge(existing, payload));\n } else {\n savedEntity = await entityRepo.save(entityRepo.create(payload));\n }\n } else {\n savedEntity = await entityRepo.save(entityRepo.create(payload));\n }\n\n if (multiRelationPayload.length > 0) {\n await this.seedMultiRelations(savedEntity.id, modelUserKey, multiRelationPayload, modelsByName);\n }\n\n if (Object.keys(mediaPayload).length > 0) {\n await this.seedEntityMedia(savedEntity.id, modelUserKey, mediaPayload);\n }\n }\n }\n\n private async seedTestRoles(roles: TestingRoleSpec[]): Promise<void> {\n const roleService = this.moduleRef.get(RoleMetadataService, { strict: false });\n if (!roleService) {\n throw new Error('RoleMetadataService not available — cannot seed test roles.');\n }\n\n await roleService.createRolesIfNotExists(roles.map((r) => ({ name: r.name } as any)));\n\n for (const role of roles) {\n const perms = role.permissions ?? [];\n if (perms.length === 0) continue;\n\n if (perms.some((p) => p === '*')) {\n await roleService.addAllPermissionsToRole(role.name);\n this.logger.log(`Bound all permissions to test role \"${role.name}\"`);\n continue;\n }\n\n const expanded = await this.expandPermissionNames(perms);\n if (expanded.length === 0) {\n this.logger.warn(`Test role \"${role.name}\" has permissions declared but none resolved — skipping binding.`);\n continue;\n }\n\n try {\n await roleService.addPermissionsToRole(role.name, expanded);\n } catch (err: any) {\n throw new Error(\n `Failed to bind permissions to test role \"${role.name}\": ${err?.message ?? err}. ` +\n `Did you run \"solid seed\" first so controller permissions are registered?`,\n );\n }\n this.logger.log(`Bound ${expanded.length} permissions to test role \"${role.name}\"`);\n }\n }\n\n private async expandPermissionNames(permissions: string[]): Promise<string[]> {\n const permissionRepo = this.moduleRef.get(PermissionMetadataRepository, { strict: false });\n if (!permissionRepo) {\n throw new Error('PermissionMetadataRepository not available — cannot resolve test role permissions.');\n }\n\n const exact = new Set<string>();\n const prefixes: string[] = [];\n for (const entry of permissions) {\n if (!entry) continue;\n if (entry.endsWith('.*')) {\n prefixes.push(entry.slice(0, -1));\n } else {\n exact.add(entry);\n }\n }\n\n if (prefixes.length > 0) {\n const allPermissions = await permissionRepo.find();\n for (const p of allPermissions) {\n if (prefixes.some((prefix) => p.name.startsWith(prefix))) {\n exact.add(p.name);\n }\n }\n }\n\n return Array.from(exact);\n }\n\n private async seedTestUsers(users: TestingUserSpec[]): Promise<void> {\n const userService = this.moduleRef.get(UserService, { strict: false });\n const authService = this.moduleRef.get(AuthenticationService, { strict: false });\n if (!userService || !authService) {\n throw new Error('UserService / AuthenticationService not available — cannot seed test users.');\n }\n\n for (const user of users) {\n const existing = await userService.findOneByUsername(user.username);\n if (existing) {\n this.logger.debug(`Test user \"${user.username}\" already exists — skipping signUp.`);\n continue;\n }\n\n await authService.signUp({ ...user });\n this.logger.log(`Created test user \"${user.username}\"${user.roles?.length ? ` with roles [${user.roles.join(', ')}]` : ''}`);\n }\n }\n\n private async seedMultiRelations(\n entityId: number,\n modelUserKey: string,\n relations: Array<{ field: any; userKeys: string[] }>,\n modelsByName: Map<string, CreateModelMetadataDto>,\n ): Promise<void> {\n for (const { field, userKeys } of relations) {\n if (!userKeys.length) continue;\n\n const coModelName = field.relationCoModelSingularName;\n const coModelDef = modelsByName.get(coModelName);\n if (!coModelDef) {\n throw new Error(`Relation model \"${coModelName}\" not found in metadata for field ${modelUserKey}.${field.name}`);\n }\n const coUserKeyField = coModelDef.userKeyFieldUserKey;\n if (!coUserKeyField) {\n throw new Error(`Relation model \"${coModelName}\" is missing userKeyFieldUserKey, needed to resolve ${modelUserKey}.${field.name}`);\n }\n\n const coRepo = this.resolveRepository(coModelName);\n const resolvedIds: number[] = [];\n for (const uk of userKeys) {\n const related = typeof coRepo.findOneByUserKey === 'function'\n ? await coRepo.findOneByUserKey(uk)\n : await coRepo.findOne({ where: { [coUserKeyField]: uk } });\n if (!related) {\n throw new Error(`Related entity not found: ${coModelName}.${coUserKeyField}=${uk}`);\n }\n resolvedIds.push(related.id);\n }\n\n // Load currently associated entities to diff (set semantics — idempotent)\n const existingRelated: any[] = await this.entityManager\n .createQueryBuilder()\n .relation(classify(modelUserKey), field.name)\n .of(entityId)\n .loadMany();\n const existingIds: number[] = existingRelated.map((e) => e.id);\n\n const toAdd = resolvedIds.filter((id) => !existingIds.includes(id));\n const toRemove = existingIds.filter((id) => !resolvedIds.includes(id));\n\n if (toAdd.length > 0 || toRemove.length > 0) {\n await this.entityManager\n .createQueryBuilder()\n .relation(classify(modelUserKey), field.name)\n .of(entityId)\n .addAndRemove(toAdd, toRemove);\n }\n\n this.logger.debug(`Seeded ${field.relationType} relation ${modelUserKey}.${field.name} entityId=${entityId}: +${toAdd.length} -${toRemove.length}`);\n }\n }\n\n private async seedEntityMedia(\n entityId: number,\n modelUserKey: string,\n mediaPayload: Record<string, string>,\n ): Promise<void> {\n const mediaBasePath = process.env.TEST_UPLOADS_MEDIA_FILE_PATH;\n if (!mediaBasePath) {\n throw new Error('TEST_UPLOADS_MEDIA_FILE_PATH is not set. Cannot seed test media.');\n }\n\n const modelMetadata = await this.modelMetadataService.findOneBySingularName(modelUserKey, {\n fields: {\n model: { userKeyField: true },\n mediaStorageProvider: true,\n },\n });\n\n for (const [fieldName, fileName] of Object.entries(mediaPayload)) {\n if (!fileName) continue;\n\n const fieldMetadata = modelMetadata.fields.find((f) => f.name === fieldName);\n if (!fieldMetadata) {\n throw new Error(`Media field \"${fieldName}\" not found in loaded metadata for model ${modelUserKey}`);\n }\n if (!fieldMetadata.mediaStorageProvider) {\n throw new Error(`Media field \"${fieldName}\" in model ${modelUserKey} has no storage provider configured`);\n }\n\n const storageProviderType = fieldMetadata.mediaStorageProvider.type as MediaStorageProviderType;\n if (storageProviderType !== MediaStorageProviderType.Filesystem) {\n throw new Error(`Test media seeding supports filesystem storage only. Field \"${fieldName}\" uses \"${storageProviderType}\".`);\n }\n\n // Idempotency: skip if media already exists for this entity + field\n const existing = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(\n entityId, fieldMetadata.id, fieldMetadata.model.id,\n );\n if (existing.length > 0) {\n this.logger.debug(`Media already seeded for ${modelUserKey}.${fieldName} entityId=${entityId}, skipping`);\n continue;\n }\n\n const sourcePath = path.join(mediaBasePath, fileName);\n if (!fs.existsSync(sourcePath)) {\n throw new Error(`Test media file not found: ${sourcePath}`);\n }\n\n const storageProvider = await getMediaStorageProvider(this.moduleRef, storageProviderType);\n const stream = fs.createReadStream(sourcePath);\n await storageProvider.storeStreams([[stream, fileName]], { id: entityId }, fieldMetadata);\n this.logger.debug(`Seeded media for ${modelUserKey}.${fieldName} entityId=${entityId} file=${fileName}`);\n }\n }\n\n private get entityManager(): EntityManager {\n return this.moduleRef.get(EntityManager, { strict: false });\n }\n\n private get modelMetadataService(): ModelMetadataService {\n return this.moduleRef.get(ModelMetadataService, { strict: false });\n }\n\n private get mediaRepository(): MediaRepository {\n return this.moduleRef.get(MediaRepository, { strict: false });\n }\n\n private resolveRepository(modelUserKey: string): any {\n const repoName = `${classify(modelUserKey)}Repository`;\n const providers = this.discoveryService.getProviders();\n const wrapper = providers.find((provider) => provider.name === repoName);\n const repo = wrapper?.instance;\n if (repo) {\n return repo;\n }\n\n try {\n const resolved = this.moduleRef.get(repoName as any, { strict: false });\n if (resolved) {\n return resolved;\n }\n } catch {\n // fall through\n }\n\n throw new Error(`Repository not found for model ${modelUserKey}. Expected provider: ${repoName}`);\n }\n\n private generateDbRunName(): string {\n const adjectives = [\n 'brave', 'bright', 'calm', 'clever', 'curious', 'gentle', 'jolly', 'lively', 'mighty', 'nimble',\n 'proud', 'quick', 'quiet', 'sharp', 'sly', 'steady', 'swift', 'wise', 'witty', 'zesty',\n ];\n const animals = [\n 'lion', 'tiger', 'panther', 'eagle', 'falcon', 'otter', 'wolf', 'fox', 'bear', 'badger',\n 'monkey', 'panda', 'leopard', 'whale', 'dolphin', 'rhino', 'giraffe', 'camel', 'koala', 'lynx',\n ];\n const adjective = adjectives[Math.floor(Math.random() * adjectives.length)];\n const animal = animals[Math.floor(Math.random() * animals.length)];\n return `${adjective}_${animal}`;\n }\n\n private getTimestamp(): string {\n const now = new Date();\n const pad = (value: number) => value.toString().padStart(2, '0');\n return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;\n }\n\n private buildTestEnvContents(baseEnv: string, dbNameByDatasource: Map<string, string>): string {\n const datasourceNameSet = new Set(Array.from(dbNameByDatasource.keys()));\n const lines = baseEnv.split(/\\r?\\n/);\n return lines\n .map((line) => {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#') || !trimmed.includes('=')) {\n return line;\n }\n const [rawKey] = line.split('=');\n const key = rawKey.trim();\n if (!key.endsWith('_DATABASE_NAME')) {\n return line;\n }\n const prefix = key.replace(/_DATABASE_NAME$/, '').toLowerCase();\n const matchedDatasource = Array.from(datasourceNameSet).find((name) => name === prefix);\n if (!matchedDatasource) {\n return line;\n }\n const dbName = dbNameByDatasource.get(matchedDatasource);\n if (!dbName) {\n return line;\n }\n return `${key}=${dbName}`;\n })\n .join('\\n');\n }\n\n private async createTestDatabaseObjects(dbNameByDatasource: Map<string, string>): Promise<void> {\n for (const [dsName, dbName] of dbNameByDatasource.entries()) {\n const dataSource = this.resolveDataSourceByName(dsName);\n if (!dataSource.isInitialized) {\n await dataSource.initialize();\n }\n\n console.log(`Creating test database/schema \"${dbName}\" on datasource \"${dsName}\"...`);\n\n const queryRunner = dataSource.createQueryRunner();\n try {\n const type = dataSource.options.type;\n if (type === 'postgres') {\n await queryRunner.query(`CREATE DATABASE \"${dbName}\"`);\n } else if (type === 'mssql') {\n await queryRunner.query(\n `IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = '${dbName}') EXEC('CREATE SCHEMA [${dbName}]')`,\n );\n } else if (type === 'mysql' || type === 'mariadb') {\n await queryRunner.query(`CREATE DATABASE IF NOT EXISTS \\`${dbName}\\``);\n } else {\n throw new Error(`Unsupported database type for test data creation: ${type}`);\n }\n } finally {\n await queryRunner.release();\n }\n }\n }\n\n private resolveDataSourceByName(datasourceName: string): DataSource {\n const token = datasourceName ? getDataSourceToken(datasourceName) : getDataSourceToken();\n try {\n const ds = this.moduleRef.get<DataSource>(token, { strict: false });\n if (!ds) {\n throw new Error(`No DataSource found for \"${datasourceName}\"`);\n }\n return ds;\n } catch (err: any) {\n throw new Error(`Failed to resolve DataSource \"${datasourceName}\": ${err?.message ?? err}`);\n }\n }\n\n private updateTestManifest(\n dbRunName: string,\n timestamp: string,\n dbNameByDatasource: Map<string, string>,\n ): void {\n const manifestPath = path.join(process.cwd(), '.solidx-test-manifest');\n let manifest: Record<string, any> = {};\n if (fs.existsSync(manifestPath)) {\n try {\n const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));\n if (parsed && typeof parsed === 'object') {\n manifest = parsed;\n }\n } catch {\n // fall through with empty manifest\n }\n }\n\n if (!manifest.runs || typeof manifest.runs !== 'object') {\n manifest.runs = {};\n }\n\n const databases: Record<string, string> = {};\n for (const [dsName, dbName] of dbNameByDatasource.entries()) {\n databases[dsName] = dbName;\n }\n\n manifest.runs[dbRunName] = {\n createdAt: timestamp,\n databases,\n };\n\n fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));\n }\n\n private async dropTestDatabaseObjects(databases: Record<string, string>): Promise<void> {\n const entries = Object.entries(databases);\n for (const [dsName, dbName] of entries) {\n await this.dropTestDatabaseObjectsWithRetry(dsName, dbName);\n }\n }\n\n private async dropTestDatabaseObjectsWithRetry(dsName: string, dbName: string): Promise<void> {\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= ModuleTestDataService.TEARDOWN_RETRY_ATTEMPTS; attempt += 1) {\n console.log(`Attempting to tear down \"${dbName}\" on datasource \"${dsName}\" (${attempt}/${ModuleTestDataService.TEARDOWN_RETRY_ATTEMPTS})...`);\n\n try {\n await this.dropSingleTestDatabaseObject(dsName, dbName);\n return;\n } catch (error) {\n lastError = error;\n if (attempt >= ModuleTestDataService.TEARDOWN_RETRY_ATTEMPTS) {\n throw error;\n }\n\n await this.sleep(this.teardownRetryDelayMs(attempt));\n }\n }\n\n throw lastError instanceof Error ? lastError : new Error(String(lastError));\n }\n\n private teardownRetryDelayMs(attempt: number): number {\n const baseMs = 500;\n const incrementMs = 350;\n const jitterMs = Math.floor(Math.random() * 250);\n return baseMs + ((attempt - 1) * incrementMs) + jitterMs;\n }\n\n private async sleep(ms: number): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n private async dropSingleTestDatabaseObject(dsName: string, dbName: string): Promise<void> {\n const dataSource = this.resolveDataSourceByName(dsName);\n\n if (dataSource.options.type === 'postgres') {\n await this.dropPostgresDatabase(dataSource, dbName);\n return;\n }\n\n if (!dataSource.isInitialized) {\n await dataSource.initialize();\n }\n\n const queryRunner = dataSource.createQueryRunner();\n try {\n const type = dataSource.options.type;\n if (type === 'mssql') {\n await this.dropMssqlSchema(queryRunner, dbName);\n } else if (type === 'mysql' || type === 'mariadb') {\n await queryRunner.query(`DROP DATABASE IF EXISTS \\`${dbName}\\``);\n } else {\n throw new Error(`Unsupported database type for test data deletion: ${type}`);\n }\n } finally {\n await queryRunner.release();\n }\n }\n\n private async dropPostgresDatabase(dataSource: DataSource, dbName: string): Promise<void> {\n if (dataSource.isInitialized) {\n await dataSource.destroy();\n }\n\n const adminDataSource = new DataSource({\n ...(dataSource.options as any),\n database: this.resolvePostgresMaintenanceDatabase(dataSource),\n name: `${String(dataSource.name ?? 'default')}_teardown_admin_${Date.now()}`,\n synchronize: false,\n migrationsRun: false,\n entities: [],\n subscribers: [],\n migrations: [],\n });\n\n try {\n await adminDataSource.initialize();\n const queryRunner = adminDataSource.createQueryRunner();\n try {\n await queryRunner.query(\n `SELECT pg_terminate_backend(pid)\n FROM pg_stat_activity\n WHERE datname = $1\n AND pid <> pg_backend_pid()`,\n [dbName],\n );\n await queryRunner.query(`DROP DATABASE IF EXISTS \"${dbName}\"`);\n } finally {\n await queryRunner.release();\n }\n } finally {\n if (adminDataSource.isInitialized) {\n await adminDataSource.destroy();\n }\n }\n }\n\n private resolvePostgresMaintenanceDatabase(dataSource: DataSource): string {\n const configured = process.env.POSTGRES_MAINTENANCE_DATABASE?.trim();\n if (configured) {\n return configured;\n }\n\n const currentDb = String((dataSource.options as any)?.database ?? '').trim();\n if (currentDb && currentDb !== 'postgres') {\n return 'postgres';\n }\n\n return 'template1';\n }\n\n private async dropMssqlSchema(queryRunner: ReturnType<DataSource['createQueryRunner']>, schemaName: string): Promise<void> {\n const foreignKeys: Array<{ fk_name: string; table_name: string }> = await queryRunner.query(\n `SELECT fk.name AS fk_name, t.name AS table_name\n FROM sys.foreign_keys fk\n INNER JOIN sys.tables t ON fk.parent_object_id = t.object_id\n INNER JOIN sys.schemas s ON t.schema_id = s.schema_id\n WHERE s.name = '${schemaName}'`,\n );\n for (const fk of foreignKeys) {\n await queryRunner.query(`ALTER TABLE [${schemaName}].[${fk.table_name}] DROP CONSTRAINT [${fk.fk_name}]`);\n }\n\n const tables: Array<{ TABLE_NAME: string }> = await queryRunner.query(\n `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '${schemaName}'`,\n );\n for (const table of tables) {\n await queryRunner.query(`DROP TABLE [${schemaName}].[${table.TABLE_NAME}]`);\n }\n\n const views: Array<{ TABLE_NAME: string }> = await queryRunner.query(\n `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '${schemaName}'`,\n );\n for (const view of views) {\n await queryRunner.query(`DROP VIEW [${schemaName}].[${view.TABLE_NAME}]`);\n }\n\n await queryRunner.query(`DROP SCHEMA [${schemaName}]`);\n }\n}\n"]}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { Reporter } from "./reporter.types";
|
|
2
2
|
import type { OpStep } from "../contracts/testing-metadata.types";
|
|
3
3
|
export declare class ConsoleReporter implements Reporter {
|
|
4
|
+
private totalScenarios;
|
|
5
|
+
private passedScenarios;
|
|
6
|
+
private failedScenarios;
|
|
4
7
|
onScenarioStart(scenario: {
|
|
5
8
|
id: string;
|
|
6
9
|
name?: string;
|
|
@@ -41,5 +44,12 @@ export declare class ConsoleReporter implements Reporter {
|
|
|
41
44
|
contentType: string;
|
|
42
45
|
data: Buffer | string;
|
|
43
46
|
}): void;
|
|
47
|
+
onRunEnd(args: {
|
|
48
|
+
ok: boolean;
|
|
49
|
+
total: number;
|
|
50
|
+
passed: number;
|
|
51
|
+
failed: number;
|
|
52
|
+
durationMs: number;
|
|
53
|
+
}): void;
|
|
44
54
|
}
|
|
45
55
|
//# sourceMappingURL=console-reporter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"console-reporter.d.ts","sourceRoot":"","sources":["../../../src/testing/reporter/console-reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAgJlE,qBAAa,eAAgB,YAAW,QAAQ;IAC9C,eAAe,CAAC,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAK9D,aAAa,CACX,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EACvC,MAAM,EAAE;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAC3D,IAAI;
|
|
1
|
+
{"version":3,"file":"console-reporter.d.ts","sourceRoot":"","sources":["../../../src/testing/reporter/console-reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAgJlE,qBAAa,eAAgB,YAAW,QAAQ;IAC9C,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,eAAe,CAAK;IAE5B,eAAe,CAAC,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAK9D,aAAa,CACX,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EACvC,MAAM,EAAE;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAC3D,IAAI;IAYP,WAAW,CAAC,IAAI,EAAE;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,IAAI;IAMR,SAAS,CAAC,IAAI,EAAE;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,OAAO,CAAC;QACZ,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,IAAI;IAwBR,YAAY,CAAC,IAAI,EAAE;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE;YAAE,EAAE,EAAE,OAAO,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;SAAE,CAAC;KACxD,GAAG,IAAI;IAQR,MAAM,CAAC,IAAI,EAAE;QACX,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;KACvB,GAAG,IAAI;IAQR,QAAQ,CAAC,IAAI,EAAE;QACb,EAAE,EAAE,OAAO,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,IAAI;CAUT"}
|
|
@@ -139,6 +139,11 @@ function formatStepLabel(step) {
|
|
|
139
139
|
return `${base} (${details})`;
|
|
140
140
|
}
|
|
141
141
|
class ConsoleReporter {
|
|
142
|
+
constructor() {
|
|
143
|
+
this.totalScenarios = 0;
|
|
144
|
+
this.passedScenarios = 0;
|
|
145
|
+
this.failedScenarios = 0;
|
|
146
|
+
}
|
|
142
147
|
onScenarioStart(scenario) {
|
|
143
148
|
const label = scenario.name ? `${scenario.id} (${scenario.name})` : scenario.id;
|
|
144
149
|
console.log(`\n▶ Scenario: ${label}`);
|
|
@@ -146,6 +151,13 @@ class ConsoleReporter {
|
|
|
146
151
|
onScenarioEnd(scenario, result) {
|
|
147
152
|
const label = scenario.name ? `${scenario.id} (${scenario.name})` : scenario.id;
|
|
148
153
|
const status = result.ok ? "✔" : "✖";
|
|
154
|
+
this.totalScenarios += 1;
|
|
155
|
+
if (result.ok) {
|
|
156
|
+
this.passedScenarios += 1;
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
this.failedScenarios += 1;
|
|
160
|
+
}
|
|
149
161
|
console.log(`${status} Scenario: ${label} (${result.durationMs}ms)`);
|
|
150
162
|
}
|
|
151
163
|
onStepStart(args) {
|
|
@@ -184,6 +196,15 @@ class ConsoleReporter {
|
|
|
184
196
|
return;
|
|
185
197
|
console.log(indentLines(dataText, `${STEP_INDENT}${INDENT}${INDENT}`));
|
|
186
198
|
}
|
|
199
|
+
onRunEnd(args) {
|
|
200
|
+
const durationSeconds = (args.durationMs / 1000).toFixed(2);
|
|
201
|
+
const finalStatus = args.ok ? "PASSED" : "FAILED";
|
|
202
|
+
console.log("\n════════ Test Run Summary ════════");
|
|
203
|
+
console.log(`Result: Test run ${finalStatus}`);
|
|
204
|
+
console.log(`Cases: total=${args.total}, passed=${args.passed}, failed=${args.failed}`);
|
|
205
|
+
console.log(`Duration: ${durationSeconds}s`);
|
|
206
|
+
console.log("══════════════════════════════════");
|
|
207
|
+
}
|
|
187
208
|
}
|
|
188
209
|
exports.ConsoleReporter = ConsoleReporter;
|
|
189
210
|
//# sourceMappingURL=console-reporter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"console-reporter.js","sourceRoot":"","sources":["../../../src/testing/reporter/console-reporter.ts"],"names":[],"mappings":"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","sourcesContent":["// Purpose: Basic console reporter implementation.\n\nimport type { Reporter } from \"./reporter.types\";\nimport type { OpStep } from \"../contracts/testing-metadata.types\";\n\nconst INDENT = \" \";\nconst STEP_INDENT = INDENT;\nconst MAX_DETAIL_LEN = 140;\n\nfunction formatError(err: unknown): string {\n if (!err) return \"\";\n if (err instanceof Error) {\n return err.stack || err.message;\n }\n return String(err);\n}\n\nfunction indentLines(text: string, indent: string): string {\n return text\n .split(\"\\n\")\n .map((line) => (line.length ? `${indent}${line}` : indent))\n .join(\"\\n\");\n}\n\nfunction truncate(value: string, maxLen: number = MAX_DETAIL_LEN): string {\n if (value.length <= maxLen) return value;\n return `${value.slice(0, maxLen - 1)}…`;\n}\n\nfunction formatHttpBody(body: unknown): string {\n if (body === null || body === undefined) return \"\";\n if (typeof body === \"string\") {\n const trimmed = body.trim();\n if (trimmed.startsWith(\"{\") || trimmed.startsWith(\"[\")) {\n try {\n return JSON.stringify(JSON.parse(trimmed), null, 2);\n } catch {\n return body;\n }\n }\n return body;\n }\n try {\n return JSON.stringify(body, null, 2);\n } catch {\n return String(body);\n }\n}\n\nfunction withoutQuery(url: string): string {\n const idx = url.indexOf(\"?\");\n return idx === -1 ? url : url.slice(0, idx);\n}\n\nfunction maskIfSensitive(value: string, hints: string[]): string {\n const lower = hints.join(\" \").toLowerCase();\n if (lower.includes(\"password\") || lower.includes(\"pwd\")) {\n return \"••••••\";\n }\n return value;\n}\n\nfunction stepDetails(step: OpStep): string | undefined {\n const withObj = (step.with ?? {}) as Record<string, any>;\n\n switch (step.op) {\n case \"api.request\": {\n const method = String(withObj.method ?? \"\").toUpperCase();\n const url = typeof withObj.url === \"string\" ? withoutQuery(withObj.url) : \"\";\n if (!method && !url) return undefined;\n return `${method} ${url}`.trim();\n }\n case \"api.auth.bearerFromLogin\": {\n const url = typeof withObj.url === \"string\" ? withoutQuery(withObj.url) : \"\";\n return url ? `url: ${url}` : undefined;\n }\n case \"ui.goto\": {\n return withObj.url ? `url: ${withObj.url}` : undefined;\n }\n case \"ui.click\":\n case \"ui.expectVisible\": {\n return withObj.selector ? `selector: ${withObj.selector}` : undefined;\n }\n case \"ui.fill\":\n case \"ui.select\": {\n const selector = withObj.selector ? `selector: ${withObj.selector}` : \"\";\n const value =\n withObj.value !== undefined\n ? `value: ${maskIfSensitive(String(withObj.value), [String(withObj.selector ?? \"\"), String(step.op)])}`\n : \"\";\n return [selector, value].filter(Boolean).join(\", \") || undefined;\n }\n case \"ui.press\": {\n const selector = withObj.selector ? `selector: ${withObj.selector}` : \"\";\n const key = withObj.key ? `key: ${withObj.key}` : \"\";\n return [selector, key].filter(Boolean).join(\", \") || undefined;\n }\n case \"ui.expectUrl\": {\n const equals = withObj.equals ? `equals: ${withObj.equals}` : \"\";\n const contains = withObj.contains ? `contains: ${withObj.contains}` : \"\";\n return [equals, contains].filter(Boolean).join(\", \") || undefined;\n }\n case \"ui.expectText\": {\n const selector = withObj.selector ? `selector: ${withObj.selector}` : \"\";\n const equals = withObj.equals ? `equals: ${truncate(String(withObj.equals))}` : \"\";\n const contains = withObj.contains ? `contains: ${truncate(String(withObj.contains))}` : \"\";\n return [selector, equals, contains].filter(Boolean).join(\", \") || undefined;\n }\n case \"assert.httpStatus\": {\n return withObj.is !== undefined ? `status: ${withObj.is}` : undefined;\n }\n case \"assert.jsonPath\": {\n const path = withObj.path ? `path: ${withObj.path}` : \"\";\n const equals = withObj.equals !== undefined ? `equals: ${truncate(String(withObj.equals))}` : \"\";\n return [path, equals].filter(Boolean).join(\", \") || undefined;\n }\n case \"assert.contains\":\n case \"assert.equals\":\n case \"assert.matches\": {\n const expected =\n withObj.expected !== undefined\n ? `expected: ${truncate(String(withObj.expected))}`\n : withObj.pattern\n ? `pattern: ${truncate(String(withObj.pattern))}`\n : withObj.equals !== undefined\n ? `equals: ${truncate(String(withObj.equals))}`\n : \"\";\n return expected || undefined;\n }\n case \"util.sleep\": {\n return withObj.ms !== undefined ? `ms: ${withObj.ms}` : undefined;\n }\n case \"util.log\": {\n return withObj.message ? `message: ${truncate(String(withObj.message))}` : undefined;\n }\n default:\n return undefined;\n }\n}\n\nfunction formatStepLabel(step: OpStep): string {\n const base = step.name ? `${step.op} (${step.name})` : step.op;\n const details = stepDetails(step);\n if (!details) return base;\n return `${base} (${details})`;\n}\n\nexport class ConsoleReporter implements Reporter {\n onScenarioStart(scenario: { id: string; name?: string }): void {\n const label = scenario.name ? `${scenario.id} (${scenario.name})` : scenario.id;\n console.log(`\\n▶ Scenario: ${label}`);\n }\n\n onScenarioEnd(\n scenario: { id: string; name?: string },\n result: { ok: boolean; error?: unknown; durationMs: number },\n ): void {\n const label = scenario.name ? `${scenario.id} (${scenario.name})` : scenario.id;\n const status = result.ok ? \"✔\" : \"✖\";\n console.log(`${status} Scenario: ${label} (${result.durationMs}ms)`);\n }\n\n onStepStart(args: {\n scenarioId: string;\n phase: string;\n step: OpStep;\n }): void {\n const label = formatStepLabel(args.step);\n const phase = args.phase.toUpperCase();\n console.log(`${STEP_INDENT}↳ ${phase} ${label}`);\n }\n\n onStepEnd(args: {\n scenarioId: string;\n phase: string;\n step: OpStep;\n ok: boolean;\n error?: unknown;\n durationMs: number;\n }): void {\n const label = formatStepLabel(args.step);\n const phase = args.phase.toUpperCase();\n const status = args.ok ? \"✔\" : \"✖\";\n console.log(\n `${STEP_INDENT}${status} ${phase} ${label} (${args.durationMs}ms)`\n );\n if (!args.ok && args.error) {\n const details = formatError(args.error);\n console.error(indentLines(details, `${STEP_INDENT}${INDENT}`));\n const httpBody = (args.error as any)?.httpResponseBody;\n if (httpBody !== undefined) {\n const formatted = formatHttpBody(httpBody);\n const bodyText = formatted.length ? formatted : \"<empty>\";\n console.error(\n indentLines(\n `HTTP Response Body:\\n${bodyText}`,\n `${STEP_INDENT}${INDENT}`,\n ),\n );\n }\n }\n }\n\n onSpecResult(args: {\n scenarioId: string;\n specId: string;\n stepName?: string;\n result: { ok: boolean; details?: Record<string, any> };\n }): void {\n console.log(`${INDENT}↳ SPEC ${args.specId} ok=${args.result.ok}`);\n if (args.result.details) {\n const details = JSON.stringify(args.result.details, null, 2);\n console.log(indentLines(details, `${INDENT}${INDENT}`));\n }\n }\n\n attach(args: {\n scenarioId: string;\n name: string;\n contentType: string;\n data: Buffer | string;\n }): void {\n const header = `ATTACH ${args.name} (${args.contentType})`;\n console.log(indentLines(header, `${STEP_INDENT}${INDENT}`));\n const dataText = Buffer.isBuffer(args.data) ? args.data.toString(\"utf8\") : String(args.data ?? \"\");\n if (!dataText.length) return;\n console.log(indentLines(dataText, `${STEP_INDENT}${INDENT}${INDENT}`));\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"console-reporter.js","sourceRoot":"","sources":["../../../src/testing/reporter/console-reporter.ts"],"names":[],"mappings":"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","sourcesContent":["// Purpose: Basic console reporter implementation.\n\nimport type { Reporter } from \"./reporter.types\";\nimport type { OpStep } from \"../contracts/testing-metadata.types\";\n\nconst INDENT = \" \";\nconst STEP_INDENT = INDENT;\nconst MAX_DETAIL_LEN = 140;\n\nfunction formatError(err: unknown): string {\n if (!err) return \"\";\n if (err instanceof Error) {\n return err.stack || err.message;\n }\n return String(err);\n}\n\nfunction indentLines(text: string, indent: string): string {\n return text\n .split(\"\\n\")\n .map((line) => (line.length ? `${indent}${line}` : indent))\n .join(\"\\n\");\n}\n\nfunction truncate(value: string, maxLen: number = MAX_DETAIL_LEN): string {\n if (value.length <= maxLen) return value;\n return `${value.slice(0, maxLen - 1)}…`;\n}\n\nfunction formatHttpBody(body: unknown): string {\n if (body === null || body === undefined) return \"\";\n if (typeof body === \"string\") {\n const trimmed = body.trim();\n if (trimmed.startsWith(\"{\") || trimmed.startsWith(\"[\")) {\n try {\n return JSON.stringify(JSON.parse(trimmed), null, 2);\n } catch {\n return body;\n }\n }\n return body;\n }\n try {\n return JSON.stringify(body, null, 2);\n } catch {\n return String(body);\n }\n}\n\nfunction withoutQuery(url: string): string {\n const idx = url.indexOf(\"?\");\n return idx === -1 ? url : url.slice(0, idx);\n}\n\nfunction maskIfSensitive(value: string, hints: string[]): string {\n const lower = hints.join(\" \").toLowerCase();\n if (lower.includes(\"password\") || lower.includes(\"pwd\")) {\n return \"••••••\";\n }\n return value;\n}\n\nfunction stepDetails(step: OpStep): string | undefined {\n const withObj = (step.with ?? {}) as Record<string, any>;\n\n switch (step.op) {\n case \"api.request\": {\n const method = String(withObj.method ?? \"\").toUpperCase();\n const url = typeof withObj.url === \"string\" ? withoutQuery(withObj.url) : \"\";\n if (!method && !url) return undefined;\n return `${method} ${url}`.trim();\n }\n case \"api.auth.bearerFromLogin\": {\n const url = typeof withObj.url === \"string\" ? withoutQuery(withObj.url) : \"\";\n return url ? `url: ${url}` : undefined;\n }\n case \"ui.goto\": {\n return withObj.url ? `url: ${withObj.url}` : undefined;\n }\n case \"ui.click\":\n case \"ui.expectVisible\": {\n return withObj.selector ? `selector: ${withObj.selector}` : undefined;\n }\n case \"ui.fill\":\n case \"ui.select\": {\n const selector = withObj.selector ? `selector: ${withObj.selector}` : \"\";\n const value =\n withObj.value !== undefined\n ? `value: ${maskIfSensitive(String(withObj.value), [String(withObj.selector ?? \"\"), String(step.op)])}`\n : \"\";\n return [selector, value].filter(Boolean).join(\", \") || undefined;\n }\n case \"ui.press\": {\n const selector = withObj.selector ? `selector: ${withObj.selector}` : \"\";\n const key = withObj.key ? `key: ${withObj.key}` : \"\";\n return [selector, key].filter(Boolean).join(\", \") || undefined;\n }\n case \"ui.expectUrl\": {\n const equals = withObj.equals ? `equals: ${withObj.equals}` : \"\";\n const contains = withObj.contains ? `contains: ${withObj.contains}` : \"\";\n return [equals, contains].filter(Boolean).join(\", \") || undefined;\n }\n case \"ui.expectText\": {\n const selector = withObj.selector ? `selector: ${withObj.selector}` : \"\";\n const equals = withObj.equals ? `equals: ${truncate(String(withObj.equals))}` : \"\";\n const contains = withObj.contains ? `contains: ${truncate(String(withObj.contains))}` : \"\";\n return [selector, equals, contains].filter(Boolean).join(\", \") || undefined;\n }\n case \"assert.httpStatus\": {\n return withObj.is !== undefined ? `status: ${withObj.is}` : undefined;\n }\n case \"assert.jsonPath\": {\n const path = withObj.path ? `path: ${withObj.path}` : \"\";\n const equals = withObj.equals !== undefined ? `equals: ${truncate(String(withObj.equals))}` : \"\";\n return [path, equals].filter(Boolean).join(\", \") || undefined;\n }\n case \"assert.contains\":\n case \"assert.equals\":\n case \"assert.matches\": {\n const expected =\n withObj.expected !== undefined\n ? `expected: ${truncate(String(withObj.expected))}`\n : withObj.pattern\n ? `pattern: ${truncate(String(withObj.pattern))}`\n : withObj.equals !== undefined\n ? `equals: ${truncate(String(withObj.equals))}`\n : \"\";\n return expected || undefined;\n }\n case \"util.sleep\": {\n return withObj.ms !== undefined ? `ms: ${withObj.ms}` : undefined;\n }\n case \"util.log\": {\n return withObj.message ? `message: ${truncate(String(withObj.message))}` : undefined;\n }\n default:\n return undefined;\n }\n}\n\nfunction formatStepLabel(step: OpStep): string {\n const base = step.name ? `${step.op} (${step.name})` : step.op;\n const details = stepDetails(step);\n if (!details) return base;\n return `${base} (${details})`;\n}\n\nexport class ConsoleReporter implements Reporter {\n private totalScenarios = 0;\n private passedScenarios = 0;\n private failedScenarios = 0;\n\n onScenarioStart(scenario: { id: string; name?: string }): void {\n const label = scenario.name ? `${scenario.id} (${scenario.name})` : scenario.id;\n console.log(`\\n▶ Scenario: ${label}`);\n }\n\n onScenarioEnd(\n scenario: { id: string; name?: string },\n result: { ok: boolean; error?: unknown; durationMs: number },\n ): void {\n const label = scenario.name ? `${scenario.id} (${scenario.name})` : scenario.id;\n const status = result.ok ? \"✔\" : \"✖\";\n this.totalScenarios += 1;\n if (result.ok) {\n this.passedScenarios += 1;\n } else {\n this.failedScenarios += 1;\n }\n console.log(`${status} Scenario: ${label} (${result.durationMs}ms)`);\n }\n\n onStepStart(args: {\n scenarioId: string;\n phase: string;\n step: OpStep;\n }): void {\n const label = formatStepLabel(args.step);\n const phase = args.phase.toUpperCase();\n console.log(`${STEP_INDENT}↳ ${phase} ${label}`);\n }\n\n onStepEnd(args: {\n scenarioId: string;\n phase: string;\n step: OpStep;\n ok: boolean;\n error?: unknown;\n durationMs: number;\n }): void {\n const label = formatStepLabel(args.step);\n const phase = args.phase.toUpperCase();\n const status = args.ok ? \"✔\" : \"✖\";\n console.log(\n `${STEP_INDENT}${status} ${phase} ${label} (${args.durationMs}ms)`\n );\n if (!args.ok && args.error) {\n const details = formatError(args.error);\n console.error(indentLines(details, `${STEP_INDENT}${INDENT}`));\n const httpBody = (args.error as any)?.httpResponseBody;\n if (httpBody !== undefined) {\n const formatted = formatHttpBody(httpBody);\n const bodyText = formatted.length ? formatted : \"<empty>\";\n console.error(\n indentLines(\n `HTTP Response Body:\\n${bodyText}`,\n `${STEP_INDENT}${INDENT}`,\n ),\n );\n }\n }\n }\n\n onSpecResult(args: {\n scenarioId: string;\n specId: string;\n stepName?: string;\n result: { ok: boolean; details?: Record<string, any> };\n }): void {\n console.log(`${INDENT}↳ SPEC ${args.specId} ok=${args.result.ok}`);\n if (args.result.details) {\n const details = JSON.stringify(args.result.details, null, 2);\n console.log(indentLines(details, `${INDENT}${INDENT}`));\n }\n }\n\n attach(args: {\n scenarioId: string;\n name: string;\n contentType: string;\n data: Buffer | string;\n }): void {\n const header = `ATTACH ${args.name} (${args.contentType})`;\n console.log(indentLines(header, `${STEP_INDENT}${INDENT}`));\n const dataText = Buffer.isBuffer(args.data) ? args.data.toString(\"utf8\") : String(args.data ?? \"\");\n if (!dataText.length) return;\n console.log(indentLines(dataText, `${STEP_INDENT}${INDENT}${INDENT}`));\n }\n\n onRunEnd(args: {\n ok: boolean;\n total: number;\n passed: number;\n failed: number;\n durationMs: number;\n }): void {\n const durationSeconds = (args.durationMs / 1000).toFixed(2);\n const finalStatus = args.ok ? \"PASSED\" : \"FAILED\";\n\n console.log(\"\\n════════ Test Run Summary ════════\");\n console.log(`Result: Test run ${finalStatus}`);\n console.log(`Cases: total=${args.total}, passed=${args.passed}, failed=${args.failed}`);\n console.log(`Duration: ${durationSeconds}s`);\n console.log(\"══════════════════════════════════\");\n }\n}\n"]}
|
|
@@ -33,5 +33,12 @@ export interface Reporter {
|
|
|
33
33
|
contentType: string;
|
|
34
34
|
data: Buffer | string;
|
|
35
35
|
}): void;
|
|
36
|
+
onRunEnd?(args: {
|
|
37
|
+
ok: boolean;
|
|
38
|
+
total: number;
|
|
39
|
+
passed: number;
|
|
40
|
+
failed: number;
|
|
41
|
+
durationMs: number;
|
|
42
|
+
}): void;
|
|
36
43
|
}
|
|
37
44
|
//# sourceMappingURL=reporter.types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.types.d.ts","sourceRoot":"","sources":["../../../src/testing/reporter/reporter.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAChF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAExE,MAAM,WAAW,QAAQ;IACvB,eAAe,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9C,aAAa,CACX,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAC3D,IAAI,CAAC;IACR,WAAW,CAAC,IAAI,EAAE;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,SAAS,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,IAAI,CAAC;IACT,SAAS,CAAC,IAAI,EAAE;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,SAAS,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,OAAO,CAAC;QACZ,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,IAAI,CAAC;IACT,YAAY,CAAC,CAAC,IAAI,EAAE;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,mBAAmB,CAAC;KAC7B,GAAG,IAAI,CAAC;IACT,MAAM,CAAC,CAAC,IAAI,EAAE;QACZ,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;KACvB,GAAG,IAAI,CAAC;CACV"}
|
|
1
|
+
{"version":3,"file":"reporter.types.d.ts","sourceRoot":"","sources":["../../../src/testing/reporter/reporter.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAChF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAExE,MAAM,WAAW,QAAQ;IACvB,eAAe,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9C,aAAa,CACX,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAC3D,IAAI,CAAC;IACR,WAAW,CAAC,IAAI,EAAE;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,SAAS,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,IAAI,CAAC;IACT,SAAS,CAAC,IAAI,EAAE;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,SAAS,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,OAAO,CAAC;QACZ,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,IAAI,CAAC;IACT,YAAY,CAAC,CAAC,IAAI,EAAE;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,mBAAmB,CAAC;KAC7B,GAAG,IAAI,CAAC;IACT,MAAM,CAAC,CAAC,IAAI,EAAE;QACZ,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;KACvB,GAAG,IAAI,CAAC;IACT,QAAQ,CAAC,CAAC,IAAI,EAAE;QACd,EAAE,EAAE,OAAO,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,IAAI,CAAC;CACV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.types.js","sourceRoot":"","sources":["../../../src/testing/reporter/reporter.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { StepPhase } from \"../contracts/runtime-context.types\";\nimport type { OpStep, ScenarioSpec } from \"../contracts/testing-metadata.types\";\nimport type { SolidTestSpecResult } from \"../contracts/test-spec.types\";\n\nexport interface Reporter {\n onScenarioStart(scenario: ScenarioSpec): void;\n onScenarioEnd(\n scenario: ScenarioSpec,\n result: { ok: boolean; error?: unknown; durationMs: number },\n ): void;\n onStepStart(args: {\n scenarioId: string;\n phase: StepPhase;\n step: OpStep;\n }): void;\n onStepEnd(args: {\n scenarioId: string;\n phase: StepPhase;\n step: OpStep;\n ok: boolean;\n error?: unknown;\n durationMs: number;\n }): void;\n onSpecResult?(args: {\n scenarioId: string;\n specId: string;\n stepName?: string;\n result: SolidTestSpecResult;\n }): void;\n attach?(args: {\n scenarioId: string;\n name: string;\n contentType: string;\n data: Buffer | string;\n }): void;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"reporter.types.js","sourceRoot":"","sources":["../../../src/testing/reporter/reporter.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { StepPhase } from \"../contracts/runtime-context.types\";\nimport type { OpStep, ScenarioSpec } from \"../contracts/testing-metadata.types\";\nimport type { SolidTestSpecResult } from \"../contracts/test-spec.types\";\n\nexport interface Reporter {\n onScenarioStart(scenario: ScenarioSpec): void;\n onScenarioEnd(\n scenario: ScenarioSpec,\n result: { ok: boolean; error?: unknown; durationMs: number },\n ): void;\n onStepStart(args: {\n scenarioId: string;\n phase: StepPhase;\n step: OpStep;\n }): void;\n onStepEnd(args: {\n scenarioId: string;\n phase: StepPhase;\n step: OpStep;\n ok: boolean;\n error?: unknown;\n durationMs: number;\n }): void;\n onSpecResult?(args: {\n scenarioId: string;\n specId: string;\n stepName?: string;\n result: SolidTestSpecResult;\n }): void;\n attach?(args: {\n scenarioId: string;\n name: string;\n contentType: string;\n data: Buffer | string;\n }): void;\n onRunEnd?(args: {\n ok: boolean;\n total: number;\n passed: number;\n failed: number;\n durationMs: number;\n }): void;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-from-metadata.d.ts","sourceRoot":"","sources":["../../../src/testing/runner/run-from-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,qCAAqC,CAAC;AAC9F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AASxE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAoBrD,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,eAAe,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,GAAG,CAAC,EAAE,iBAAiB,CAAC;IACxB,EAAE,CAAC,EAAE,wBAAwB,CAAC;IAC9B,QAAQ,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACrC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;CAC1C,CAAC;AAEF,wBAAsB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"run-from-metadata.d.ts","sourceRoot":"","sources":["../../../src/testing/runner/run-from-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,qCAAqC,CAAC;AAC9F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AASxE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAoBrD,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,eAAe,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,GAAG,CAAC,EAAE,iBAAiB,CAAC;IACxB,EAAE,CAAC,EAAE,wBAAwB,CAAC;IAC9B,QAAQ,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACrC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;CAC1C,CAAC;AAEF,wBAAsB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA2DxE"}
|
|
@@ -62,6 +62,7 @@ function buildTestDataIndex(data) {
|
|
|
62
62
|
return index;
|
|
63
63
|
}
|
|
64
64
|
async function runFromMetadata(opts) {
|
|
65
|
+
const startedAt = Date.now();
|
|
65
66
|
const registry = new step_registry_1.StepRegistry();
|
|
66
67
|
(0, api_1.registerApiSteps)(registry);
|
|
67
68
|
(0, ui_1.registerUiSteps)(registry);
|
|
@@ -86,15 +87,33 @@ async function runFromMetadata(opts) {
|
|
|
86
87
|
const ui = new PlaywrightAdapter(opts.ui);
|
|
87
88
|
const ctxBase = { resources, reporter, api, ui, specRegistry, testData, options: opts.options };
|
|
88
89
|
const uiStarted = { value: false };
|
|
90
|
+
let passed = 0;
|
|
91
|
+
let failed = 0;
|
|
92
|
+
let runError;
|
|
89
93
|
try {
|
|
90
94
|
for (const scenario of scenarios) {
|
|
91
95
|
if ((0, lifecycle_1.scenarioNeedsUi)(scenario)) {
|
|
92
96
|
await (0, lifecycle_1.ensureUiStarted)(ctxBase, uiStarted);
|
|
93
97
|
}
|
|
94
|
-
|
|
98
|
+
try {
|
|
99
|
+
await engine.runScenario(scenario, ctxBase);
|
|
100
|
+
passed += 1;
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
failed += 1;
|
|
104
|
+
runError = error;
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
95
107
|
}
|
|
96
108
|
}
|
|
97
109
|
finally {
|
|
110
|
+
reporter.onRunEnd?.({
|
|
111
|
+
ok: !runError,
|
|
112
|
+
total: scenarios.length,
|
|
113
|
+
passed,
|
|
114
|
+
failed,
|
|
115
|
+
durationMs: Date.now() - startedAt,
|
|
116
|
+
});
|
|
98
117
|
if (uiStarted.value) {
|
|
99
118
|
await ui.stop();
|
|
100
119
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-from-metadata.js","sourceRoot":"","sources":["../../../src/testing/runner/run-from-metadata.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,
|
|
1
|
+
{"version":3,"file":"run-from-metadata.js","sourceRoot":"","sources":["../../../src/testing/runner/run-from-metadata.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Reporter } from \"../reporter/reporter.types\";\nimport type { TestingMetadata, TestingDataRecord } from \"../contracts/testing-metadata.types\";\nimport type { ApiAdapterOptions } from \"../adapters/api/api.types\";\nimport type { PlaywrightAdapterOptions } from \"../adapters/ui/ui.types\";\nimport { ApiAdapter } from \"../adapters/api/api-adapter\";\nimport { registerApiSteps } from \"../steps/api\";\nimport { registerUiSteps } from \"../steps/ui\";\nimport { registerAssertSteps } from \"../steps/assert\";\nimport { registerUtilSteps } from \"../steps/util\";\nimport { registerTestSteps } from \"../steps/test\";\nimport { SimpleResourceStore } from \"../core/resource-store\";\nimport { StepRegistry } from \"../core/step-registry\";\nimport { SpecRegistry } from \"../core/spec-registry\";\nimport { TestingEngine } from \"../core/testing-engine\";\nimport { filterScenarios } from \"./scenario-filter\";\nimport { ensureUiStarted, scenarioNeedsUi } from \"./lifecycle\";\nimport { ConsoleReporter } from \"../reporter/console-reporter\";\n\n\nfunction buildTestDataIndex(data?: TestingDataRecord[]): Record<string, Record<string, any>> {\n const index: Record<string, Record<string, any>> = {};\n if (!Array.isArray(data)) return index;\n for (const record of data) {\n if (!record?.modelUserKey || !record?.recUserKeyValue) continue;\n if (!index[record.modelUserKey]) {\n index[record.modelUserKey] = {};\n }\n index[record.modelUserKey][record.recUserKeyValue] = record.data ?? {};\n }\n return index;\n}\n\nexport type RunnerOptions = {\n metadata: TestingMetadata;\n scenarioIds?: string[];\n includeTags?: string[];\n skipScenarioIds?: string[];\n reporter?: Reporter;\n api?: ApiAdapterOptions;\n ui?: PlaywrightAdapterOptions;\n defaults?: { timeoutMs?: number; retries?: number };\n options?: { printApiLogs?: boolean };\n specs?: (registry: SpecRegistry) => void;\n};\n\nexport async function runFromMetadata(opts: RunnerOptions): Promise<void> {\n const startedAt = Date.now();\n const registry = new StepRegistry();\n registerApiSteps(registry);\n registerUiSteps(registry);\n registerAssertSteps(registry);\n registerUtilSteps(registry);\n registerTestSteps(registry);\n\n const engine = new TestingEngine(registry, opts.defaults);\n const scenarios = filterScenarios(opts.metadata.testing.scenarios, {\n scenarioIds: opts.scenarioIds,\n includeTags: opts.includeTags,\n skipScenarioIds: opts.skipScenarioIds,\n });\n\n const specRegistry = new SpecRegistry();\n const testData = buildTestDataIndex(opts.metadata.testing?.data);\n if (opts.specs) {\n opts.specs(specRegistry);\n }\n\n const resources = new SimpleResourceStore();\n const reporter = opts.reporter ?? new ConsoleReporter();\n const api = new ApiAdapter(opts.api);\n const { PlaywrightAdapter } = await import(\"../adapters/ui/playwright-adapter\");\n const ui = new PlaywrightAdapter(opts.ui);\n const ctxBase = { resources, reporter, api, ui, specRegistry, testData, options: opts.options };\n const uiStarted = { value: false };\n let passed = 0;\n let failed = 0;\n let runError: unknown;\n\n try {\n for (const scenario of scenarios) {\n if (scenarioNeedsUi(scenario)) {\n await ensureUiStarted(ctxBase, uiStarted);\n }\n try {\n await engine.runScenario(scenario, ctxBase);\n passed += 1;\n } catch (error) {\n failed += 1;\n runError = error;\n throw error;\n }\n }\n } finally {\n reporter.onRunEnd?.({\n ok: !runError,\n total: scenarios.length,\n passed,\n failed,\n durationMs: Date.now() - startedAt,\n });\n if (uiStarted.value) {\n await ui.stop();\n }\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidxai/core",
|
|
3
|
-
"version": "0.1.10-beta.
|
|
3
|
+
"version": "0.1.10-beta.7",
|
|
4
4
|
"description": "This module is a NestJS module containing all the required core providers required by a Solid application",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -24,6 +24,7 @@ import { TestingRoleSpec, TestingUserSpec } from 'src/testing/contracts/testing-
|
|
|
24
24
|
@Injectable()
|
|
25
25
|
export class ModuleTestDataService {
|
|
26
26
|
private readonly logger = new Logger(ModuleTestDataService.name);
|
|
27
|
+
private static readonly TEARDOWN_RETRY_ATTEMPTS = 5;
|
|
27
28
|
|
|
28
29
|
constructor(
|
|
29
30
|
private readonly moduleRef: ModuleRef,
|
|
@@ -665,31 +666,122 @@ export class ModuleTestDataService {
|
|
|
665
666
|
private async dropTestDatabaseObjects(databases: Record<string, string>): Promise<void> {
|
|
666
667
|
const entries = Object.entries(databases);
|
|
667
668
|
for (const [dsName, dbName] of entries) {
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
}
|
|
669
|
+
await this.dropTestDatabaseObjectsWithRetry(dsName, dbName);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
672
|
|
|
673
|
-
|
|
673
|
+
private async dropTestDatabaseObjectsWithRetry(dsName: string, dbName: string): Promise<void> {
|
|
674
|
+
let lastError: unknown;
|
|
675
|
+
|
|
676
|
+
for (let attempt = 1; attempt <= ModuleTestDataService.TEARDOWN_RETRY_ATTEMPTS; attempt += 1) {
|
|
677
|
+
console.log(`Attempting to tear down "${dbName}" on datasource "${dsName}" (${attempt}/${ModuleTestDataService.TEARDOWN_RETRY_ATTEMPTS})...`);
|
|
674
678
|
|
|
675
|
-
const queryRunner = dataSource.createQueryRunner();
|
|
676
679
|
try {
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
await queryRunner.query(`DROP DATABASE IF EXISTS \`${dbName}\``);
|
|
684
|
-
} else {
|
|
685
|
-
throw new Error(`Unsupported database type for test data deletion: ${type}`);
|
|
680
|
+
await this.dropSingleTestDatabaseObject(dsName, dbName);
|
|
681
|
+
return;
|
|
682
|
+
} catch (error) {
|
|
683
|
+
lastError = error;
|
|
684
|
+
if (attempt >= ModuleTestDataService.TEARDOWN_RETRY_ATTEMPTS) {
|
|
685
|
+
throw error;
|
|
686
686
|
}
|
|
687
|
+
|
|
688
|
+
await this.sleep(this.teardownRetryDelayMs(attempt));
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
private teardownRetryDelayMs(attempt: number): number {
|
|
696
|
+
const baseMs = 500;
|
|
697
|
+
const incrementMs = 350;
|
|
698
|
+
const jitterMs = Math.floor(Math.random() * 250);
|
|
699
|
+
return baseMs + ((attempt - 1) * incrementMs) + jitterMs;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
private async sleep(ms: number): Promise<void> {
|
|
703
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
private async dropSingleTestDatabaseObject(dsName: string, dbName: string): Promise<void> {
|
|
707
|
+
const dataSource = this.resolveDataSourceByName(dsName);
|
|
708
|
+
|
|
709
|
+
if (dataSource.options.type === 'postgres') {
|
|
710
|
+
await this.dropPostgresDatabase(dataSource, dbName);
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
if (!dataSource.isInitialized) {
|
|
715
|
+
await dataSource.initialize();
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
const queryRunner = dataSource.createQueryRunner();
|
|
719
|
+
try {
|
|
720
|
+
const type = dataSource.options.type;
|
|
721
|
+
if (type === 'mssql') {
|
|
722
|
+
await this.dropMssqlSchema(queryRunner, dbName);
|
|
723
|
+
} else if (type === 'mysql' || type === 'mariadb') {
|
|
724
|
+
await queryRunner.query(`DROP DATABASE IF EXISTS \`${dbName}\``);
|
|
725
|
+
} else {
|
|
726
|
+
throw new Error(`Unsupported database type for test data deletion: ${type}`);
|
|
727
|
+
}
|
|
728
|
+
} finally {
|
|
729
|
+
await queryRunner.release();
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
private async dropPostgresDatabase(dataSource: DataSource, dbName: string): Promise<void> {
|
|
734
|
+
if (dataSource.isInitialized) {
|
|
735
|
+
await dataSource.destroy();
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
const adminDataSource = new DataSource({
|
|
739
|
+
...(dataSource.options as any),
|
|
740
|
+
database: this.resolvePostgresMaintenanceDatabase(dataSource),
|
|
741
|
+
name: `${String(dataSource.name ?? 'default')}_teardown_admin_${Date.now()}`,
|
|
742
|
+
synchronize: false,
|
|
743
|
+
migrationsRun: false,
|
|
744
|
+
entities: [],
|
|
745
|
+
subscribers: [],
|
|
746
|
+
migrations: [],
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
try {
|
|
750
|
+
await adminDataSource.initialize();
|
|
751
|
+
const queryRunner = adminDataSource.createQueryRunner();
|
|
752
|
+
try {
|
|
753
|
+
await queryRunner.query(
|
|
754
|
+
`SELECT pg_terminate_backend(pid)
|
|
755
|
+
FROM pg_stat_activity
|
|
756
|
+
WHERE datname = $1
|
|
757
|
+
AND pid <> pg_backend_pid()`,
|
|
758
|
+
[dbName],
|
|
759
|
+
);
|
|
760
|
+
await queryRunner.query(`DROP DATABASE IF EXISTS "${dbName}"`);
|
|
687
761
|
} finally {
|
|
688
762
|
await queryRunner.release();
|
|
689
763
|
}
|
|
764
|
+
} finally {
|
|
765
|
+
if (adminDataSource.isInitialized) {
|
|
766
|
+
await adminDataSource.destroy();
|
|
767
|
+
}
|
|
690
768
|
}
|
|
691
769
|
}
|
|
692
770
|
|
|
771
|
+
private resolvePostgresMaintenanceDatabase(dataSource: DataSource): string {
|
|
772
|
+
const configured = process.env.POSTGRES_MAINTENANCE_DATABASE?.trim();
|
|
773
|
+
if (configured) {
|
|
774
|
+
return configured;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
const currentDb = String((dataSource.options as any)?.database ?? '').trim();
|
|
778
|
+
if (currentDb && currentDb !== 'postgres') {
|
|
779
|
+
return 'postgres';
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
return 'template1';
|
|
783
|
+
}
|
|
784
|
+
|
|
693
785
|
private async dropMssqlSchema(queryRunner: ReturnType<DataSource['createQueryRunner']>, schemaName: string): Promise<void> {
|
|
694
786
|
const foreignKeys: Array<{ fk_name: string; table_name: string }> = await queryRunner.query(
|
|
695
787
|
`SELECT fk.name AS fk_name, t.name AS table_name
|
|
@@ -146,6 +146,10 @@ function formatStepLabel(step: OpStep): string {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
export class ConsoleReporter implements Reporter {
|
|
149
|
+
private totalScenarios = 0;
|
|
150
|
+
private passedScenarios = 0;
|
|
151
|
+
private failedScenarios = 0;
|
|
152
|
+
|
|
149
153
|
onScenarioStart(scenario: { id: string; name?: string }): void {
|
|
150
154
|
const label = scenario.name ? `${scenario.id} (${scenario.name})` : scenario.id;
|
|
151
155
|
console.log(`\n▶ Scenario: ${label}`);
|
|
@@ -157,6 +161,12 @@ export class ConsoleReporter implements Reporter {
|
|
|
157
161
|
): void {
|
|
158
162
|
const label = scenario.name ? `${scenario.id} (${scenario.name})` : scenario.id;
|
|
159
163
|
const status = result.ok ? "✔" : "✖";
|
|
164
|
+
this.totalScenarios += 1;
|
|
165
|
+
if (result.ok) {
|
|
166
|
+
this.passedScenarios += 1;
|
|
167
|
+
} else {
|
|
168
|
+
this.failedScenarios += 1;
|
|
169
|
+
}
|
|
160
170
|
console.log(`${status} Scenario: ${label} (${result.durationMs}ms)`);
|
|
161
171
|
}
|
|
162
172
|
|
|
@@ -226,4 +236,21 @@ export class ConsoleReporter implements Reporter {
|
|
|
226
236
|
if (!dataText.length) return;
|
|
227
237
|
console.log(indentLines(dataText, `${STEP_INDENT}${INDENT}${INDENT}`));
|
|
228
238
|
}
|
|
239
|
+
|
|
240
|
+
onRunEnd(args: {
|
|
241
|
+
ok: boolean;
|
|
242
|
+
total: number;
|
|
243
|
+
passed: number;
|
|
244
|
+
failed: number;
|
|
245
|
+
durationMs: number;
|
|
246
|
+
}): void {
|
|
247
|
+
const durationSeconds = (args.durationMs / 1000).toFixed(2);
|
|
248
|
+
const finalStatus = args.ok ? "PASSED" : "FAILED";
|
|
249
|
+
|
|
250
|
+
console.log("\n════════ Test Run Summary ════════");
|
|
251
|
+
console.log(`Result: Test run ${finalStatus}`);
|
|
252
|
+
console.log(`Cases: total=${args.total}, passed=${args.passed}, failed=${args.failed}`);
|
|
253
|
+
console.log(`Duration: ${durationSeconds}s`);
|
|
254
|
+
console.log("══════════════════════════════════");
|
|
255
|
+
}
|
|
229
256
|
}
|
|
@@ -44,6 +44,7 @@ export type RunnerOptions = {
|
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
export async function runFromMetadata(opts: RunnerOptions): Promise<void> {
|
|
47
|
+
const startedAt = Date.now();
|
|
47
48
|
const registry = new StepRegistry();
|
|
48
49
|
registerApiSteps(registry);
|
|
49
50
|
registerUiSteps(registry);
|
|
@@ -71,15 +72,32 @@ export async function runFromMetadata(opts: RunnerOptions): Promise<void> {
|
|
|
71
72
|
const ui = new PlaywrightAdapter(opts.ui);
|
|
72
73
|
const ctxBase = { resources, reporter, api, ui, specRegistry, testData, options: opts.options };
|
|
73
74
|
const uiStarted = { value: false };
|
|
75
|
+
let passed = 0;
|
|
76
|
+
let failed = 0;
|
|
77
|
+
let runError: unknown;
|
|
74
78
|
|
|
75
79
|
try {
|
|
76
80
|
for (const scenario of scenarios) {
|
|
77
81
|
if (scenarioNeedsUi(scenario)) {
|
|
78
82
|
await ensureUiStarted(ctxBase, uiStarted);
|
|
79
83
|
}
|
|
80
|
-
|
|
84
|
+
try {
|
|
85
|
+
await engine.runScenario(scenario, ctxBase);
|
|
86
|
+
passed += 1;
|
|
87
|
+
} catch (error) {
|
|
88
|
+
failed += 1;
|
|
89
|
+
runError = error;
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
81
92
|
}
|
|
82
93
|
} finally {
|
|
94
|
+
reporter.onRunEnd?.({
|
|
95
|
+
ok: !runError,
|
|
96
|
+
total: scenarios.length,
|
|
97
|
+
passed,
|
|
98
|
+
failed,
|
|
99
|
+
durationMs: Date.now() - startedAt,
|
|
100
|
+
});
|
|
83
101
|
if (uiStarted.value) {
|
|
84
102
|
await ui.stop();
|
|
85
103
|
}
|