@thinkwise/testwise 0.2.0-beta.3 → 0.2.4
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/Testwise.ts +8 -7
- package/artifact-builder/ArtifactManager.ts +0 -1
- package/artifact-builder/InterfaceGenerator.ts +73 -83
- package/artifact-builder/ModelDataBuilder.ts +74 -86
- package/artifact-builder/ModelDataRefiner.ts +18 -13
- package/artifact-builder/SchemaGenerator.ts +1 -4
- package/artifact-builder/ScreenInterfaceRefiner.ts +0 -5
- package/artifact-builder/SelectorBuilder.ts +8 -1
- package/artifact-builder/SubjectComponentGenerator.ts +77 -7
- package/artifact-builder/SubjectGenerator.ts +3 -3
- package/artifact-builder/SubjectRegistration.ts +68 -60
- package/artifact-builder/helpers/DataRetriever.ts +6 -3
- package/artifact-builder/helpers/NamingHandler.ts +28 -20
- package/artifact-builder/helpers/Stopwatch.ts +13 -0
- package/artifact-builder/helpers/index.ts +1 -0
- package/components/BaseComponentObjects.ts +4 -1
- package/components/action-bar/ActionBar.ts +3 -3
- package/components/grid/Grid.ts +18 -21
- package/components/tab/BaseTab.ts +2 -2
- package/components/tab/BaseTabObjects.ts +1 -1
- package/components/tab/DetailTabPage.ts +2 -2
- package/components/tab/Tab.ts +4 -4
- package/controls/LookupDropdown.ts +7 -2
- package/dist/Testwise.d.ts +1 -0
- package/dist/Testwise.js +15 -6
- package/dist/Testwise.js.map +1 -1
- package/dist/artifact-builder/ArtifactManager.js.map +1 -1
- package/dist/artifact-builder/InterfaceGenerator.d.ts +1 -1
- package/dist/artifact-builder/InterfaceGenerator.js +60 -67
- package/dist/artifact-builder/InterfaceGenerator.js.map +1 -1
- package/dist/artifact-builder/ModelDataBuilder.js +49 -60
- package/dist/artifact-builder/ModelDataBuilder.js.map +1 -1
- package/dist/artifact-builder/ModelDataRefiner.js +11 -7
- package/dist/artifact-builder/ModelDataRefiner.js.map +1 -1
- package/dist/artifact-builder/SchemaGenerator.js +0 -2
- package/dist/artifact-builder/SchemaGenerator.js.map +1 -1
- package/dist/artifact-builder/ScreenInterfaceRefiner.js +0 -5
- package/dist/artifact-builder/ScreenInterfaceRefiner.js.map +1 -1
- package/dist/artifact-builder/SelectorBuilder.js +3 -1
- package/dist/artifact-builder/SelectorBuilder.js.map +1 -1
- package/dist/artifact-builder/SubjectComponentGenerator.d.ts +4 -0
- package/dist/artifact-builder/SubjectComponentGenerator.js +61 -5
- package/dist/artifact-builder/SubjectComponentGenerator.js.map +1 -1
- package/dist/artifact-builder/SubjectGenerator.js +1 -1
- package/dist/artifact-builder/SubjectGenerator.js.map +1 -1
- package/dist/artifact-builder/SubjectRegistration.d.ts +9 -10
- package/dist/artifact-builder/SubjectRegistration.js +51 -43
- package/dist/artifact-builder/SubjectRegistration.js.map +1 -1
- package/dist/artifact-builder/helpers/DataRetriever.js +4 -3
- package/dist/artifact-builder/helpers/DataRetriever.js.map +1 -1
- package/dist/artifact-builder/helpers/NamingHandler.d.ts +2 -1
- package/dist/artifact-builder/helpers/NamingHandler.js +23 -16
- package/dist/artifact-builder/helpers/NamingHandler.js.map +1 -1
- package/dist/artifact-builder/helpers/Stopwatch.d.ts +5 -0
- package/dist/artifact-builder/helpers/Stopwatch.js +13 -0
- package/dist/artifact-builder/helpers/Stopwatch.js.map +1 -0
- package/dist/artifact-builder/helpers/index.d.ts +1 -0
- package/dist/artifact-builder/helpers/index.js +1 -0
- package/dist/artifact-builder/helpers/index.js.map +1 -1
- package/dist/components/BaseComponentObjects.d.ts +1 -0
- package/dist/components/BaseComponentObjects.js +3 -1
- package/dist/components/BaseComponentObjects.js.map +1 -1
- package/dist/components/action-bar/ActionBar.d.ts +1 -1
- package/dist/components/action-bar/ActionBar.js +3 -3
- package/dist/components/grid/Grid.d.ts +5 -4
- package/dist/components/grid/Grid.js +13 -19
- package/dist/components/grid/Grid.js.map +1 -1
- package/dist/components/tab/BaseTab.d.ts +2 -2
- package/dist/components/tab/BaseTab.js +2 -2
- package/dist/components/tab/BaseTab.js.map +1 -1
- package/dist/components/tab/BaseTabObjects.js +1 -1
- package/dist/components/tab/BaseTabObjects.js.map +1 -1
- package/dist/components/tab/DetailTabPage.d.ts +2 -2
- package/dist/components/tab/DetailTabPage.js +2 -2
- package/dist/components/tab/DetailTabPage.js.map +1 -1
- package/dist/components/tab/Tab.d.ts +3 -3
- package/dist/components/tab/Tab.js +4 -4
- package/dist/components/tab/Tab.js.map +1 -1
- package/dist/controls/LookupDropdown.d.ts +3 -7
- package/dist/controls/LookupDropdown.js.map +1 -1
- package/dist/enums/ElementTypes.d.ts +1 -1
- package/dist/enums/ElementTypes.js +1 -1
- package/dist/enums/ElementTypes.js.map +1 -1
- package/dist/helpers/ConfigChecker.d.ts +3 -0
- package/dist/helpers/ConfigChecker.js +7 -0
- package/dist/helpers/ConfigChecker.js.map +1 -0
- package/dist/helpers/LoginHelper.js +1 -1
- package/dist/helpers/LoginHelper.js.map +1 -1
- package/dist/interfaces/IComponentObjects.d.ts +1 -0
- package/dist/page-extensions/SubjectRegistry.d.ts +0 -8
- package/dist/page-extensions/SubjectRegistry.js +2 -6
- package/dist/page-extensions/SubjectRegistry.js.map +1 -1
- package/dist/page-extensions/index.d.ts +0 -1
- package/dist/page-extensions/index.js +0 -1
- package/dist/page-extensions/index.js.map +1 -1
- package/dist/services/IndiciumApi.service.d.ts +27 -0
- package/dist/services/IndiciumApi.service.js +135 -0
- package/dist/services/IndiciumApi.service.js.map +1 -0
- package/dist/templates/test-artifacts/SubjectPageBase.d.ts +5 -0
- package/dist/templates/test-artifacts/SubjectPageBase.js +6 -0
- package/dist/templates/test-artifacts/SubjectPageBase.js.map +1 -0
- package/dist/templates/test-artifacts/screens/index.d.ts +1 -0
- package/dist/templates/test-artifacts/screens/index.js +2 -0
- package/dist/templates/test-artifacts/screens/index.js.map +1 -0
- package/dist/templates/test-artifacts/subjects/index.d.ts +1 -0
- package/dist/templates/test-artifacts/subjects/index.js +2 -0
- package/dist/templates/test-artifacts/subjects/index.js.map +1 -0
- package/enums/ElementTypes.ts +2 -2
- package/helpers/ConfigChecker.ts +7 -0
- package/helpers/LoginHelper.ts +1 -1
- package/interfaces/IComponentObjects.ts +1 -0
- package/interfaces/IRegisteredSubjects.ts +1 -1
- package/package.json +5 -3
- package/page-extensions/SubjectRegistry.ts +2 -19
- package/page-extensions/index.ts +0 -1
- package/scripts/main.js +63 -82
- package/scripts/postinstall.js +40 -42
- package/scripts/setup.js +37 -37
- package/scripts/sync.js +756 -69
- package/services/ConfigBuilder.ts +1 -1
- package/services/IndiciumApi.service.ts +159 -0
- package/templates/SubjectRegistry.template.ts +73 -0
- package/templates/test-artifacts/SubjectPageBase.ts +9 -0
- package/templates/test-artifacts/screens/index.ts +0 -0
- package/templates/test-artifacts/subjects/index.ts +0 -0
- package/tsconfig.json +2 -3
- package/types/Components.ts +1 -1
- package/dist/config.json +0 -10
- package/dist/page-extensions/SubjectProvider.d.ts +0 -11
- package/dist/page-extensions/SubjectProvider.js +0 -24
- package/dist/page-extensions/SubjectProvider.js.map +0 -1
- package/dist/test-artifacts/index.d.ts +0 -3
- package/dist/test-artifacts/index.js +0 -4
- package/dist/test-artifacts/index.js.map +0 -1
- package/page-extensions/SubjectProvider.ts +0 -41
- package/test-artifacts/index.ts +0 -3
package/Testwise.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { test as base } from '@playwright/test';
|
|
2
|
+
import { test as bddBase } from 'playwright-bdd';
|
|
2
3
|
import { Components, GoToDeepLink, LoginFeatures, UserSimulation } from './page-extensions/index.js';
|
|
3
|
-
import { SubjectProvider } from './page-extensions/SubjectProvider.js';
|
|
4
4
|
import { SubjectRegistry } from './page-extensions/SubjectRegistry.js';
|
|
5
5
|
import { WaitEventHandler } from './page-extensions/WaitEventHandler.js';
|
|
6
6
|
import { ClickOverride } from './page-overrides/ClickOverride.js';
|
|
@@ -11,9 +11,7 @@ function combineExtensions(baseTest: Test, ...extensions: { new (test: Test): {
|
|
|
11
11
|
return extensions.reduce((test, Extension) => new Extension(test).test, baseTest);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
base,
|
|
16
|
-
|
|
14
|
+
const extensions = [
|
|
17
15
|
// Override section
|
|
18
16
|
ClickOverride,
|
|
19
17
|
FillOverride,
|
|
@@ -24,6 +22,9 @@ export const test: Test = combineExtensions(
|
|
|
24
22
|
LoginFeatures,
|
|
25
23
|
UserSimulation,
|
|
26
24
|
WaitEventHandler,
|
|
27
|
-
SubjectRegistry
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
SubjectRegistry
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
export const test: Test = combineExtensions(base, ...extensions);
|
|
29
|
+
|
|
30
|
+
export const bddTest: Test = combineExtensions(bddBase, ...extensions);
|
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
import { exec } from 'node:child_process';
|
|
3
1
|
import fs from 'node:fs';
|
|
4
2
|
import path from 'node:path';
|
|
5
3
|
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import * as prettier from 'prettier';
|
|
5
|
+
import { FetchingJSONSchemaStore, InputData, JSONSchemaInput, quicktype } from 'quicktype-core';
|
|
6
6
|
import { PathResolver } from '../helpers/PathResolver.js';
|
|
7
|
-
import { NamingHandler } from '../index.js';
|
|
7
|
+
import { DataRetriever, NamingHandler } from '../index.js';
|
|
8
8
|
|
|
9
9
|
export class InterfaceGenerator {
|
|
10
10
|
private readonly _namingHandler: NamingHandler;
|
|
11
11
|
private _filename: string;
|
|
12
12
|
private _dirname: string;
|
|
13
|
+
private _screensToBuild: string[];
|
|
13
14
|
|
|
14
15
|
constructor() {
|
|
15
16
|
this._namingHandler = new NamingHandler();
|
|
16
17
|
this._filename = fileURLToPath(import.meta.url);
|
|
17
18
|
this._dirname = path.dirname(this._filename);
|
|
19
|
+
this._screensToBuild = new DataRetriever().getScreensToBuild();
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
public async generateScreenInterfacesFromSchemas() {
|
|
@@ -24,7 +26,6 @@ export class InterfaceGenerator {
|
|
|
24
26
|
const schemasDirectory = this.getScreenSchemaFilesPath();
|
|
25
27
|
|
|
26
28
|
await this.generateInterfacesFromSchemaFiles(schemasDirectory, SchemaType.Screen, screenOutputDirectory);
|
|
27
|
-
await this.runPrettierOnSpecifiedDirectory(screenOutputDirectory);
|
|
28
29
|
|
|
29
30
|
console.info('All screen schemas processed.');
|
|
30
31
|
}
|
|
@@ -37,21 +38,18 @@ export class InterfaceGenerator {
|
|
|
37
38
|
this.verifyOutputDirectory(subjectOutputDirectory);
|
|
38
39
|
|
|
39
40
|
await this.generateInterfacesFromSchemaFiles(schemasDirectory, SchemaType.Subject, subjectOutputDirectory);
|
|
40
|
-
await this.runPrettierOnSpecifiedDirectory(subjectOutputDirectory);
|
|
41
41
|
|
|
42
42
|
console.info('All subject schemas processed.');
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
private verifyGeneratedSubjectSchemasDirectory(directory: string) {
|
|
46
46
|
if (!fs.existsSync(directory)) {
|
|
47
|
-
console.error(`Schemas directory not found: ${directory}`);
|
|
48
47
|
return;
|
|
49
48
|
}
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
private verifyOutputDirectory(directory: string) {
|
|
53
52
|
if (!fs.existsSync(directory)) {
|
|
54
|
-
console.info(`Creating output directory: ${directory}`);
|
|
55
53
|
fs.mkdirSync(directory, { recursive: true });
|
|
56
54
|
}
|
|
57
55
|
}
|
|
@@ -69,51 +67,58 @@ export class InterfaceGenerator {
|
|
|
69
67
|
return componentsDirectory;
|
|
70
68
|
}
|
|
71
69
|
|
|
72
|
-
private createInterfaceFromSchema(
|
|
70
|
+
private async createInterfaceFromSchema(
|
|
73
71
|
schemasDirectory: string,
|
|
74
72
|
outputPath: string,
|
|
75
73
|
file: string,
|
|
76
74
|
isInterface: boolean = false
|
|
77
75
|
): Promise<boolean> {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
})
|
|
76
|
+
try {
|
|
77
|
+
const baseFileName = file.slice(0, file.lastIndexOf('.'));
|
|
78
|
+
const correctInterfaceName = isInterface
|
|
79
|
+
? this._namingHandler.generateScreenInterfaceName(baseFileName)
|
|
80
|
+
: this._namingHandler.snakeToPascalCase(baseFileName);
|
|
81
|
+
|
|
82
|
+
const schemaPath = path.join(schemasDirectory, file);
|
|
83
|
+
const schemaContent = fs.readFileSync(schemaPath, 'utf-8');
|
|
84
|
+
|
|
85
|
+
const schemaInput = new JSONSchemaInput(new FetchingJSONSchemaStore());
|
|
86
|
+
await schemaInput.addSource({
|
|
87
|
+
name: correctInterfaceName,
|
|
88
|
+
schema: schemaContent
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const inputData = new InputData();
|
|
92
|
+
inputData.addInput(schemaInput);
|
|
93
|
+
|
|
94
|
+
const result = await quicktype({
|
|
95
|
+
inputData,
|
|
96
|
+
lang: 'typescript',
|
|
97
|
+
rendererOptions: { 'just-types': 'true', 'nice-property-names': 'true' }
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
let updatedContent = result.lines.join('\n');
|
|
101
|
+
|
|
102
|
+
updatedContent = updatedContent.replace(/interface\s+\w+/, `interface ${correctInterfaceName}`);
|
|
103
|
+
|
|
104
|
+
const formattedContent = await prettier.format(updatedContent, {
|
|
105
|
+
parser: 'typescript',
|
|
106
|
+
singleQuote: true,
|
|
107
|
+
semi: true,
|
|
108
|
+
trailingComma: 'all'
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
fs.writeFileSync(outputPath, formattedContent, 'utf-8');
|
|
112
|
+
|
|
113
|
+
return true;
|
|
114
|
+
} catch (error) {
|
|
115
|
+
if (error instanceof Error) {
|
|
116
|
+
console.error(`Error processing ${file}:`, error.message);
|
|
117
|
+
} else {
|
|
118
|
+
console.error(`Error processing ${file}:`, error);
|
|
119
|
+
}
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
117
122
|
}
|
|
118
123
|
|
|
119
124
|
private async generateInterfacesFromSchemaFiles(
|
|
@@ -123,46 +128,31 @@ export class InterfaceGenerator {
|
|
|
123
128
|
): Promise<void> {
|
|
124
129
|
const schemaFiles: string[] = this.getGeneratedSubjectSchemas(schemasDirectory);
|
|
125
130
|
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
const fileName = this._namingHandler.getPascalSubjectComponentName(file);
|
|
129
|
-
|
|
130
|
-
if (schemaType === SchemaType.Subject) {
|
|
131
|
-
const subject = this._namingHandler.getSubjectFromFileName(fileName);
|
|
132
|
-
const componentsDirectory = this.verifySubjectComponentsDirectory(outputPath, subject);
|
|
133
|
-
const perFileOutputPath = path.join(componentsDirectory, `${fileName}.ts`);
|
|
134
|
-
this.createInterfaceFromSchema(schemasDirectory, perFileOutputPath, file).then(resolve).catch(reject);
|
|
135
|
-
} else if (schemaType === SchemaType.Screen) {
|
|
136
|
-
const perFileOutputPath = path.join(outputPath, `I${fileName}.ts`);
|
|
137
|
-
this.createInterfaceFromSchema(schemasDirectory, perFileOutputPath, file, true).then(resolve).catch(reject);
|
|
138
|
-
} else {
|
|
139
|
-
reject(new Error(`Unsupported schema type: ${schemaType}`));
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
});
|
|
131
|
+
const tasks = schemaFiles.map(async (file) => {
|
|
132
|
+
const fileName = this._namingHandler.getPascalSubjectComponentName(file);
|
|
143
133
|
|
|
144
|
-
|
|
145
|
-
|
|
134
|
+
if (schemaType === SchemaType.Subject) {
|
|
135
|
+
const subject = this._namingHandler.getSubjectFromFileName(fileName);
|
|
136
|
+
const componentsDirectory = this.verifySubjectComponentsDirectory(outputPath, subject);
|
|
137
|
+
const perFileOutputPath = path.join(componentsDirectory, `${fileName}.ts`);
|
|
138
|
+
return this.createInterfaceFromSchema(schemasDirectory, perFileOutputPath, file);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (schemaType === SchemaType.Screen) {
|
|
142
|
+
const fileNameSnakeCase = this._namingHandler.pascalToSnakeCase(fileName);
|
|
146
143
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const relativeDir = path.relative(packageDir, directory);
|
|
150
|
-
|
|
151
|
-
await new Promise((resolve, reject) => {
|
|
152
|
-
exec(
|
|
153
|
-
`npx prettier --write "${relativeDir}"`,
|
|
154
|
-
{ cwd: packageDir },
|
|
155
|
-
(prettierError) => {
|
|
156
|
-
if (prettierError) {
|
|
157
|
-
console.error(`Prettier failed for ${directory}:`, prettierError.message);
|
|
158
|
-
reject(prettierError);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
console.info(`Formatted all files in: ${directory}`);
|
|
162
|
-
resolve(true);
|
|
144
|
+
if (this._screensToBuild.length > 0 && !this._screensToBuild.includes(fileNameSnakeCase)) {
|
|
145
|
+
return Promise.resolve(true);
|
|
163
146
|
}
|
|
164
|
-
|
|
147
|
+
|
|
148
|
+
const perFileOutputPath = path.join(outputPath, `I${fileName}.ts`);
|
|
149
|
+
return this.createInterfaceFromSchema(schemasDirectory, perFileOutputPath, file, true);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
throw new Error(`Unsupported schema type: ${schemaType}`);
|
|
165
153
|
});
|
|
154
|
+
|
|
155
|
+
await Promise.all(tasks);
|
|
166
156
|
}
|
|
167
157
|
|
|
168
158
|
public getScreenSchemaFilesPath(): string {
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/** biome-ignore-all lint/style/noNonNullAssertion: Because I can */
|
|
3
3
|
/** biome-ignore-all lint/suspicious/noExplicitAny: Because I can */
|
|
4
|
-
import
|
|
4
|
+
import * as fs from 'node:fs/promises';
|
|
5
|
+
import * as path from 'node:path';
|
|
5
6
|
import type { IProperty } from '../interfaces/IProperty.js';
|
|
6
|
-
import {
|
|
7
|
+
import { indiciumApi } from '../services/IndiciumApi.service.js';
|
|
7
8
|
import { DataRetriever } from './helpers/DataRetriever.js';
|
|
8
9
|
|
|
10
|
+
// ToDo: move this to a types folder
|
|
9
11
|
type Subjects = {
|
|
10
12
|
subject: string;
|
|
11
13
|
variant: string;
|
|
@@ -14,82 +16,92 @@ type Subjects = {
|
|
|
14
16
|
properties?: IProperty[];
|
|
15
17
|
};
|
|
16
18
|
|
|
17
|
-
const serviceUrl: string = testwiseConfig().get<string>('environmentSettings.serviceUrl')!.replace(/\/$/, '');
|
|
18
|
-
const metaEndpoint: string = testwiseConfig()
|
|
19
|
-
.get<string>('environmentSettings.metaEndpoint')!
|
|
20
|
-
.replace(/^\//, '')
|
|
21
|
-
.replace(/\/$/, '');
|
|
22
|
-
const authUser: string = testwiseConfig().get<string>('environmentSettings.authUser')!;
|
|
23
|
-
const authUserPassword: string = testwiseConfig().get<string>('environmentSettings.authUserPassword')!;
|
|
24
|
-
|
|
25
|
-
const axiosInstance = axios.create({
|
|
26
|
-
baseURL: serviceUrl,
|
|
27
|
-
headers: {
|
|
28
|
-
Authorization: `Basic ${Buffer.from(`${authUser}:${authUserPassword}`).toString('base64')}`,
|
|
29
|
-
accept: '*/*'
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
const guiApplId: number = await getGuiApplId();
|
|
34
|
-
|
|
35
19
|
export async function buildSubjects() {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const subjectArray: Subjects[] = rawTabs.flatMap((tab: any) => {
|
|
41
|
-
const base = {
|
|
42
|
-
subject: tab.tab_id,
|
|
43
|
-
variant: tab.tab_variant_id
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
return [
|
|
47
|
-
{ ...base, screentype_id: tab.main_screen_type_id, screentype_context: 'main' },
|
|
48
|
-
{ ...base, screentype_id: tab.detail_screen_type_id, screentype_context: 'detail' },
|
|
49
|
-
{ ...base, screentype_id: tab.zoom_screen_type_id, screentype_context: 'zoom' },
|
|
50
|
-
{ ...base, screentype_id: tab.popup_screen_type_id, screentype_context: 'popup' }
|
|
51
|
-
];
|
|
52
|
-
}).filter(item => item.screentype_id !== "not_visible_in_gui");
|
|
20
|
+
if (!(await indiciumApi.canConnectToProject())) {
|
|
21
|
+
console.log('Cannot connect to Indicium API. Aborting subject build.');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
53
24
|
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
25
|
+
const rawTables: any[] = await indiciumApi.getAllTables();
|
|
26
|
+
|
|
27
|
+
const subjects: Subjects[] = rawTables
|
|
28
|
+
.flatMap((tab: any) => {
|
|
29
|
+
const base = {
|
|
30
|
+
subject: tab.tab_id,
|
|
31
|
+
variant: tab.tab_variant_id
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return [
|
|
35
|
+
{ ...base, screentype_id: tab.main_screen_type_id, screentype_context: 'main' },
|
|
36
|
+
{ ...base, screentype_id: tab.detail_screen_type_id, screentype_context: 'detail' },
|
|
37
|
+
{ ...base, screentype_id: tab.popup_screen_type_id, screentype_context: 'popup' },
|
|
38
|
+
{ ...base, screentype_id: tab.zoom_screen_type_id, screentype_context: 'zoom' }
|
|
39
|
+
];
|
|
40
|
+
})
|
|
41
|
+
.filter((item) => item.screentype_id !== 'not_visible_in_gui');
|
|
42
|
+
|
|
43
|
+
const screentypeOrder = ['main', 'detail', 'popup', 'zoom'];
|
|
44
|
+
|
|
45
|
+
subjects.sort((a, b) => {
|
|
46
|
+
return (
|
|
47
|
+
a.subject.localeCompare(b.subject) ||
|
|
48
|
+
a.variant.localeCompare(b.variant) ||
|
|
49
|
+
screentypeOrder.indexOf(a.screentype_context) - screentypeOrder.indexOf(b.screentype_context)
|
|
50
|
+
);
|
|
51
|
+
});
|
|
57
52
|
|
|
58
|
-
const allProperties: IPropertyWithSubjectIdentifiers[] =
|
|
53
|
+
const allProperties: IPropertyWithSubjectIdentifiers[] = (await indiciumApi.getAllColumns()).map((col: any) => ({
|
|
59
54
|
subject: col.tab_id,
|
|
60
55
|
variant: col.tab_variant_id,
|
|
61
56
|
col: col.col_id,
|
|
62
57
|
control_type: col.control_id || ''
|
|
63
58
|
}));
|
|
64
59
|
|
|
65
|
-
for (const subject of
|
|
60
|
+
for (const subject of subjects) {
|
|
66
61
|
const matchingProperties = allProperties.filter(
|
|
67
62
|
(prop) => prop.subject === subject.subject && prop.variant === subject.variant
|
|
68
63
|
);
|
|
69
64
|
|
|
70
|
-
|
|
71
|
-
|
|
65
|
+
subject.properties = matchingProperties
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
67
|
+
.map(({ subject, variant, ...rest }) => rest)
|
|
68
|
+
.sort((a, b) => a.col.localeCompare(b.col));
|
|
72
69
|
}
|
|
73
70
|
|
|
74
|
-
const
|
|
71
|
+
const subjectsWithLookupsSet = await setLookupDropdowns(subjects);
|
|
75
72
|
|
|
76
|
-
const
|
|
77
|
-
const path = await import('node:path');
|
|
73
|
+
const seedDataDirectory = new DataRetriever().getSeedDataDirectory();
|
|
78
74
|
|
|
79
75
|
const seedDataPath = path.join(seedDataDirectory, 'subjects.json');
|
|
80
|
-
await fs.writeFile(seedDataPath, JSON.stringify(
|
|
76
|
+
await fs.writeFile(seedDataPath, JSON.stringify(subjectsWithLookupsSet, null, 2), 'utf-8');
|
|
81
77
|
console.log(`Seed data written to ${seedDataPath}`);
|
|
82
78
|
}
|
|
83
79
|
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
async function setLookupDropdowns(subjects: Subjects[]): Promise<Subjects[]> {
|
|
81
|
+
const lookupMappings: any[] = await indiciumApi.getLookups();
|
|
82
|
+
|
|
83
|
+
for (const mapping of lookupMappings) {
|
|
84
|
+
const targetSubject = subjects.find(
|
|
85
|
+
(subj) => subj.subject === mapping.tab_id && subj.variant === mapping.tab_variant_id
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const targetProperty = targetSubject?.properties?.find((prop) => prop.col === mapping.col_id);
|
|
89
|
+
|
|
90
|
+
if (targetProperty) {
|
|
91
|
+
targetProperty.control_type = 'LOOKUP_DROPDOWN';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return subjects;
|
|
96
|
+
}
|
|
86
97
|
|
|
87
98
|
export async function buildScreens() {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
99
|
+
if (!(await indiciumApi.canConnectToProject())) {
|
|
100
|
+
console.log('Cannot connect to Indicium API. Aborting screen build.');
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
91
103
|
|
|
92
|
-
const rawComponents =
|
|
104
|
+
const rawComponents = await indiciumApi.getScreenComponents();
|
|
93
105
|
const screenMap = new Map<string, any>();
|
|
94
106
|
|
|
95
107
|
for (const item of rawComponents) {
|
|
@@ -119,59 +131,35 @@ export async function buildScreens() {
|
|
|
119
131
|
|
|
120
132
|
for (const comp of screenData.Components) {
|
|
121
133
|
const type = comp.ScreenComponentType;
|
|
122
|
-
properties[comp.ScreenComponentId] = {
|
|
134
|
+
properties[comp.ScreenComponentId] = { $ref: `#/definitions/${type}` };
|
|
123
135
|
required.push(comp.ScreenComponentId);
|
|
124
136
|
usedTypes.add(type);
|
|
125
137
|
}
|
|
126
138
|
|
|
127
139
|
const schema = {
|
|
128
140
|
title: `I_${screenTypeId}`,
|
|
129
|
-
type:
|
|
141
|
+
type: 'object',
|
|
130
142
|
properties,
|
|
131
143
|
required,
|
|
132
144
|
additionalProperties: false,
|
|
133
145
|
definitions: Array.from(usedTypes).reduce((acc, type) => {
|
|
134
146
|
acc[type] = {
|
|
135
|
-
type:
|
|
136
|
-
properties: { temp: { type:
|
|
137
|
-
required: [
|
|
147
|
+
type: 'object',
|
|
148
|
+
properties: { temp: { type: 'string' } },
|
|
149
|
+
required: ['temp'],
|
|
138
150
|
additionalProperties: false
|
|
139
151
|
};
|
|
140
152
|
return acc;
|
|
141
153
|
}, {} as any)
|
|
142
154
|
};
|
|
143
155
|
|
|
144
|
-
await fs.writeFile(
|
|
145
|
-
path.join(outputDir, `${screenTypeId}.json`),
|
|
146
|
-
JSON.stringify(schema, null, 2)
|
|
147
|
-
);
|
|
156
|
+
await fs.writeFile(path.join(outputDir, `${screenTypeId}.json`), JSON.stringify(schema, null, 2));
|
|
148
157
|
}
|
|
149
158
|
console.log('Screen schemas generated successfully.');
|
|
150
159
|
}
|
|
151
160
|
|
|
152
|
-
|
|
153
|
-
const guiApplAlias = testwiseConfig().get<string>('environmentSettings.guiApplAlias');
|
|
154
|
-
|
|
155
|
-
if (guiApplAlias) {
|
|
156
|
-
const response = await axiosInstance.get(`/iam/${metaEndpoint}/i_ui_gui_appl`);
|
|
157
|
-
const guiAppl = response.data?.value.find((appl: any) => {
|
|
158
|
-
const currentAlias = appl?.gui_appl_alias?.toString();
|
|
159
|
-
const targetAlias = guiApplAlias?.toString();
|
|
160
|
-
|
|
161
|
-
return currentAlias === targetAlias;
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
if (guiAppl) {
|
|
165
|
-
return guiAppl.gui_appl_id;
|
|
166
|
-
} else {
|
|
167
|
-
throw new Error(`No GUI Application found for GUI Application Alias: ${guiApplAlias}`);
|
|
168
|
-
}
|
|
169
|
-
} else {
|
|
170
|
-
throw new Error('GUI Application Alias is not defined in the configuration.');
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
161
|
+
// ToDo: move this to a interfaces folder
|
|
174
162
|
interface IPropertyWithSubjectIdentifiers extends IProperty {
|
|
175
163
|
subject: string;
|
|
176
164
|
variant: string;
|
|
177
|
-
}
|
|
165
|
+
}
|
|
@@ -8,31 +8,36 @@ export class ModelDataRefiner {
|
|
|
8
8
|
|
|
9
9
|
public run() {
|
|
10
10
|
const seedDataDir = this._dataRetriever.getSeedDataDirectory();
|
|
11
|
-
const
|
|
11
|
+
const subjectsToBuildPath = path.resolve(seedDataDir, 'subjectsToBuild.json');
|
|
12
|
+
const screensToBuildPath = path.resolve(seedDataDir, 'screensToBuild.json');
|
|
13
|
+
const registeredSubjects: IRegisteredSubjects[] | null = this._dataRetriever.getRegisteredSubjects();
|
|
12
14
|
|
|
13
15
|
if (!registeredSubjects || registeredSubjects.length === 0) {
|
|
14
|
-
console.
|
|
16
|
+
console.info('No registered subjects found.');
|
|
17
|
+
|
|
18
|
+
if (fs.existsSync(screensToBuildPath)) fs.unlinkSync(screensToBuildPath);
|
|
19
|
+
if (fs.existsSync(subjectsToBuildPath)) fs.unlinkSync(subjectsToBuildPath);
|
|
20
|
+
|
|
15
21
|
return;
|
|
16
22
|
}
|
|
17
23
|
|
|
18
24
|
const subjects = this._dataRetriever.getSubjectsSeedData();
|
|
19
25
|
|
|
20
|
-
const subjectsToBuild = subjects.filter(subject =>
|
|
21
|
-
registeredSubjects.some(
|
|
22
|
-
registered
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
const subjectsToBuild = subjects.filter((subject) =>
|
|
27
|
+
registeredSubjects.some(
|
|
28
|
+
(registered) =>
|
|
29
|
+
registered.subject === subject.subject &&
|
|
30
|
+
(registered.variant != null ? registered.variant === subject.variant : subject.variant === '') &&
|
|
31
|
+
registered.screen_type === subject.screentype_context
|
|
25
32
|
)
|
|
26
33
|
);
|
|
27
34
|
|
|
28
|
-
const subjectsToBuildPath = path.resolve(seedDataDir, 'subjectsToBuild.json');
|
|
29
35
|
fs.writeFileSync(subjectsToBuildPath, JSON.stringify(subjectsToBuild, null, 2));
|
|
30
36
|
console.log(`Created subjectsToBuild.json with ${subjectsToBuild.length} subjects.`);
|
|
31
37
|
|
|
32
|
-
const
|
|
38
|
+
const screensToBuildList = Array.from(new Set(subjectsToBuild.map((subject) => subject.screentype_id)));
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
console.log(`Created screensToBuild.json with ${screensToBuild.length} screens.`);
|
|
40
|
+
fs.writeFileSync(screensToBuildPath, JSON.stringify(screensToBuildList, null, 2));
|
|
41
|
+
console.log(`Created screensToBuild.json with ${screensToBuildList.length} screens.`);
|
|
37
42
|
}
|
|
38
|
-
}
|
|
43
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
2
|
import * as fs from 'node:fs';
|
|
4
3
|
import * as path from 'node:path';
|
|
@@ -48,11 +47,9 @@ export class SchemaGenerator {
|
|
|
48
47
|
switch (component) {
|
|
49
48
|
case 'Form':
|
|
50
49
|
this.createComponentSchema(subject, 'Form');
|
|
51
|
-
console.log(`Generated Form schema for subject: ${subject.subject}`);
|
|
52
50
|
break;
|
|
53
51
|
case 'Grid':
|
|
54
52
|
this.createComponentSchema(subject, 'Grid');
|
|
55
|
-
console.log(`Generated Grid schema for subject: ${subject.subject}`);
|
|
56
53
|
break;
|
|
57
54
|
}
|
|
58
55
|
}
|
|
@@ -90,7 +87,7 @@ export class SchemaGenerator {
|
|
|
90
87
|
const interfaceName = `${subject.subject}_${componentType.toLowerCase()}`;
|
|
91
88
|
const schemasDir = path.join(currentDirname, '..', '..', 'dist/test-artifacts/schemas');
|
|
92
89
|
const fileName = `${this._namingHandler.snakeToPascalCase(interfaceName)}.json`;
|
|
93
|
-
|
|
90
|
+
|
|
94
91
|
if (fs.existsSync(path.join(schemasDir, fileName))) {
|
|
95
92
|
return;
|
|
96
93
|
}
|
|
@@ -13,8 +13,6 @@ export class ScreenInterfaceRefiner {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
public refine() {
|
|
16
|
-
console.log('Refining interfaces in:', this._screensDirectory);
|
|
17
|
-
|
|
18
16
|
const screenFiles = this.getAllScreenInterfaceFiles();
|
|
19
17
|
|
|
20
18
|
screenFiles.forEach((screenFile) => {
|
|
@@ -34,9 +32,6 @@ export class ScreenInterfaceRefiner {
|
|
|
34
32
|
this.formatContent(screen);
|
|
35
33
|
|
|
36
34
|
fs.writeFileSync(filePath, screen.content, 'utf-8');
|
|
37
|
-
console.log(`Refined interfaces in: ${screenFile}`);
|
|
38
|
-
} else {
|
|
39
|
-
console.log(`No additional interfaces to refine in: ${screenFile}`);
|
|
40
35
|
}
|
|
41
36
|
|
|
42
37
|
this.indexScreenInterface(screenFile);
|
|
@@ -53,7 +53,14 @@ export class SelectorBuilder {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
public getPageLocatorString(property: string, componentName: SubjectComponents): string {
|
|
56
|
-
|
|
56
|
+
let elementId = this._namingHandler.getIdFromElementName(
|
|
57
|
+
property,
|
|
58
|
+
componentName,
|
|
59
|
+
this._namingHandler.getElementTypeFromElementName(property)
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
if (componentName === 'Grid') elementId = elementId.replace(/-/g, '_');
|
|
63
|
+
|
|
57
64
|
const selectorPrefix = this.getDefaultPrefix(componentName);
|
|
58
65
|
const defaultSuffix = this.getDefaultSuffix(componentName);
|
|
59
66
|
const selectorSuffix = this.determineSelectorSuffix(property, componentName) || defaultSuffix;
|