@boltic/cli 1.0.6-beta.11 → 1.0.6-beta.14

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.
@@ -34,8 +34,12 @@ const commands = {
34
34
  description: "Edit an existing integration",
35
35
  action: handleEdit,
36
36
  },
37
+ submit: {
38
+ description: "Submit an integration for review",
39
+ action: handleSubmit,
40
+ },
37
41
  publish: {
38
- description: "Publish an integration",
42
+ description: "Publish an integration (deprecated, use submit)",
39
43
  action: handlePublish,
40
44
  },
41
45
  sync: {
@@ -51,7 +55,7 @@ const commands = {
51
55
  action: handleStatus,
52
56
  },
53
57
  test: {
54
- description: "Run tests for the integration",
58
+ description: "Run tests for the integration with coverage",
55
59
  action: handleTest,
56
60
  },
57
61
  help: {
@@ -236,8 +240,8 @@ async function handleSync(args) {
236
240
  }
237
241
 
238
242
  // Publish an integration
239
- async function handlePublish(args) {
240
- console.log(chalk.green("Publishing integration...\n"));
243
+ async function handleSubmit(args) {
244
+ console.log(chalk.green("Submitting integration for review...\n"));
241
245
  // Parse command line arguments
242
246
  let currentDir = process.cwd();
243
247
  const pathIndex = args.indexOf("--path");
@@ -347,18 +351,32 @@ async function handlePublish(args) {
347
351
  if (review) {
348
352
  console.log(
349
353
  chalk.green(
350
- "\n✅ Integration sent to review successfully!\n"
354
+ "\n✅ Integration submitted for review successfully!\n"
351
355
  )
352
356
  );
353
357
  }
354
358
  } else {
355
359
  console.error(
356
- chalk.red("\n❌ Error publishing integration:", data.message)
360
+ chalk.red("\n❌ Error submitting integration:", data.message)
357
361
  );
358
362
  }
359
363
  }
360
364
  }
361
365
 
366
+ async function handlePublish(args) {
367
+ console.log(
368
+ chalk.yellow(
369
+ "⚠️ WARNING: The 'publish' command is deprecated and will be removed in a future version."
370
+ )
371
+ );
372
+ console.log(
373
+ chalk.yellow("Please use 'boltic integration submit' instead.\n")
374
+ );
375
+
376
+ // Call the new submit function
377
+ await handleSubmit(args);
378
+ }
379
+
362
380
  // Execute the integration command
363
381
  const execute = async (args) => {
364
382
  const subCommand = args[0];
@@ -609,15 +627,15 @@ async function handleCreate() {
609
627
  create_catalogue
610
628
  );
611
629
 
612
- // Also share Documentation URL to the user: https://docs.boltic.io/docs/integration-builder/develop/boilerplate
613
630
  const documentationUrl =
614
631
  "https://docs.boltic.io/docs/integration-builder/develop/boilerplate";
632
+
615
633
  console.log(
616
634
  chalk.cyan(
617
- "\n📄 Documentation URL: " +
618
- chalk.underline.blue(documentationUrl)
635
+ `📄 For detailed instructions on next steps, refer to the official documentation:`
619
636
  )
620
637
  );
638
+ console.log(chalk.underline.blue(documentationUrl));
621
639
  }
622
640
  } catch (error) {
623
641
  console.error(
@@ -909,6 +927,26 @@ function showHelp() {
909
927
  Object.entries(commands).forEach(([cmd, details]) => {
910
928
  console.log(chalk.bold(`${cmd}`) + ` - ${details.description}`);
911
929
  });
930
+
931
+ console.log(chalk.cyan("\nTest Command Usage:"));
932
+ console.log(chalk.dim(" boltic integration test"));
933
+ console.log(chalk.dim(" boltic integration test --path /path/to/project"));
934
+ console.log(chalk.dim(" boltic integration test --config jest.config.js"));
935
+ console.log(chalk.dim(" boltic integration test --watchAll"));
936
+ console.log(chalk.dim(" boltic integration test --updateSnapshot"));
937
+
938
+ console.log(chalk.cyan("\nSupported Flags:"));
939
+ console.log(
940
+ chalk.dim(" --path <directory> Run tests in specific directory")
941
+ );
942
+ console.log(
943
+ chalk.dim(" --config <file> Use specific Jest config file")
944
+ );
945
+ console.log(
946
+ chalk.dim(" --watchAll Watch all files for changes")
947
+ );
948
+ console.log(chalk.dim(" --updateSnapshot Update snapshots"));
949
+ console.log(chalk.dim(" All other Jest CLI flags are supported"));
912
950
  }
913
951
 
914
952
  // Show detailed information about an integration
@@ -1036,7 +1074,9 @@ async function handleStatus() {
1036
1074
  async function handleTest(args) {
1037
1075
  // Parse command line arguments
1038
1076
  let currentDir = process.cwd();
1077
+ let jestConfigFile = null;
1039
1078
  const pathIndex = args.indexOf("--path");
1079
+ const configIndex = args.indexOf("--config");
1040
1080
 
1041
1081
  if (pathIndex !== -1 && args[pathIndex + 1]) {
1042
1082
  currentDir = args[pathIndex + 1];
@@ -1051,72 +1091,228 @@ async function handleTest(args) {
1051
1091
  }
1052
1092
  }
1053
1093
 
1094
+ if (configIndex !== -1 && args[configIndex + 1]) {
1095
+ jestConfigFile = args[configIndex + 1];
1096
+ // Validate the config file path
1097
+ const configPath = path.isAbsolute(jestConfigFile)
1098
+ ? jestConfigFile
1099
+ : path.join(currentDir, jestConfigFile);
1100
+
1101
+ if (!fs.existsSync(configPath)) {
1102
+ console.error(
1103
+ chalk.red(
1104
+ `Error: Jest config file does not exist: ${configPath}`
1105
+ )
1106
+ );
1107
+ return;
1108
+ }
1109
+ }
1110
+
1054
1111
  const { spawn } = await import("child_process");
1055
1112
 
1056
1113
  console.log(chalk.cyan.bold("\n🧪 Running integration tests...\n"));
1057
1114
 
1058
- // Look for test directory
1115
+ // Look for test directory and test files
1059
1116
  const testDirs = ["test", "tests", "__tests__"];
1060
1117
  let testDir = null;
1118
+ let testFiles = [];
1061
1119
 
1120
+ // Check for test directories
1062
1121
  for (const dir of testDirs) {
1063
- if (fs.existsSync(dir)) {
1122
+ const testPath = path.join(currentDir, dir);
1123
+ if (fs.existsSync(testPath)) {
1064
1124
  testDir = dir;
1125
+ // Find all test files in the directory
1126
+ const files = fs.readdirSync(testPath);
1127
+ testFiles = files.filter(
1128
+ (file) =>
1129
+ file.endsWith(".test.js") ||
1130
+ file.endsWith(".spec.js") ||
1131
+ file.endsWith(".test.ts") ||
1132
+ file.endsWith(".spec.ts")
1133
+ );
1065
1134
  break;
1066
1135
  }
1067
1136
  }
1068
1137
 
1138
+ // If no test directory found, look for test files in current directory
1069
1139
  if (!testDir) {
1140
+ const currentDirFiles = fs.readdirSync(currentDir);
1141
+ testFiles = currentDirFiles.filter(
1142
+ (file) =>
1143
+ file.endsWith(".test.js") ||
1144
+ file.endsWith(".spec.js") ||
1145
+ file.endsWith(".test.ts") ||
1146
+ file.endsWith(".spec.ts")
1147
+ );
1148
+
1149
+ if (testFiles.length === 0) {
1150
+ console.log(
1151
+ chalk.yellow(
1152
+ "⚠️ No test files found. Looked for: test, tests, __tests__ directories and *.test.js, *.spec.js, *.test.ts, *.spec.ts files"
1153
+ )
1154
+ );
1155
+ return;
1156
+ }
1157
+ }
1158
+
1159
+ if (testFiles.length === 0 && testDir) {
1070
1160
  console.log(
1071
1161
  chalk.yellow(
1072
- "⚠️ No test directory found. Looked for: test, tests, __tests__"
1162
+ `⚠️ No test files found in ${testDir} directory. Looking for: *.test.js, *.spec.js, *.test.ts, *.spec.ts files`
1073
1163
  )
1074
1164
  );
1075
1165
  return;
1076
1166
  }
1077
1167
 
1078
- console.log(chalk.dim(`📁 Found test directory: ${testDir}`));
1079
-
1080
- // Check if Jest is available
1081
- const packageJsonPath = path.join(process.cwd(), "package.json");
1082
- let hasJest = false;
1168
+ console.log(chalk.dim(`📁 Found test directory: ${testDir || currentDir}`));
1169
+ console.log(
1170
+ chalk.dim(
1171
+ `📋 Found ${testFiles.length} test file(s): ${testFiles.join(", ")}`
1172
+ )
1173
+ );
1174
+
1175
+ // Check for Jest configuration
1176
+ let jestConfigPath;
1177
+ if (jestConfigFile) {
1178
+ jestConfigPath = path.isAbsolute(jestConfigFile)
1179
+ ? jestConfigFile
1180
+ : path.join(currentDir, jestConfigFile);
1181
+ } else {
1182
+ // Look for default config files
1183
+ const defaultConfigs = [
1184
+ "jest.config.cjs",
1185
+ "jest.config.js",
1186
+ "jest.config.json",
1187
+ ];
1188
+ for (const configFile of defaultConfigs) {
1189
+ const configPath = path.join(currentDir, configFile);
1190
+ if (fs.existsSync(configPath)) {
1191
+ jestConfigPath = configPath;
1192
+ break;
1193
+ }
1194
+ }
1195
+ }
1083
1196
 
1084
- if (fs.existsSync(packageJsonPath)) {
1085
- try {
1086
- const packageJson = JSON.parse(
1087
- fs.readFileSync(packageJsonPath, "utf-8")
1088
- );
1089
- hasJest = !!(
1090
- packageJson.devDependencies?.jest ||
1091
- packageJson.dependencies?.jest
1197
+ const jestConfigExists = !!jestConfigPath;
1198
+ const configFileName = jestConfigPath
1199
+ ? path.basename(jestConfigPath)
1200
+ : null;
1201
+
1202
+ console.log(
1203
+ chalk.dim(
1204
+ `⚙️ Jest configuration: ${jestConfigExists ? `Found ${configFileName}` : "Using default configuration"}`
1205
+ )
1206
+ );
1207
+
1208
+ // Prepare Jest arguments
1209
+ const jestArgs = ["jest"];
1210
+
1211
+ // Add basic Jest flags
1212
+ jestArgs.push("--coverage");
1213
+ jestArgs.push("--verbose");
1214
+ jestArgs.push("--colors");
1215
+ jestArgs.push("--passWithNoTests");
1216
+
1217
+ // Add config file if exists, otherwise use simple patterns
1218
+ if (jestConfigExists) {
1219
+ jestArgs.push("--config", jestConfigPath);
1220
+ } else {
1221
+ // Use simple test matching patterns
1222
+ if (testDir) {
1223
+ jestArgs.push(
1224
+ "--testMatch",
1225
+ `**/${testDir}/**/*.{test,spec}.{js,ts}`
1092
1226
  );
1093
- } catch (error) {
1094
- console.log(chalk.yellow("⚠️ Could not read package.json"));
1227
+ } else {
1228
+ jestArgs.push("--testMatch", "**/*.{test,spec}.{js,ts}");
1095
1229
  }
1230
+ jestArgs.push("--collectCoverageFrom", "lib/**/*.{js,ts}");
1231
+ jestArgs.push("--collectCoverageFrom", "src/**/*.{js,ts}");
1232
+ jestArgs.push("--collectCoverageFrom", "*.{js,ts}");
1233
+ jestArgs.push("--coveragePathIgnorePatterns", "/node_modules/");
1234
+ jestArgs.push("--coveragePathIgnorePatterns", "/tests/");
1096
1235
  }
1097
1236
 
1098
- if (!hasJest) {
1237
+ // Add any additional Jest arguments passed by user
1238
+ const additionalArgs = args.filter((arg, index) => {
1239
+ // Skip our custom flags and their values
1240
+ if (arg === "--path" || arg === "--config") return false;
1241
+ if (args[index - 1] === "--path" || args[index - 1] === "--config")
1242
+ return false;
1243
+ return true;
1244
+ });
1245
+
1246
+ if (additionalArgs.length > 0) {
1247
+ jestArgs.push(...additionalArgs);
1099
1248
  console.log(
1100
- chalk.red(
1101
- "❌ Jest is not installed. Please install Jest to run tests."
1249
+ chalk.dim(
1250
+ `🔧 Additional Jest arguments: ${additionalArgs.join(" ")}`
1102
1251
  )
1103
1252
  );
1104
- return;
1105
1253
  }
1106
1254
 
1107
- // Run Jest with the test directory
1255
+ console.log(chalk.dim(`🚀 Running command: npx ${jestArgs.join(" ")}`));
1256
+ console.log(chalk.cyan("─".repeat(50)));
1257
+
1258
+ // Run Jest with coverage
1108
1259
  return new Promise((resolve, reject) => {
1109
- const jestProcess = spawn("npx", ["jest", testDir, "--verbose"], {
1260
+ const jestProcess = spawn("npx", jestArgs, {
1110
1261
  stdio: "inherit",
1111
1262
  shell: true,
1263
+ cwd: currentDir,
1112
1264
  });
1113
1265
 
1114
1266
  jestProcess.on("close", (code) => {
1267
+ console.log(chalk.cyan("─".repeat(50)));
1268
+
1115
1269
  if (code === 0) {
1116
1270
  console.log(chalk.green.bold("\n✅ All tests passed!"));
1271
+
1272
+ // Check for coverage directory
1273
+ const coverageDir = path.join(currentDir, "coverage");
1274
+ if (fs.existsSync(coverageDir)) {
1275
+ console.log(chalk.cyan("\n📊 Coverage Report Generated:"));
1276
+ console.log(chalk.dim(` Directory: ${coverageDir}`));
1277
+
1278
+ // Check for HTML report
1279
+ const htmlReportPath = path.join(
1280
+ coverageDir,
1281
+ "lcov-report",
1282
+ "index.html"
1283
+ );
1284
+ if (fs.existsSync(htmlReportPath)) {
1285
+ console.log(
1286
+ chalk.dim(` HTML Report: ${htmlReportPath}`)
1287
+ );
1288
+ }
1289
+
1290
+ // Check for text report
1291
+ const textReportPath = path.join(coverageDir, "lcov.info");
1292
+ if (fs.existsSync(textReportPath)) {
1293
+ console.log(
1294
+ chalk.dim(` LCOV Report: ${textReportPath}`)
1295
+ );
1296
+ }
1297
+ }
1298
+
1299
+ // Show test summary
1300
+ console.log(chalk.cyan("\n📋 Test Summary:"));
1301
+ console.log(chalk.dim(` Test files: ${testFiles.length}`));
1302
+ console.log(
1303
+ chalk.dim(` Test directory: ${testDir || currentDir}`)
1304
+ );
1305
+ console.log(chalk.green(" Status: PASSED"));
1117
1306
  } else {
1118
1307
  console.log(chalk.red.bold("\n❌ Some tests failed."));
1308
+ console.log(chalk.red(` Exit code: ${code}`));
1119
1309
  }
1310
+
1311
+ console.log(
1312
+ chalk.cyan(
1313
+ "\n💡 Tip: Check the coverage directory for detailed coverage reports"
1314
+ )
1315
+ );
1120
1316
  resolve(code);
1121
1317
  });
1122
1318