@thinkwise/testwise 0.1.12 → 0.1.65
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 +5 -1
- package/components/filter/FilterForm.ts +1 -1
- package/components/filter/FindForm.ts +1 -1
- package/components/grid/Grid.ts +88 -12
- package/components/grid/GridObjects.ts +16 -8
- package/components/index.ts +7 -3
- package/components/pop-up/PopUpComponent.ts +1 -1
- package/components/tab/BaseTab.ts +42 -0
- package/components/tab/BaseTabObjects.ts +23 -0
- package/components/tab/ComponentTab.ts +35 -0
- package/components/tab/ComponentTabObjects.ts +14 -0
- package/components/tab/DetailTab.ts +20 -0
- package/components/tab/DetailTabObjects.ts +10 -0
- package/components/task/TaskBar.ts +29 -9
- package/components/task/TaskBarObjects.ts +24 -0
- package/components/task/TaskTile.ts +28 -0
- package/components/task/TaskTileObjects.ts +20 -0
- package/controls/LookupDropdown.ts +54 -0
- package/controls/index.ts +1 -0
- package/dist/Testwise.js +4 -2
- package/dist/Testwise.js.map +1 -1
- package/dist/biome.json +52 -0
- package/dist/components/filter/FilterForm.d.ts +5 -0
- package/dist/components/filter/FilterForm.js +10 -0
- package/dist/components/filter/FilterForm.js.map +1 -0
- package/dist/components/filter/FindForm.d.ts +5 -0
- package/dist/components/filter/FindForm.js +10 -0
- package/dist/components/filter/FindForm.js.map +1 -0
- package/dist/components/grid/Grid.d.ts +25 -6
- package/dist/components/grid/Grid.js +80 -16
- package/dist/components/grid/Grid.js.map +1 -1
- package/dist/components/grid/GridObjects.d.ts +5 -3
- package/dist/components/grid/GridObjects.js +9 -6
- package/dist/components/grid/GridObjects.js.map +1 -1
- package/dist/components/index.d.ts +7 -3
- package/dist/components/index.js +7 -3
- package/dist/components/index.js.map +1 -1
- package/dist/components/pop-up/PopUpComponent.js +1 -1
- package/dist/components/pop-up/PopUpComponent.js.map +1 -1
- package/dist/components/pop-up/{PopUpComponentModels.js → PopUpComponentObjects.js} +1 -1
- package/dist/components/pop-up/PopUpComponentObjects.js.map +1 -0
- package/dist/components/tab/BaseTab.d.ts +11 -0
- package/dist/components/tab/BaseTab.js +34 -0
- package/dist/components/tab/BaseTab.js.map +1 -0
- package/dist/components/tab/BaseTabObjects.d.ts +10 -0
- package/dist/components/tab/BaseTabObjects.js +14 -0
- package/dist/components/tab/BaseTabObjects.js.map +1 -0
- package/dist/components/tab/ComponentTab.d.ts +11 -0
- package/dist/components/tab/ComponentTab.js +27 -0
- package/dist/components/tab/ComponentTab.js.map +1 -0
- package/dist/components/tab/ComponentTabObjects.d.ts +7 -0
- package/dist/components/tab/ComponentTabObjects.js +10 -0
- package/dist/components/tab/ComponentTabObjects.js.map +1 -0
- package/dist/components/tab/DetailTab.d.ts +9 -0
- package/dist/components/tab/DetailTab.js +15 -0
- package/dist/components/tab/DetailTab.js.map +1 -0
- package/dist/components/tab/DetailTabObjects.d.ts +5 -0
- package/dist/components/tab/DetailTabObjects.js +7 -0
- package/dist/components/tab/DetailTabObjects.js.map +1 -0
- package/dist/components/task/TaskBar.d.ts +17 -0
- package/dist/components/task/TaskBar.js +23 -0
- package/dist/components/task/TaskBar.js.map +1 -0
- package/dist/components/task/TaskBarObjects.d.ts +17 -0
- package/dist/components/task/TaskBarObjects.js +19 -0
- package/dist/components/task/TaskBarObjects.js.map +1 -0
- package/dist/components/task/TaskTile.d.ts +14 -0
- package/dist/components/task/TaskTile.js +20 -0
- package/dist/components/task/TaskTile.js.map +1 -0
- package/dist/components/task/TaskTileObjects.d.ts +13 -0
- package/dist/components/task/TaskTileObjects.js +15 -0
- package/dist/components/task/TaskTileObjects.js.map +1 -0
- package/dist/config.json +10 -10
- package/dist/controls/LookupDropdown.d.ts +11 -0
- package/dist/controls/LookupDropdown.js +39 -0
- package/dist/controls/LookupDropdown.js.map +1 -0
- package/dist/controls/index.d.ts +1 -0
- package/dist/controls/index.js +2 -0
- package/dist/controls/index.js.map +1 -0
- package/dist/enums/LogLevel.d.ts +2 -3
- package/dist/enums/LogLevel.js +1 -2
- package/dist/enums/LogLevel.js.map +1 -1
- package/dist/enums/index.d.ts +1 -0
- package/dist/enums/index.js +2 -0
- package/dist/enums/index.js.map +1 -0
- package/dist/example-code/TestifyService.js +22 -12
- package/dist/example-code/TestifyService.js.map +1 -1
- package/dist/helpers/Ensure.d.ts +2 -0
- package/dist/helpers/Ensure.js +10 -0
- package/dist/helpers/Ensure.js.map +1 -0
- package/dist/helpers/FlightTracker.d.ts +6 -0
- package/dist/helpers/FlightTracker.js +25 -0
- package/dist/helpers/FlightTracker.js.map +1 -0
- package/dist/helpers/GlobalWaitEventHandler.d.ts +12 -0
- package/dist/helpers/GlobalWaitEventHandler.js +53 -0
- package/dist/helpers/GlobalWaitEventHandler.js.map +1 -0
- package/dist/helpers/LoginHelper.d.ts +3 -2
- package/dist/helpers/LoginHelper.js +14 -8
- package/dist/helpers/LoginHelper.js.map +1 -1
- package/dist/helpers/Poll.d.ts +2 -0
- package/dist/helpers/Poll.js +17 -0
- package/dist/helpers/Poll.js.map +1 -0
- package/dist/helpers/RegexHelper.d.ts +5 -0
- package/dist/helpers/RegexHelper.js +16 -0
- package/dist/helpers/RegexHelper.js.map +1 -0
- package/dist/helpers/UserSimulationHelper.d.ts +1 -1
- package/dist/helpers/UserSimulationHelper.js +10 -6
- package/dist/helpers/UserSimulationHelper.js.map +1 -1
- package/dist/helpers/index.d.ts +2 -0
- package/dist/helpers/index.js +3 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/index.d.ts +8 -12
- package/dist/index.js +9 -13
- package/dist/index.js.map +1 -1
- package/dist/package-lock.json +4087 -0
- package/dist/package.json +59 -0
- package/dist/page-extensions/GoToDeepLink.js +15 -1
- package/dist/page-extensions/GoToDeepLink.js.map +1 -1
- package/dist/page-extensions/LoginFeatures.d.ts +2 -1
- package/dist/page-extensions/LoginFeatures.js +3 -0
- package/dist/page-extensions/LoginFeatures.js.map +1 -1
- package/dist/page-extensions/WaitEventHandler.d.ts +12 -0
- package/dist/page-extensions/WaitEventHandler.js +15 -0
- package/dist/page-extensions/WaitEventHandler.js.map +1 -0
- package/dist/page-extensions/index.d.ts +3 -0
- package/dist/page-extensions/index.js +4 -0
- package/dist/page-extensions/index.js.map +1 -0
- package/dist/page-overrides/ClickOverride.d.ts +1 -0
- package/dist/page-overrides/ClickOverride.js +46 -25
- package/dist/page-overrides/ClickOverride.js.map +1 -1
- package/dist/page-overrides/FillOverride.d.ts +7 -0
- package/dist/page-overrides/FillOverride.js +106 -0
- package/dist/page-overrides/FillOverride.js.map +1 -0
- package/dist/page-overrides/index.d.ts +1 -0
- package/dist/page-overrides/index.js +2 -0
- package/dist/page-overrides/index.js.map +1 -0
- package/dist/scripts/Testwise.template.json +25 -0
- package/dist/scripts/tsconfig.template.json +12 -0
- package/dist/services/ConfigBuilder.js +25 -2
- package/dist/services/ConfigBuilder.js.map +1 -1
- package/dist/services/Logger.d.ts +1 -2
- package/dist/services/Logger.js +69 -15
- package/dist/services/Logger.js.map +1 -1
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +2 -0
- package/dist/services/index.js.map +1 -0
- package/dist/tsconfig.json +20 -0
- package/dist/types/PollTypes.d.ts +6 -0
- package/dist/types/PollTypes.js +2 -0
- package/dist/types/PollTypes.js.map +1 -0
- package/dist/types/Universal.js +2 -0
- package/dist/types/Universal.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/enums/LogLevel.ts +2 -3
- package/enums/index.ts +1 -0
- package/example-code/TestifyService.ts +26 -12
- package/helpers/Ensure.ts +9 -0
- package/helpers/FlightTracker.ts +26 -0
- package/helpers/GlobalWaitEventHandler.ts +66 -0
- package/helpers/LoginHelper.ts +20 -8
- package/helpers/Poll.ts +19 -0
- package/helpers/RegexHelper.ts +17 -0
- package/helpers/UserSimulationHelper.ts +11 -6
- package/helpers/index.ts +2 -0
- package/index.ts +9 -13
- package/package.json +24 -8
- package/page-extensions/GoToDeepLink.ts +17 -1
- package/page-extensions/LoginFeatures.ts +6 -1
- package/page-extensions/WaitEventHandler.ts +26 -0
- package/page-extensions/index.ts +3 -0
- package/page-overrides/ClickOverride.ts +60 -26
- package/page-overrides/FillOverride.ts +133 -0
- package/page-overrides/index.ts +1 -0
- package/promptCredentials.js +124 -113
- package/scripts/Testwise.template.json +4 -1
- package/scripts/main.js +11 -0
- package/scripts/setup.js +34 -0
- package/scripts/tsconfig.template.json +12 -0
- package/services/ConfigBuilder.ts +29 -2
- package/services/Logger.ts +73 -15
- package/services/index.ts +1 -0
- package/tsconfig.json +20 -0
- package/types/PollTypes.ts +6 -0
- package/types/index.ts +2 -0
- package/.ci/azure-pipelines.yaml +0 -80
- package/.eslintcache +0 -1
- package/.gitattributes +0 -3
- package/.gitconfig +0 -2
- package/.vscode/settings.json +0 -20
- package/components/tab/Tab.ts +0 -29
- package/components/task/TaskTiles.ts +0 -11
- package/dist/components/pop-up/PopUpComponentModels.js.map +0 -1
- package/dist/enums/ActionbarRegions.d.ts +0 -5
- package/dist/enums/ActionbarRegions.js +0 -7
- package/dist/enums/ActionbarRegions.js.map +0 -1
- package/dist/enums/ButtonEnums.d.ts +0 -24
- package/dist/enums/ButtonEnums.js +0 -29
- package/dist/enums/ButtonEnums.js.map +0 -1
- package/dist/helpers/InflightRequestTracker.d.ts +0 -10
- package/dist/helpers/InflightRequestTracker.js +0 -26
- package/dist/helpers/InflightRequestTracker.js.map +0 -1
- package/dist/types/universal.js +0 -2
- package/dist/types/universal.js.map +0 -1
- package/enums/ActionbarRegions.ts +0 -5
- package/enums/ButtonEnums.ts +0 -28
- package/helpers/InflightRequestTracker.ts +0 -33
- package/scripts/add-config.js +0 -23
- /package/components/pop-up/{PopUpComponentModels.ts → PopUpComponentObjects.ts} +0 -0
- /package/dist/components/pop-up/{PopUpComponentModels.d.ts → PopUpComponentObjects.d.ts} +0 -0
- /package/dist/types/{universal.d.ts → Universal.d.ts} +0 -0
- /package/types/{universal.ts → Universal.ts} +0 -0
package/dist/services/Logger.js
CHANGED
|
@@ -4,6 +4,42 @@ import { LogLevel } from '../enums/LogLevel.js';
|
|
|
4
4
|
import { originalDebug, originalError, originalInfo, originalLog, originalWarn } from '../index.js';
|
|
5
5
|
import { testwiseConfig } from './ConfigBuilder.js';
|
|
6
6
|
const logDir = path.resolve(process.cwd(), testwiseConfig().get('featureSettings.logger.logDir') ?? 'logs');
|
|
7
|
+
const logLevel = testwiseConfig().get('featureSettings.logger.logLevel')?.toUpperCase() ?? LogLevel.ALL;
|
|
8
|
+
const applyLogLevelToConsoleOutput = testwiseConfig().get('featureSettings.logger.applyLogLevelToConsoleOutput') ?? false;
|
|
9
|
+
let logErrors = false;
|
|
10
|
+
let logWarnings = false;
|
|
11
|
+
let logInfo = false;
|
|
12
|
+
let logDebug = false;
|
|
13
|
+
let logLog = false;
|
|
14
|
+
switch (logLevel) {
|
|
15
|
+
case LogLevel.ERROR:
|
|
16
|
+
logErrors = true;
|
|
17
|
+
break;
|
|
18
|
+
case LogLevel.WARN:
|
|
19
|
+
logErrors = true;
|
|
20
|
+
logWarnings = true;
|
|
21
|
+
break;
|
|
22
|
+
case LogLevel.INFO:
|
|
23
|
+
logErrors = true;
|
|
24
|
+
logWarnings = true;
|
|
25
|
+
logInfo = true;
|
|
26
|
+
break;
|
|
27
|
+
case LogLevel.DEBUG:
|
|
28
|
+
logErrors = true;
|
|
29
|
+
logWarnings = true;
|
|
30
|
+
logInfo = true;
|
|
31
|
+
logDebug = true;
|
|
32
|
+
break;
|
|
33
|
+
case LogLevel.ALL:
|
|
34
|
+
logErrors = true;
|
|
35
|
+
logWarnings = true;
|
|
36
|
+
logInfo = true;
|
|
37
|
+
logDebug = true;
|
|
38
|
+
logLog = true;
|
|
39
|
+
break;
|
|
40
|
+
default:
|
|
41
|
+
throw new Error(`Unknown log level: ${logLevel}`);
|
|
42
|
+
}
|
|
7
43
|
fs.mkdirSync(logDir, { recursive: true });
|
|
8
44
|
const sanitizedTimestamp = new Date().toISOString().split('T')[0];
|
|
9
45
|
const logFilePath = path.join(logDir, testwiseConfig().get('featureSettings.logger.logByDay') === true
|
|
@@ -11,11 +47,11 @@ const logFilePath = path.join(logDir, testwiseConfig().get('featureSettings.logg
|
|
|
11
47
|
: 'test-log.log');
|
|
12
48
|
let logBuffer = [];
|
|
13
49
|
const bufferSizeLimit = testwiseConfig().get('featureSettings.logger.bufferSizeLimit') ?? 1000;
|
|
14
|
-
let
|
|
50
|
+
let _linesAlreadyWritten = 0;
|
|
15
51
|
if (fs.existsSync(logFilePath)) {
|
|
16
52
|
const existingLogs = fs.readFileSync(logFilePath, 'utf-8').split('\n').filter(Boolean);
|
|
17
53
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
18
|
-
|
|
54
|
+
_linesAlreadyWritten = existingLogs.length;
|
|
19
55
|
}
|
|
20
56
|
/**
|
|
21
57
|
* Flushes the log buffer to the log file.
|
|
@@ -44,30 +80,49 @@ function flushLogs() {
|
|
|
44
80
|
* @param level
|
|
45
81
|
* @param optionalParams
|
|
46
82
|
*/
|
|
47
|
-
function log(message, level = LogLevel.
|
|
83
|
+
function log(message, level = LogLevel.ALL, ...optionalParams) {
|
|
48
84
|
const timestamp = new Date().toISOString();
|
|
49
85
|
const origin = getCallerInfo();
|
|
50
86
|
const formatted = `[${timestamp}] [${level}] [${origin}] ${message}`;
|
|
51
87
|
switch (level) {
|
|
52
|
-
case LogLevel.FATAL:
|
|
53
88
|
case LogLevel.ERROR:
|
|
54
|
-
|
|
89
|
+
if (logErrors) {
|
|
90
|
+
logBuffer.push(`${formatted} ${optionalParams}`);
|
|
91
|
+
}
|
|
92
|
+
if (logErrors || !applyLogLevelToConsoleOutput)
|
|
93
|
+
originalError(formatted, ...optionalParams);
|
|
55
94
|
break;
|
|
56
95
|
case LogLevel.WARN:
|
|
57
|
-
|
|
96
|
+
if (logWarnings) {
|
|
97
|
+
logBuffer.push(`${formatted} ${optionalParams}`);
|
|
98
|
+
}
|
|
99
|
+
if (logWarnings || !applyLogLevelToConsoleOutput)
|
|
100
|
+
originalWarn(formatted, ...optionalParams);
|
|
58
101
|
break;
|
|
59
102
|
case LogLevel.DEBUG:
|
|
60
|
-
|
|
103
|
+
if (logDebug) {
|
|
104
|
+
logBuffer.push(`${formatted} ${optionalParams}`);
|
|
105
|
+
}
|
|
106
|
+
if (logDebug || !applyLogLevelToConsoleOutput)
|
|
107
|
+
originalDebug(formatted, ...optionalParams);
|
|
61
108
|
break;
|
|
62
109
|
case LogLevel.INFO:
|
|
63
|
-
|
|
110
|
+
if (logInfo) {
|
|
111
|
+
logBuffer.push(`${formatted} ${optionalParams}`);
|
|
112
|
+
}
|
|
113
|
+
if (logInfo || !applyLogLevelToConsoleOutput)
|
|
114
|
+
originalInfo(formatted, ...optionalParams);
|
|
64
115
|
break;
|
|
65
116
|
default:
|
|
66
|
-
|
|
67
|
-
|
|
117
|
+
if (logLog) {
|
|
118
|
+
logBuffer.push(`${formatted} ${optionalParams}`);
|
|
119
|
+
}
|
|
120
|
+
if (logLog || !applyLogLevelToConsoleOutput)
|
|
121
|
+
originalLog(formatted, ...optionalParams);
|
|
122
|
+
}
|
|
123
|
+
if (logBuffer.length >= bufferSizeLimit) {
|
|
124
|
+
flushLogs();
|
|
68
125
|
}
|
|
69
|
-
logBuffer.push(`${formatted} ${optionalParams}`);
|
|
70
|
-
flushLogs();
|
|
71
126
|
}
|
|
72
127
|
/**
|
|
73
128
|
* Retrieves the caller information from the stack trace.
|
|
@@ -96,11 +151,10 @@ function getCallerInfo() {
|
|
|
96
151
|
}
|
|
97
152
|
export const logger = {
|
|
98
153
|
// Order by severity level
|
|
99
|
-
fatal: (msg, ...optionalParams) => log(msg, LogLevel.FATAL, ...optionalParams),
|
|
100
154
|
error: (msg, ...optionalParams) => log(msg, LogLevel.ERROR, ...optionalParams),
|
|
101
155
|
warn: (msg, ...optionalParams) => log(msg, LogLevel.WARN, ...optionalParams),
|
|
102
|
-
step: (msg, ...optionalParams) => log(msg, LogLevel.STEP, ...optionalParams),
|
|
103
156
|
info: (msg, ...optionalParams) => log(msg, LogLevel.INFO, ...optionalParams),
|
|
104
|
-
debug: (msg, ...optionalParams) => log(msg, LogLevel.DEBUG, ...optionalParams)
|
|
157
|
+
debug: (msg, ...optionalParams) => log(msg, LogLevel.DEBUG, ...optionalParams),
|
|
158
|
+
log: (msg, ...optionalParams) => log(msg, LogLevel.ALL, ...optionalParams)
|
|
105
159
|
};
|
|
106
160
|
//# sourceMappingURL=Logger.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Logger.js","sourceRoot":"","sources":["../../services/Logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACpG,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,CAAC,GAAG,CAAS,+BAA+B,CAAC,IAAI,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"Logger.js","sourceRoot":"","sources":["../../services/Logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ConfigBuilder.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../services/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "nodenext",
|
|
5
|
+
"moduleResolution": "nodenext",
|
|
6
|
+
"esModuleInterop": true,
|
|
7
|
+
"allowSyntheticDefaultImports": true,
|
|
8
|
+
"outDir": "dist",
|
|
9
|
+
"declaration": true,
|
|
10
|
+
"sourceMap": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"strict": true
|
|
14
|
+
},
|
|
15
|
+
"include": [
|
|
16
|
+
"**/*.ts",
|
|
17
|
+
"**/*.json"
|
|
18
|
+
],
|
|
19
|
+
"exclude": ["dist", "node_modules"]
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PollTypes.js","sourceRoot":"","sources":["../../types/PollTypes.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Universal.js","sourceRoot":"","sources":["../../types/Universal.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../types/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC"}
|
package/enums/LogLevel.ts
CHANGED
package/enums/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ExportFormat.js';
|
|
@@ -13,7 +13,7 @@ export class TestifyService {
|
|
|
13
13
|
constructor() {
|
|
14
14
|
this.token = `Bearer ${process.env.TESTIFY_TOKEN}`;
|
|
15
15
|
this.projectId = process.env.TESTIFY_PROJECT_ID || '';
|
|
16
|
-
// biome-ignore lint/style/noNonNullAssertion:
|
|
16
|
+
// biome-ignore lint/style/noNonNullAssertion: Acceptable technical debt
|
|
17
17
|
this.baseUrl = process.env.TESTIFY_BASE_URL!.replace(/\/$/, '');
|
|
18
18
|
this.axiosInstance = axios.create({
|
|
19
19
|
baseURL: this.baseUrl,
|
|
@@ -43,10 +43,15 @@ export class TestifyService {
|
|
|
43
43
|
private async getTestRunId(testRunName: string): Promise<string> {
|
|
44
44
|
try {
|
|
45
45
|
const url = `/api/v1/TestRun?projectId=${this.projectId}`;
|
|
46
|
-
const response = await this.axiosInstance.get(url, {
|
|
46
|
+
const response = await this.axiosInstance.get(url, {
|
|
47
|
+
headers: this.headers('text/plain')
|
|
48
|
+
});
|
|
47
49
|
const testRunList = response.data;
|
|
48
|
-
|
|
49
|
-
const found = testRunList.find(
|
|
50
|
+
|
|
51
|
+
const found = testRunList.find(
|
|
52
|
+
// biome-ignore lint/suspicious/noExplicitAny: Acceptable technical debt
|
|
53
|
+
(tr: any) => tr.name?.toLowerCase() === testRunName.toLowerCase()
|
|
54
|
+
);
|
|
50
55
|
return found?.id?.toString() ?? '';
|
|
51
56
|
} catch (err) {
|
|
52
57
|
console.error('getTestRunId failed:', err);
|
|
@@ -67,7 +72,9 @@ export class TestifyService {
|
|
|
67
72
|
private async getProjectName(): Promise<string> {
|
|
68
73
|
try {
|
|
69
74
|
const url = `/api/v1/Project/${this.projectId}`;
|
|
70
|
-
const response = await this.axiosInstance.get(url, {
|
|
75
|
+
const response = await this.axiosInstance.get(url, {
|
|
76
|
+
headers: this.headers('text/plain')
|
|
77
|
+
});
|
|
71
78
|
const project = response.data;
|
|
72
79
|
return project.name;
|
|
73
80
|
} catch (err) {
|
|
@@ -114,10 +121,15 @@ export class TestifyService {
|
|
|
114
121
|
private async getTestResultId(testCaseId: string): Promise<string> {
|
|
115
122
|
try {
|
|
116
123
|
const url = `/api/v1/Result?testRunId=${this.testRunId}`;
|
|
117
|
-
const response = await this.axiosInstance.get(url, {
|
|
124
|
+
const response = await this.axiosInstance.get(url, {
|
|
125
|
+
headers: this.headers('text/plain')
|
|
126
|
+
});
|
|
118
127
|
const results = response.data;
|
|
119
|
-
|
|
120
|
-
const found = results.find(
|
|
128
|
+
|
|
129
|
+
const found = results.find(
|
|
130
|
+
// biome-ignore lint/suspicious/noExplicitAny: Acceptable technical debt
|
|
131
|
+
(r: any) => r.testCaseId?.toString() === testCaseId
|
|
132
|
+
);
|
|
121
133
|
return found?.id?.toString() ?? '';
|
|
122
134
|
} catch (err) {
|
|
123
135
|
console.error('getTestResultId failed:', err);
|
|
@@ -128,7 +140,7 @@ export class TestifyService {
|
|
|
128
140
|
private async getTestCaseId(testCaseName: string): Promise<string> {
|
|
129
141
|
try {
|
|
130
142
|
const testCases = await this.getTestCases();
|
|
131
|
-
// biome-ignore lint/suspicious/noExplicitAny:
|
|
143
|
+
// biome-ignore lint/suspicious/noExplicitAny: Acceptable technical debt
|
|
132
144
|
const found = testCases.find((tc: any) => tc.name === testCaseName);
|
|
133
145
|
return found?.id?.toString() ?? '';
|
|
134
146
|
} catch (err) {
|
|
@@ -156,7 +168,7 @@ export class TestifyService {
|
|
|
156
168
|
}
|
|
157
169
|
}
|
|
158
170
|
|
|
159
|
-
// biome-ignore lint/suspicious/noExplicitAny:
|
|
171
|
+
// biome-ignore lint/suspicious/noExplicitAny: Acceptable technical debt
|
|
160
172
|
private testCaseExists(testCases: any[], testName: string): boolean {
|
|
161
173
|
try {
|
|
162
174
|
return testCases.some((tc) => tc.name?.toLowerCase() === testName.toLowerCase());
|
|
@@ -166,11 +178,13 @@ export class TestifyService {
|
|
|
166
178
|
}
|
|
167
179
|
}
|
|
168
180
|
|
|
169
|
-
// biome-ignore lint/suspicious/noExplicitAny:
|
|
181
|
+
// biome-ignore lint/suspicious/noExplicitAny: Acceptable technical debt
|
|
170
182
|
private async getTestCases(): Promise<any[]> {
|
|
171
183
|
try {
|
|
172
184
|
const url = `/api/v1/TestCase?projectId=${this.projectId}`;
|
|
173
|
-
const response = await this.axiosInstance.get(url, {
|
|
185
|
+
const response = await this.axiosInstance.get(url, {
|
|
186
|
+
headers: this.headers('text/plain')
|
|
187
|
+
});
|
|
174
188
|
return response.data;
|
|
175
189
|
} catch (err) {
|
|
176
190
|
console.error('getTestCases failed:', err);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function ensure(condition: unknown, message = 'Check failed'): asserts condition {
|
|
2
|
+
if (!condition) throw new Error(message);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function ensureEqual<T>(actual: T, expected: T, label?: string) {
|
|
6
|
+
if (actual !== expected) {
|
|
7
|
+
throw new Error(label ? `${label}: expected ${expected}, got ${actual}` : `expected ${expected}, got ${actual}`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { testwiseConfig } from '../services/ConfigBuilder.js';
|
|
3
|
+
|
|
4
|
+
const timeout = testwiseConfig().get<number>('featureSettings.InflightRequests.waitTimeout') ?? 5000;
|
|
5
|
+
|
|
6
|
+
export class FlightTracker {
|
|
7
|
+
public requestsInFlight: number = 0;
|
|
8
|
+
public eventEmitter: EventEmitter = new EventEmitter();
|
|
9
|
+
|
|
10
|
+
public waitToContinue = async (): Promise<void> => {
|
|
11
|
+
if (this.requestsInFlight === 0) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
await Promise.race([
|
|
16
|
+
new Promise<void>((resolve) => {
|
|
17
|
+
this.eventEmitter.once('idle', resolve);
|
|
18
|
+
}),
|
|
19
|
+
new Promise<void>((_, reject) => {
|
|
20
|
+
setTimeout(() => {
|
|
21
|
+
reject(new Error('Timeout waiting for requests to complete'));
|
|
22
|
+
}, timeout);
|
|
23
|
+
})
|
|
24
|
+
]);
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import type { Page, Response } from '@playwright/test';
|
|
3
|
+
import { testwiseConfig } from '../services/ConfigBuilder.js';
|
|
4
|
+
|
|
5
|
+
export class GlobalWaitEventHandler {
|
|
6
|
+
private _canContinue: boolean = true;
|
|
7
|
+
private _eventEmitter: EventEmitter = new EventEmitter();
|
|
8
|
+
private _page: Page;
|
|
9
|
+
private _timeout = testwiseConfig().get<number>('featureSettings.InflightRequests.waitTimeout') ?? 5000;
|
|
10
|
+
|
|
11
|
+
constructor(page: Page) {
|
|
12
|
+
this._eventEmitter.on('continue', () => {
|
|
13
|
+
this._canContinue = true;
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
this._page = page;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private withTimeout(promise: Promise<void>, message: string): Promise<void> {
|
|
20
|
+
return new Promise((resolve) => {
|
|
21
|
+
const timeout = setTimeout(() => {
|
|
22
|
+
console.warn(message);
|
|
23
|
+
this._eventEmitter.emit('continue');
|
|
24
|
+
resolve();
|
|
25
|
+
}, this._timeout);
|
|
26
|
+
|
|
27
|
+
promise.finally(() => clearTimeout(timeout)).then(resolve);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public waitForResponse(url: string): Promise<void> {
|
|
32
|
+
this._canContinue = false;
|
|
33
|
+
|
|
34
|
+
const responsePromise = new Promise<void>((resolve) => {
|
|
35
|
+
const listener = (result: Response) => {
|
|
36
|
+
if (result.url().includes(url)) {
|
|
37
|
+
this._page.off('response', listener);
|
|
38
|
+
this._canContinue = true;
|
|
39
|
+
this._eventEmitter.emit('continue');
|
|
40
|
+
resolve();
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
this._page.on('response', listener);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return this.withTimeout(responsePromise, 'Timeout reached while waiting for response. Proceeding anyway.');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public waitForCanContinue(): Promise<void> {
|
|
50
|
+
if (this._canContinue) return Promise.resolve();
|
|
51
|
+
|
|
52
|
+
const continuePromise = new Promise<void>((resolve) => {
|
|
53
|
+
this._eventEmitter.once('continue', resolve);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return this.withTimeout(continuePromise, 'Timeout reached while waiting for continue. Proceeding anyway.');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public setCanContinue(value: boolean): void {
|
|
60
|
+
this._canContinue = value;
|
|
61
|
+
|
|
62
|
+
if (value) {
|
|
63
|
+
this._eventEmitter.emit('continue');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
package/helpers/LoginHelper.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import {
|
|
4
|
+
import type { Page } from '@playwright/test';
|
|
5
5
|
import { testwiseConfig } from '../services/ConfigBuilder.js';
|
|
6
|
-
import type { UniversalConfigOptions, UniversalLoginOptions } from '../types/
|
|
6
|
+
import type { UniversalConfigOptions, UniversalLoginOptions } from '../types/index.js';
|
|
7
|
+
import { pollUntil } from './Poll.js';
|
|
7
8
|
|
|
8
9
|
const _dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
10
|
const configFixture = JSON.parse(fs.readFileSync(path.resolve(_dirname, '../config.json'), 'utf-8'));
|
|
@@ -76,12 +77,13 @@ export class LoginHelper {
|
|
|
76
77
|
route.continue();
|
|
77
78
|
});
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
80
|
+
const timeout = Number(testwiseConfig().get<string | number>('featureSettings.other.loginTimeout') ?? 30_000);
|
|
81
|
+
|
|
82
|
+
await pollUntil(async () => this._page.url().includes('#application='), {
|
|
83
|
+
timeout,
|
|
84
|
+
interval: 200,
|
|
85
|
+
predicate: (ok: boolean) => ok === true
|
|
86
|
+
});
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
/**
|
|
@@ -146,4 +148,14 @@ export class LoginHelper {
|
|
|
146
148
|
});
|
|
147
149
|
});
|
|
148
150
|
}
|
|
151
|
+
|
|
152
|
+
public async logOut() {
|
|
153
|
+
const response = await this._page.request.post(`${this._serviceUrl}/account/api/logout`);
|
|
154
|
+
|
|
155
|
+
if (![204, 401].includes(response.status())) {
|
|
156
|
+
throw new Error(`Logout failed with status code: ${response.status()}`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
await this._page.context().clearCookies();
|
|
160
|
+
}
|
|
149
161
|
}
|
package/helpers/Poll.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { PollOptions } from '../types/PollTypes.ts';
|
|
2
|
+
|
|
3
|
+
export async function pollUntil<T>(fn: () => Promise<T> | T, opts: PollOptions<T> = {}): Promise<T> {
|
|
4
|
+
const timeout = opts.timeout ?? 10_000;
|
|
5
|
+
const interval = opts.interval ?? 200;
|
|
6
|
+
const ok = opts.predicate ?? ((v: T) => Boolean(v));
|
|
7
|
+
const start = Date.now();
|
|
8
|
+
|
|
9
|
+
while (true) {
|
|
10
|
+
const val = await fn();
|
|
11
|
+
if (ok(val)) return val;
|
|
12
|
+
|
|
13
|
+
opts.onTick?.(val, Date.now() - start);
|
|
14
|
+
if (Date.now() - start >= timeout) {
|
|
15
|
+
throw new Error(`pollUntil timeout after ${timeout}ms`);
|
|
16
|
+
}
|
|
17
|
+
await new Promise((r) => setTimeout(r, interval));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Escapes characters with special meaning in regexes.
|
|
2
|
+
export function escapeRegex(input: string): string {
|
|
3
|
+
return input.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// Exact match, case-insensitive, Unicode-safe.
|
|
7
|
+
// By default trims the input; set trim=false for truly literal.
|
|
8
|
+
export function exactTextRegex(input: string, opts?: { trim?: boolean; collapseWhitespace?: boolean }) {
|
|
9
|
+
const { trim = true, collapseWhitespace = false } = opts ?? {};
|
|
10
|
+
let s = trim ? input.trim() : input;
|
|
11
|
+
|
|
12
|
+
if (collapseWhitespace) {
|
|
13
|
+
// turn runs of whitespace into a single space to match UI normalization
|
|
14
|
+
s = s.replace(/\s+/g, ' ');
|
|
15
|
+
}
|
|
16
|
+
return new RegExp(`^${escapeRegex(s)}$`, 'iu'); // i = case-insensitive, u = Unicode
|
|
17
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Page } from '@playwright/test';
|
|
2
2
|
import { testwiseConfig } from '../services/ConfigBuilder.js';
|
|
3
|
+
import { pollUntil } from './Poll.js';
|
|
3
4
|
|
|
4
5
|
export class UserSimulationHelper {
|
|
5
6
|
private _page: Page;
|
|
@@ -24,12 +25,12 @@ export class UserSimulationHelper {
|
|
|
24
25
|
|
|
25
26
|
switch (response.status()) {
|
|
26
27
|
case 204:
|
|
27
|
-
console.error('User simulation not active',
|
|
28
|
+
console.error('User simulation not active', response.status());
|
|
28
29
|
return '';
|
|
29
30
|
case 200:
|
|
30
31
|
return (await response.json()).simulated_user;
|
|
31
32
|
default:
|
|
32
|
-
throw new Error(`Get simulated user request failed with status: ${
|
|
33
|
+
throw new Error(`Get simulated user request failed with status: ${response.status()}`);
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
|
|
@@ -40,12 +41,16 @@ export class UserSimulationHelper {
|
|
|
40
41
|
const response = await this._page.request.delete(`${this._serviceUrl}/account/api/usersimulation`);
|
|
41
42
|
|
|
42
43
|
if (response.status() === 204) {
|
|
43
|
-
console.info('STOP User simulation request is successful',
|
|
44
|
+
console.info('STOP User simulation request is successful', response.status());
|
|
44
45
|
} else {
|
|
45
|
-
throw new Error(`STOP User simulation has unexpected status: ${
|
|
46
|
+
throw new Error(`STOP User simulation has unexpected status: ${response.status()}`);
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
await
|
|
49
|
+
await pollUntil(() => this.getSimulatedUser(), {
|
|
50
|
+
timeout: 5_000,
|
|
51
|
+
interval: 200,
|
|
52
|
+
predicate: (val) => val === ''
|
|
53
|
+
});
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
/**
|
package/helpers/index.ts
ADDED
package/index.ts
CHANGED
|
@@ -6,23 +6,19 @@ const originalWarn = console.warn;
|
|
|
6
6
|
const originalError = console.error;
|
|
7
7
|
const originalDebug = console.debug;
|
|
8
8
|
|
|
9
|
-
console.log = (...args: unknown[]) => logger.
|
|
9
|
+
console.log = (...args: unknown[]) => logger.log(args.join(' '));
|
|
10
10
|
console.info = (...args: unknown[]) => logger.info(args.join(' '));
|
|
11
11
|
console.warn = (...args: unknown[]) => logger.warn(args.join(' '));
|
|
12
12
|
console.error = (...args: unknown[]) => logger.error(args.join(' '));
|
|
13
13
|
console.debug = (...args: unknown[]) => logger.debug(args.join(' '));
|
|
14
14
|
|
|
15
15
|
export { originalLog, originalInfo, originalWarn, originalError, originalDebug };
|
|
16
|
-
export * from './services/ConfigBuilder.js';
|
|
17
|
-
export * from './Testwise.js';
|
|
18
|
-
export * from './helpers/LoginHelper.js';
|
|
19
|
-
export * from './page-extensions/GoToDeepLink.js';
|
|
20
|
-
export * from './page-extensions/LoginFeatures.js';
|
|
21
|
-
export * from './page-extensions/UserSimulation.js';
|
|
22
|
-
export * from './page-overrides/ClickOverride.js';
|
|
23
|
-
export * from './types/CoreTypes.js';
|
|
24
|
-
export * from './types/universal.js';
|
|
25
|
-
export * from './enums/ButtonEnums.js';
|
|
26
|
-
export * from './enums/ActionbarRegions.js';
|
|
27
|
-
export * from './enums/ExportFormat.js';
|
|
28
16
|
export * from './components/index.js';
|
|
17
|
+
export * from './controls/index.js';
|
|
18
|
+
export * from './enums/index.js';
|
|
19
|
+
export * from './helpers/index.js';
|
|
20
|
+
export * from './page-extensions/index.js';
|
|
21
|
+
export * from './page-overrides/index.js';
|
|
22
|
+
export * from './services/index.js';
|
|
23
|
+
export * from './Testwise.js';
|
|
24
|
+
export * from './types/index.js';
|