@activate-core/test-forge 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -22,6 +22,8 @@ import { runInit } from '../core/init.js';
22
22
  import { runSetup } from '../core/setup.js';
23
23
  import { runUpdate } from '../core/update.js';
24
24
  import { runEnvTemplate } from '../core/env-template.js';
25
+ import { loadConfig } from '../core/config.js';
26
+ import { dirname } from 'node:path';
25
27
  const command = process.argv[2];
26
28
  const useBasic = process.argv.includes('--basic');
27
29
  const force = process.argv.includes('--force');
@@ -39,6 +41,22 @@ function flagValue(name) {
39
41
  function sourceOptions() {
40
42
  return { reference: flagValue('--reference'), source: flagValue('--source') };
41
43
  }
44
+ /**
45
+ * The output dirs to scan for env vars the GENERATED suite reads (test
46
+ * output dirs + their sibling helpers/ + the seed dir). Shared by the
47
+ * `generate` and `env` commands so the example always reflects the suite.
48
+ */
49
+ function generatedScanDirs() {
50
+ const cfg = loadConfig();
51
+ const dirs = new Set();
52
+ for (const out of Object.values(cfg.testOutput ?? {})) {
53
+ dirs.add(out);
54
+ dirs.add(dirname(out));
55
+ }
56
+ if (cfg.seedOutput)
57
+ dirs.add(cfg.seedOutput);
58
+ return [...dirs];
59
+ }
42
60
  function printUsage() {
43
61
  console.log(`testforge v${VERSION}`);
44
62
  console.log('');
@@ -87,7 +105,7 @@ async function main() {
87
105
  console.log('then run `testforge generate`.');
88
106
  }
89
107
  else if (command === 'env') {
90
- runEnvTemplate('docs', '.env.testing.example');
108
+ runEnvTemplate('docs', '.env.testing.example', '.', generatedScanDirs());
91
109
  }
92
110
  else if (command === 'generate') {
93
111
  const useAI = !useBasic;
@@ -130,6 +148,11 @@ async function main() {
130
148
  if (seedFailures > 0) {
131
149
  console.log(`Warning: ${seedFailures} seed file(s) could not be generated — see notes above.`);
132
150
  }
151
+ // Auto-refresh the env template so running `generate` on its own (not
152
+ // just `setup`) tells the developer exactly which credentials the
153
+ // generated suite needs — including vars the tests themselves read.
154
+ console.log('');
155
+ runEnvTemplate('docs', '.env.testing.example', '.', generatedScanDirs());
133
156
  }
134
157
  }
135
158
  else {
@@ -55,7 +55,8 @@ const SOURCE_EXT = /\.(c|m)?[jt]sx?$/i;
55
55
  * skipping vendored/build/test output, with a file cap so a huge repo
56
56
  * can't stall the run.
57
57
  */
58
- function scanSourceEnvVars(srcDir, maxFiles = 4000) {
58
+ function scanSourceEnvVars(srcDir, opts = {}) {
59
+ const { includeTests = false, maxFiles = 4000 } = opts;
59
60
  const vars = new Set();
60
61
  let seen = 0;
61
62
  const walk = (dir) => {
@@ -78,8 +79,10 @@ function scanSourceEnvVars(srcDir, maxFiles = 4000) {
78
79
  walk(full);
79
80
  }
80
81
  else if (SOURCE_EXT.test(entry.name)) {
81
- // Skip test files — we want app source, not existing tests.
82
- if (/\.(test|spec)\./i.test(entry.name))
82
+ // App-source scan skips test files; the generated-suite scan
83
+ // (includeTests) WANTS them — that is where the tests' own env
84
+ // vars (tokens, ids, base URLs) live.
85
+ if (!includeTests && /\.(test|spec)\./i.test(entry.name))
83
86
  continue;
84
87
  seen++;
85
88
  try {
@@ -108,7 +111,7 @@ function areaAndJourney(file) {
108
111
  // Fallback: flat file with no area folder.
109
112
  return { area: 'general', journey: noExt };
110
113
  }
111
- export function runEnvTemplate(docsDir, outPath, srcDir = '.') {
114
+ export function runEnvTemplate(docsDir, outPath, srcDir = '.', testDirs = []) {
112
115
  if (!existsSync(docsDir)) {
113
116
  console.log(`No docs found at "${docsDir}". Run \`testforge setup\` first.`);
114
117
  return;
@@ -153,7 +156,21 @@ export function runEnvTemplate(docsDir, outPath, srcDir = '.') {
153
156
  }
154
157
  const sourceVars = scanSourceEnvVars(srcDir);
155
158
  const bootVars = [...sourceVars].filter((v) => !knownFromDocs.has(v)).sort();
156
- if (byArea.size === 0 && bootVars.length === 0) {
159
+ // Vars the GENERATED suite (tests + seeds + testkit) actually reads —
160
+ // scanned from the output dirs, INCLUDING test files. This is what
161
+ // captures tokens/ids/base-URLs the generated code needs but that no
162
+ // doc/source mentioned.
163
+ const suiteScan = new Set();
164
+ for (const d of testDirs) {
165
+ for (const v of scanSourceEnvVars(d, { includeTests: true })) {
166
+ suiteScan.add(v);
167
+ }
168
+ }
169
+ const alreadyShown = new Set([...knownFromDocs, ...bootVars]);
170
+ const suiteVars = [...suiteScan]
171
+ .filter((v) => !alreadyShown.has(v))
172
+ .sort();
173
+ if (byArea.size === 0 && bootVars.length === 0 && suiteVars.length === 0) {
157
174
  console.log('No environment variables found in the docs or source.');
158
175
  return;
159
176
  }
@@ -167,6 +184,15 @@ export function runEnvTemplate(docsDir, outPath, srcDir = '.') {
167
184
  '# Keep .env.testing OUT of version control.',
168
185
  '',
169
186
  ];
187
+ if (suiteVars.length > 0) {
188
+ lines.push(`# ${'='.repeat(40)}`);
189
+ lines.push('# GENERATED SUITE (env the generated tests/testkit read)');
190
+ lines.push(`# ${'='.repeat(40)}`);
191
+ for (const v of suiteVars) {
192
+ lines.push(`${v}= # used by: generated tests`);
193
+ }
194
+ lines.push('');
195
+ }
170
196
  if (bootVars.length > 0) {
171
197
  lines.push(`# ${'='.repeat(40)}`);
172
198
  lines.push('# APP (read directly from source — REQUIRED to boot)');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@activate-core/test-forge",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "AI-powered QA automation. Scans a project, drafts journey docs, and generates seeded Jest/Playwright tests. Works in any project, with any AI CLI.",
5
5
  "type": "module",
6
6
  "bin": {