@dev-blinq/cucumber_client 1.0.1731-dev → 1.0.1733-dev
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.
|
@@ -100,18 +100,10 @@ class StepsDefinitions {
|
|
|
100
100
|
this.initPage(codePage, mjsFile);
|
|
101
101
|
}
|
|
102
102
|
let stepCount = Object.keys(this.steps).length;
|
|
103
|
-
if (this.steps["Before"])
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (this.steps["
|
|
107
|
-
stepCount--;
|
|
108
|
-
}
|
|
109
|
-
if (this.steps["BeforeAll"]) {
|
|
110
|
-
stepCount--;
|
|
111
|
-
}
|
|
112
|
-
if (this.steps["AfterAll"]) {
|
|
113
|
-
stepCount--;
|
|
114
|
-
}
|
|
103
|
+
if (this.steps["Before"]) stepCount--;
|
|
104
|
+
if (this.steps["After"]) stepCount--;
|
|
105
|
+
if (this.steps["BeforeAll"]) stepCount--;
|
|
106
|
+
if (this.steps["AfterAll"]) stepCount--;
|
|
115
107
|
if (print) {
|
|
116
108
|
logger.info("total steps definitions found", stepCount);
|
|
117
109
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export const FIXED_FOLDER_NAMES = {
|
|
2
|
+
STEP_DEFINITIONS: "step_definitions",
|
|
3
|
+
FEATURES: "features",
|
|
4
|
+
ASSETS: "assets",
|
|
5
|
+
TEMPLATES: "templates",
|
|
6
|
+
BLINQ_TEMP_ROUTES: "blinq_temp_routes",
|
|
7
|
+
DATA: "data",
|
|
8
|
+
ROUTES: "routes",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const FIXED_FILE_NAMES = {
|
|
12
|
+
UTILS: "utils.mjs",
|
|
13
|
+
UTILS_TEMPLATE: "utils_template.txt",
|
|
14
|
+
HOOKS_TEMPLATE: "_hooks_template.txt",
|
|
15
|
+
HOOKS: "_hooks.mjs",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const UTF8_ENCODING = "utf8";
|
|
19
|
+
|
|
20
|
+
export class UpdateStepDefinitionsError extends Error {
|
|
21
|
+
constructor({ type, message, statusCode = 500, meta } = {}) {
|
|
22
|
+
super(message);
|
|
23
|
+
|
|
24
|
+
this.name = "UpdateStepDefinitionsError";
|
|
25
|
+
this.type = type;
|
|
26
|
+
this.statusCode = statusCode;
|
|
27
|
+
this.meta = meta;
|
|
28
|
+
|
|
29
|
+
if (typeof Object.setPrototypeOf === "function") {
|
|
30
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export const SaveJobErrorType = {
|
|
35
|
+
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
36
|
+
STEP_ERROR: "STEP_ERROR",
|
|
37
|
+
GIT_ERROR: "GIT_ERROR",
|
|
38
|
+
UNKNOWN: "UNKNOWN",
|
|
39
|
+
INTERNAL_ERROR: "INTERNAL_ERROR",
|
|
40
|
+
STEP_DEFINITION_UPDATE_FAILED: "STEP_DEFINITION_UPDATE_FAILED",
|
|
41
|
+
FILE_SYSTEM_ERROR: "FILE_SYSTEM_ERROR",
|
|
42
|
+
STEP_DEFINITIONS_LOADING_FAILED: "STEP_DEFINITIONS_LOADING_FAILED",
|
|
43
|
+
STEP_COMMANDS_PROCESSING_FAILED: "STEP_COMMANDS_PROCESSING_FAILED",
|
|
44
|
+
STEP_INITIALIZATION_FAILED: "STEP_INITIALIZATION_FAILED",
|
|
45
|
+
};
|
|
@@ -11,6 +11,14 @@ import { generateApiCode } from "../code_gen/api_codegen.js";
|
|
|
11
11
|
import { tmpdir } from "node:os";
|
|
12
12
|
import { createHash } from "node:crypto";
|
|
13
13
|
import { getErrorMessage } from "../utils/socket_logger.js";
|
|
14
|
+
import {
|
|
15
|
+
FIXED_FILE_NAMES,
|
|
16
|
+
FIXED_FOLDER_NAMES,
|
|
17
|
+
SaveJobErrorType,
|
|
18
|
+
UpdateStepDefinitionsError,
|
|
19
|
+
UTF8_ENCODING,
|
|
20
|
+
} from "./constants.js";
|
|
21
|
+
import { handleFileInitOps, potentialErrorWrapper, processScenarioSteps, writeTemplateFiles } from "./utils.js";
|
|
14
22
|
|
|
15
23
|
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
|
|
16
24
|
|
|
@@ -454,7 +462,7 @@ export function getCodePage(stepDefsFilePath) {
|
|
|
454
462
|
return codePage;
|
|
455
463
|
}
|
|
456
464
|
// const templateFile = path.join(__dirname, "../../assets", "templates", "page_template.txt");
|
|
457
|
-
// const initialCode = readFileSync(templateFile,
|
|
465
|
+
// const initialCode = readFileSync(templateFile, UTF8_ENCODING);
|
|
458
466
|
const codePage = new CodePage();
|
|
459
467
|
codePage.generateModel();
|
|
460
468
|
return codePage;
|
|
@@ -508,6 +516,7 @@ export async function saveRecording({
|
|
|
508
516
|
stepsDefinitions,
|
|
509
517
|
parametersMap,
|
|
510
518
|
logger,
|
|
519
|
+
bvtSnapshotsDir,
|
|
511
520
|
}) {
|
|
512
521
|
if (step.commands && Array.isArray(step.commands)) {
|
|
513
522
|
step.commands = step.commands.map((cmd) => toRecordingStep(cmd, parametersMap, step.text));
|
|
@@ -762,7 +771,7 @@ const getLocatorsJson = (file) => {
|
|
|
762
771
|
return {};
|
|
763
772
|
}
|
|
764
773
|
try {
|
|
765
|
-
const locatorsJson = readFileSync(locatorsFilePath,
|
|
774
|
+
const locatorsJson = readFileSync(locatorsFilePath, UTF8_ENCODING);
|
|
766
775
|
return JSON.parse(locatorsJson);
|
|
767
776
|
} catch (error) {
|
|
768
777
|
console.error(error);
|
|
@@ -863,42 +872,104 @@ export async function executeStep({ stepsDefinitions, cucumberStep, context, cod
|
|
|
863
872
|
throw new Error(`Step definition not found for "${cucumberStep.text}"`);
|
|
864
873
|
}
|
|
865
874
|
}
|
|
866
|
-
class DomainError extends Error {
|
|
867
|
-
constructor(message) {
|
|
868
|
-
super(message);
|
|
869
|
-
this.name = this.constructor.name;
|
|
870
|
-
this.statusCode = 500; // default, can override in subclasses
|
|
871
|
-
if (typeof Object.setPrototypeOf === "function") {
|
|
872
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
export async function updateStepDefinitions({ scenario, featureName, projectDir, logger }) {
|
|
877
|
-
try {
|
|
878
|
-
const utilsFilePath = path.join(projectDir, "features", "step_definitions", "utils.mjs");
|
|
879
|
-
const stepDefinitionFolderPath = path.join(projectDir, "features", "step_definitions");
|
|
880
|
-
if (!existsSync(stepDefinitionFolderPath)) {
|
|
881
|
-
mkdirSync(stepDefinitionFolderPath, { recursive: true });
|
|
882
|
-
}
|
|
883
875
|
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
876
|
+
export async function updateStepDefinitionsOld({ scenario, featureName, projectDir, logger }) {
|
|
877
|
+
// set the candidate step definition file name
|
|
878
|
+
// set the utils file path
|
|
879
|
+
const utilsFilePath = path.join(projectDir, "features", "step_definitions", "utils.mjs");
|
|
880
|
+
const stepDefinitionFolderPath = path.join(projectDir, "features", "step_definitions");
|
|
881
|
+
if (!existsSync(stepDefinitionFolderPath)) {
|
|
882
|
+
mkdirSync(stepDefinitionFolderPath, { recursive: true });
|
|
883
|
+
}
|
|
884
|
+
const utilsTemplateFilePath = path.join(__dirname, "../../assets", "templates", "utils_template.txt");
|
|
885
|
+
const utilsContent = readFileSync(utilsTemplateFilePath, "utf8");
|
|
886
|
+
writeFileSync(utilsFilePath, utilsContent, "utf8");
|
|
887
|
+
const hooksTemplateFilePath = path.join(__dirname, "../../assets", "templates", "_hooks_template.txt");
|
|
888
|
+
if (existsSync(hooksTemplateFilePath)) {
|
|
889
|
+
const hooksFilePath = path.join(stepDefinitionFolderPath, "_hooks.mjs");
|
|
890
|
+
const hooksContent = readFileSync(hooksTemplateFilePath, "utf8");
|
|
891
|
+
writeFileSync(hooksFilePath, hooksContent, "utf8");
|
|
892
|
+
}
|
|
893
|
+
const steps = scenario.steps;
|
|
887
894
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
895
|
+
const stepsDefinitions = new StepsDefinitions(projectDir);
|
|
896
|
+
const featureFolder = path.join(projectDir, "features");
|
|
897
|
+
stepsDefinitions.load(false);
|
|
898
|
+
// const parameters = scenario.parameters;
|
|
899
|
+
// await saveRecordings({ steps, parameters, codePage, projectDir });
|
|
900
|
+
for (const step of steps) {
|
|
901
|
+
if (step.internalImplementedStepId) {
|
|
902
|
+
const si = steps.findIndex((s) => s.id === step.internalImplementedStepId);
|
|
903
|
+
if (si !== -1) {
|
|
904
|
+
step.isImplementedWhileRecording = true;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
if (!step.isUtilStep && ((step.isImplemented && !step.shouldOverride) || step.commands.length === 0)) {
|
|
908
|
+
let routesPath = path.join(tmpdir(), `blinq_temp_routes`);
|
|
909
|
+
if (process.env.TEMP_RUN === "true") {
|
|
910
|
+
if (existsSync(routesPath)) {
|
|
911
|
+
routesPath = path.join(tmpdir(), `blinq_temp_routes`);
|
|
912
|
+
rmSync(routesPath, { recursive: true });
|
|
913
|
+
}
|
|
914
|
+
mkdirSync(routesPath, { recursive: true });
|
|
915
|
+
saveRoutes({ step, folderPath: routesPath }, logger);
|
|
916
|
+
} else {
|
|
917
|
+
if (existsSync(routesPath)) {
|
|
918
|
+
try {
|
|
919
|
+
rmSync(routesPath, { recursive: true });
|
|
920
|
+
} catch (error) {
|
|
921
|
+
logger.error(`Error removing temp routes folder: ${getErrorMessage(error)}`);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
routesPath = path.join(projectDir, "data", "routes");
|
|
925
|
+
if (!existsSync(routesPath)) {
|
|
926
|
+
mkdirSync(routesPath, { recursive: true });
|
|
927
|
+
}
|
|
928
|
+
saveRoutes({ step, folderPath: routesPath }, logger);
|
|
929
|
+
}
|
|
930
|
+
if (step.commands && Array.isArray(step.commands)) {
|
|
931
|
+
step.commands = step.commands.map((cmd) => toRecordingStep(cmd, scenario.parametersMap));
|
|
932
|
+
}
|
|
933
|
+
continue;
|
|
934
|
+
}
|
|
935
|
+
const cucumberStep = getCucumberStep({ step });
|
|
936
|
+
const pageName = generatePageName(step.startFrame?.url ?? "default", step.isUtilStep);
|
|
937
|
+
const stepDefsFilePath = locateDefinitionPath(featureFolder, pageName);
|
|
938
|
+
let codePage = getCodePage(stepDefsFilePath);
|
|
939
|
+
codePage = await saveRecording({
|
|
940
|
+
step,
|
|
941
|
+
cucumberStep,
|
|
942
|
+
codePage,
|
|
943
|
+
projectDir,
|
|
944
|
+
stepsDefinitions,
|
|
945
|
+
parametersMap: scenario.parametersMap,
|
|
946
|
+
});
|
|
947
|
+
if (!codePage) {
|
|
948
|
+
continue;
|
|
949
|
+
}
|
|
950
|
+
const res = await codePage.save();
|
|
951
|
+
if (!res) {
|
|
952
|
+
throw new Error(`Failed to save step definition for "${cucumberStep.text}" in "${codePage.sourceFileName}"`);
|
|
893
953
|
}
|
|
954
|
+
}
|
|
955
|
+
writeFileSync(utilsFilePath, utilsContent, "utf8");
|
|
956
|
+
}
|
|
894
957
|
|
|
958
|
+
export async function updateStepDefinitions({ scenario, featureName, projectDir, logger, bvtSnapshotsDir }) {
|
|
959
|
+
try {
|
|
960
|
+
const { featureFolder, utilsFilePath, utilsContent } = handleFileInitOps(projectDir);
|
|
895
961
|
const steps = scenario.steps;
|
|
896
|
-
const stepsDefinitions = new StepsDefinitions(projectDir);
|
|
897
|
-
const featureFolder = path.join(projectDir, "features");
|
|
898
962
|
|
|
899
|
-
stepsDefinitions
|
|
963
|
+
const stepsDefinitions = new StepsDefinitions(projectDir);
|
|
964
|
+
await potentialErrorWrapper(
|
|
965
|
+
() => stepsDefinitions.load(false),
|
|
966
|
+
"Failed to load step definitions",
|
|
967
|
+
SaveJobErrorType.STEP_DEFINITIONS_LOADING_FAILED,
|
|
968
|
+
logger
|
|
969
|
+
);
|
|
900
970
|
|
|
901
|
-
|
|
971
|
+
for (let index = 0; index < steps.length; index++) {
|
|
972
|
+
const step = steps[index];
|
|
902
973
|
try {
|
|
903
974
|
if (step.internalImplementedStepId) {
|
|
904
975
|
const si = steps.findIndex((s) => s.id === step.internalImplementedStepId);
|
|
@@ -907,66 +978,104 @@ export async function updateStepDefinitions({ scenario, featureName, projectDir,
|
|
|
907
978
|
}
|
|
908
979
|
}
|
|
909
980
|
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
981
|
+
const processed = await potentialErrorWrapper(
|
|
982
|
+
() => {
|
|
983
|
+
if (!step.isUtilStep && ((step.isImplemented && !step.shouldOverride) || step.commands.length === 0)) {
|
|
984
|
+
let routesPath = path.join(tmpdir(), FIXED_FOLDER_NAMES.BLINQ_TEMP_ROUTES);
|
|
985
|
+
if (process.env.TEMP_RUN === "true") {
|
|
986
|
+
if (existsSync(routesPath)) rmSync(routesPath, { recursive: true });
|
|
987
|
+
mkdirSync(routesPath, { recursive: true });
|
|
988
|
+
saveRoutes({ step, folderPath: routesPath }, logger);
|
|
989
|
+
} else {
|
|
990
|
+
if (existsSync(routesPath)) {
|
|
991
|
+
try {
|
|
992
|
+
rmSync(routesPath, { recursive: true });
|
|
993
|
+
} catch (error) {
|
|
994
|
+
logger.error(`❌ Error removing temp routes folder: ${getErrorMessage(error)}`);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
routesPath = path.join(projectDir, FIXED_FOLDER_NAMES.DATA, FIXED_FOLDER_NAMES.ROUTES);
|
|
998
|
+
if (!existsSync(routesPath)) mkdirSync(routesPath, { recursive: true });
|
|
999
|
+
saveRoutes({ step, folderPath: routesPath }, logger);
|
|
922
1000
|
}
|
|
923
|
-
}
|
|
924
|
-
routesPath = path.join(projectDir, "data", "routes");
|
|
925
|
-
if (!existsSync(routesPath)) mkdirSync(routesPath, { recursive: true });
|
|
926
|
-
saveRoutes({ step, folderPath: routesPath }, logger);
|
|
927
|
-
}
|
|
928
1001
|
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
1002
|
+
if (step.commands && Array.isArray(step.commands)) {
|
|
1003
|
+
step.commands = step.commands.map((cmd) => toRecordingStep(cmd, scenario.parametersMap));
|
|
1004
|
+
}
|
|
932
1005
|
|
|
933
|
-
|
|
934
|
-
|
|
1006
|
+
return true;
|
|
1007
|
+
} else {
|
|
1008
|
+
return false;
|
|
1009
|
+
}
|
|
1010
|
+
},
|
|
1011
|
+
"Failed to process step commands and routes",
|
|
1012
|
+
SaveJobErrorType.STEP_COMMANDS_PROCESSING_FAILED,
|
|
1013
|
+
logger
|
|
1014
|
+
);
|
|
1015
|
+
if (processed) continue;
|
|
1016
|
+
|
|
1017
|
+
const { cucumberStep, stepDefsFilePath } = await potentialErrorWrapper(
|
|
1018
|
+
() => {
|
|
1019
|
+
const cucumberStep = getCucumberStep({ step });
|
|
1020
|
+
const pageName = generatePageName(step.startFrame?.url ?? "default", step.isUtilStep);
|
|
1021
|
+
const stepDefsFilePath = locateDefinitionPath(featureFolder, pageName);
|
|
1022
|
+
return { cucumberStep, stepDefsFilePath };
|
|
1023
|
+
},
|
|
1024
|
+
"Failed to initialize cucumber step and locate definition path",
|
|
1025
|
+
SaveJobErrorType.STEP_INITIALIZATION_FAILED,
|
|
1026
|
+
logger
|
|
1027
|
+
);
|
|
935
1028
|
|
|
936
|
-
const
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1029
|
+
const codePage = await potentialErrorWrapper(
|
|
1030
|
+
async () => {
|
|
1031
|
+
let codePage = getCodePage(stepDefsFilePath);
|
|
1032
|
+
codePage = await saveRecording({
|
|
1033
|
+
step,
|
|
1034
|
+
cucumberStep,
|
|
1035
|
+
codePage,
|
|
1036
|
+
projectDir,
|
|
1037
|
+
stepsDefinitions,
|
|
1038
|
+
parametersMap: scenario.parametersMap,
|
|
1039
|
+
bvtSnapshotsDir,
|
|
1040
|
+
});
|
|
1041
|
+
return codePage;
|
|
1042
|
+
},
|
|
1043
|
+
"Failed to generate and save step definition",
|
|
1044
|
+
SaveJobErrorType.STEP_DEFINITION_UPDATE_FAILED,
|
|
1045
|
+
logger
|
|
1046
|
+
);
|
|
949
1047
|
|
|
950
|
-
if (!codePage)
|
|
1048
|
+
if (!codePage) continue;
|
|
951
1049
|
|
|
952
1050
|
const res = await codePage.save();
|
|
953
1051
|
if (!res) {
|
|
954
|
-
throw new
|
|
955
|
-
|
|
956
|
-
|
|
1052
|
+
throw new UpdateStepDefinitionsError({
|
|
1053
|
+
type: SaveJobErrorType.STEP_DEFINITION_UPDATE_FAILED,
|
|
1054
|
+
message: `Failed to save step definition for "${cucumberStep.text}" in "${codePage.sourceFileName}"`,
|
|
1055
|
+
});
|
|
957
1056
|
}
|
|
958
1057
|
} catch (error) {
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1058
|
+
throw new UpdateStepDefinitionsError({
|
|
1059
|
+
type: SaveJobErrorType.STEP_DEFINITION_UPDATE_FAILED,
|
|
1060
|
+
message: "Failed to update step definition",
|
|
1061
|
+
meta: {
|
|
1062
|
+
stepIndex: index,
|
|
1063
|
+
stepText: step.text,
|
|
1064
|
+
reason: getErrorMessage(error),
|
|
1065
|
+
},
|
|
1066
|
+
});
|
|
963
1067
|
}
|
|
964
|
-
}
|
|
1068
|
+
}
|
|
965
1069
|
|
|
966
|
-
writeFileSync(utilsFilePath, utilsContent,
|
|
1070
|
+
writeFileSync(utilsFilePath, utilsContent, UTF8_ENCODING);
|
|
967
1071
|
} catch (error) {
|
|
968
1072
|
logger.error(`❌ updateStepDefinitions() failed: ${error?.message ?? String(error)}`);
|
|
969
|
-
throw error instanceof
|
|
1073
|
+
throw error instanceof UpdateStepDefinitionsError
|
|
1074
|
+
? error
|
|
1075
|
+
: new UpdateStepDefinitionsError({
|
|
1076
|
+
type: SaveJobErrorType.INTERNAL_ERROR,
|
|
1077
|
+
message: error?.message ?? "Unknown error",
|
|
1078
|
+
});
|
|
970
1079
|
}
|
|
971
1080
|
}
|
|
972
1081
|
|
|
@@ -1003,8 +1112,8 @@ export function saveRoutes({ step, folderPath }, logger) {
|
|
|
1003
1112
|
mkdirSync(folderPath, { recursive: true });
|
|
1004
1113
|
}
|
|
1005
1114
|
try {
|
|
1006
|
-
writeFileSync(routesFilePath, JSON.stringify(routesData, null, 2),
|
|
1115
|
+
writeFileSync(routesFilePath, JSON.stringify(routesData, null, 2), UTF8_ENCODING);
|
|
1007
1116
|
} catch (error) {
|
|
1008
|
-
logger.error(
|
|
1117
|
+
logger.error(`❌ Error saving routes to ${routesFilePath}: ${getErrorMessage(error)}`);
|
|
1009
1118
|
}
|
|
1010
1119
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { getErrorMessage } from "../utils/socket_logger.js";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import {
|
|
5
|
+
FIXED_FILE_NAMES,
|
|
6
|
+
FIXED_FOLDER_NAMES,
|
|
7
|
+
SaveJobErrorType,
|
|
8
|
+
UpdateStepDefinitionsError,
|
|
9
|
+
UTF8_ENCODING,
|
|
10
|
+
} from "./constants";
|
|
11
|
+
|
|
12
|
+
export function handleFileInitOps(projectDir) {
|
|
13
|
+
try {
|
|
14
|
+
const stepDefinitionFolderPath = path.join(
|
|
15
|
+
projectDir,
|
|
16
|
+
FIXED_FOLDER_NAMES.FEATURES,
|
|
17
|
+
FIXED_FOLDER_NAMES.STEP_DEFINITIONS
|
|
18
|
+
);
|
|
19
|
+
if (!existsSync(stepDefinitionFolderPath)) {
|
|
20
|
+
mkdirSync(stepDefinitionFolderPath, { recursive: true });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const utilsFilePath = path.join(
|
|
24
|
+
projectDir,
|
|
25
|
+
FIXED_FOLDER_NAMES.FEATURES,
|
|
26
|
+
FIXED_FOLDER_NAMES.STEP_DEFINITIONS,
|
|
27
|
+
FIXED_FILE_NAMES.UTILS
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const utilsTemplateFilePath = path.join(
|
|
31
|
+
__dirname,
|
|
32
|
+
`../../${FIXED_FOLDER_NAMES.ASSETS}`,
|
|
33
|
+
FIXED_FOLDER_NAMES.TEMPLATES,
|
|
34
|
+
FIXED_FILE_NAMES.UTILS_TEMPLATE
|
|
35
|
+
);
|
|
36
|
+
const utilsContent = readFileSync(utilsTemplateFilePath, UTF8_ENCODING);
|
|
37
|
+
writeFileSync(utilsFilePath, utilsContent, UTF8_ENCODING);
|
|
38
|
+
|
|
39
|
+
const hooksTemplateFilePath = path.join(
|
|
40
|
+
__dirname,
|
|
41
|
+
`../../${FIXED_FOLDER_NAMES.ASSETS}`,
|
|
42
|
+
FIXED_FOLDER_NAMES.TEMPLATES,
|
|
43
|
+
FIXED_FILE_NAMES.HOOKS_TEMPLATE
|
|
44
|
+
);
|
|
45
|
+
if (existsSync(hooksTemplateFilePath)) {
|
|
46
|
+
const hooksFilePath = path.join(stepDefinitionFolderPath, FIXED_FILE_NAMES.HOOKS);
|
|
47
|
+
const hooksContent = readFileSync(hooksTemplateFilePath, UTF8_ENCODING);
|
|
48
|
+
writeFileSync(hooksFilePath, hooksContent, UTF8_ENCODING);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const featureFolder = path.join(projectDir, FIXED_FOLDER_NAMES.FEATURES);
|
|
52
|
+
|
|
53
|
+
return { featureFolder, utilsFilePath, utilsContent };
|
|
54
|
+
} catch (error) {
|
|
55
|
+
throw new UpdateStepDefinitionsError({
|
|
56
|
+
type: SaveJobErrorType.FILE_SYSTEM_ERROR,
|
|
57
|
+
message: "Failed to initialize step definition folder structure",
|
|
58
|
+
meta: { reason: getErrorMessage(error) },
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export async function potentialErrorWrapper(fn, errorMessage, type, logger) {
|
|
64
|
+
try {
|
|
65
|
+
return await fn();
|
|
66
|
+
} catch (error) {
|
|
67
|
+
logger.error(`❌ ${errorMessage}: ${getErrorMessage(error)}`);
|
|
68
|
+
throw new UpdateStepDefinitionsError({
|
|
69
|
+
type: type,
|
|
70
|
+
message: errorMessage,
|
|
71
|
+
meta: { reason: getErrorMessage(error) },
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|