flowstride 1.0.6 → 1.0.7
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/commands/run.js
CHANGED
|
@@ -73,11 +73,11 @@ async function runAction(targetPath, options) {
|
|
|
73
73
|
process.env.GITHUB_ACTIONS ||
|
|
74
74
|
process.env.GITLAB_CI ||
|
|
75
75
|
process.env.CIRCLECI ||
|
|
76
|
-
process.env.JENKINS_URL
|
|
76
|
+
process.env.JENKINS_URL ||
|
|
77
|
+
process.env.FLOWSTRIDE_API_KEY);
|
|
77
78
|
if (isCI) {
|
|
78
79
|
console.log("\n[CI/CD]: Environment detected. Engaging Smart Automation Behaviors...");
|
|
79
80
|
}
|
|
80
|
-
// The CLI (index.ts) now strictly guarantees targetPath is the absolute path to ./flows
|
|
81
81
|
const resolvedPath = targetPath;
|
|
82
82
|
if (!fs.existsSync(resolvedPath)) {
|
|
83
83
|
console.error(`\n[Error]: Cannot find strict target path "${resolvedPath}".`);
|
|
@@ -135,12 +135,13 @@ async function runAction(targetPath, options) {
|
|
|
135
135
|
let ActiveFlowWorker = flow_worker_1.FlowWorker;
|
|
136
136
|
let ActiveFlowOrchestrator = flow_orchestrator_1.FlowOrchestrator;
|
|
137
137
|
let engineMode = "Open Source";
|
|
138
|
-
// Check the local node_modules for the Pro engine
|
|
139
138
|
const proWorkerPath = path.join(process.cwd(), "node_modules", "@flowstride", "pro", "dist", "runner", "flow_worker.js");
|
|
140
139
|
const proOrchPath = path.join(process.cwd(), "node_modules", "@flowstride", "pro", "dist", "runner", "flow_orchestrator.js");
|
|
141
|
-
if (
|
|
140
|
+
// We only attempt to load the Pro Engine if the DRM Bouncer (index.ts) did NOT force OS Mode
|
|
141
|
+
if (!options.forceOS &&
|
|
142
|
+
fs.existsSync(proWorkerPath) &&
|
|
143
|
+
fs.existsSync(proOrchPath)) {
|
|
142
144
|
try {
|
|
143
|
-
// Dynamically load the Pro classes using native absolute URL resolution
|
|
144
145
|
const proWorkerModule = await import((0, url_1.pathToFileURL)(proWorkerPath).href);
|
|
145
146
|
const proOrchModule = await import((0, url_1.pathToFileURL)(proOrchPath).href);
|
|
146
147
|
ActiveFlowWorker = proWorkerModule.FlowWorker;
|
|
@@ -153,7 +154,6 @@ async function runAction(targetPath, options) {
|
|
|
153
154
|
}
|
|
154
155
|
console.log(`\n[Engine]: Booting Flowstride in ${engineMode} mode...`);
|
|
155
156
|
// ==========================================
|
|
156
|
-
// Instantiate the chosen engine (OS or Pro)
|
|
157
157
|
const worker = new ActiveFlowWorker(config, web, api, store, sessions, pluginManager);
|
|
158
158
|
const orchestrator = new ActiveFlowOrchestrator(worker, workerCount, config);
|
|
159
159
|
try {
|
package/dist/cli/index.js
CHANGED
|
@@ -44,15 +44,16 @@ const init_1 = require("./commands/init");
|
|
|
44
44
|
const fs = __importStar(require("fs"));
|
|
45
45
|
const path = __importStar(require("path"));
|
|
46
46
|
const os = __importStar(require("os"));
|
|
47
|
-
const
|
|
47
|
+
const tar = __importStar(require("tar"));
|
|
48
48
|
const prompts_1 = require("@inquirer/prompts");
|
|
49
49
|
const chalk_1 = __importDefault(require("chalk"));
|
|
50
50
|
const ora_1 = __importDefault(require("ora"));
|
|
51
51
|
const program = new commander_1.Command();
|
|
52
|
+
const API_BASE = process.env.FLOWSTRIDE_API_URL || "https://cloud.flowstride.io";
|
|
52
53
|
program
|
|
53
54
|
.name("flowstride")
|
|
54
55
|
.description("Flowstride: The Enterprise Flow-First Automation CLI")
|
|
55
|
-
.version("1.0.
|
|
56
|
+
.version("1.0.7");
|
|
56
57
|
program
|
|
57
58
|
.command("init")
|
|
58
59
|
.description("Initialise a new Flowstride workspace in the current directory")
|
|
@@ -63,18 +64,41 @@ program
|
|
|
63
64
|
.command("login")
|
|
64
65
|
.description("Authenticate this machine with Flowstride Enterprise Cloud")
|
|
65
66
|
.action(async () => {
|
|
67
|
+
const localPackageJsonPath = path.join(process.cwd(), "package.json");
|
|
68
|
+
if (!fs.existsSync(localPackageJsonPath)) {
|
|
69
|
+
console.error(chalk_1.default.red("✖ Error: Please navigate to a valid Flowstride project directory before logging in."));
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
const pkg = JSON.parse(fs.readFileSync(localPackageJsonPath, "utf8"));
|
|
73
|
+
const deps = {
|
|
74
|
+
...(pkg.dependencies || {}),
|
|
75
|
+
...(pkg.devDependencies || {}),
|
|
76
|
+
};
|
|
77
|
+
if (!deps["flowstride"] && !deps["flowstride-os"]) {
|
|
78
|
+
console.error(chalk_1.default.red("✖ Error: Please navigate to a valid Flowstride project directory before logging in."));
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
66
81
|
console.log(chalk_1.default.bold.blue("\n🌐 Flowstride Enterprise Cloud Sync\n"));
|
|
67
|
-
|
|
68
|
-
|
|
82
|
+
let authHeader = "";
|
|
83
|
+
if (process.env.FLOWSTRIDE_API_KEY) {
|
|
84
|
+
console.log(chalk_1.default.yellow("🤖 CI/CD Environment Detected. Authenticating via API Key..."));
|
|
85
|
+
authHeader = `Bearer ${process.env.FLOWSTRIDE_API_KEY}`;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
const userEmail = await (0, prompts_1.input)({
|
|
89
|
+
message: "Enter your Flowstride email:",
|
|
90
|
+
});
|
|
91
|
+
const userPass = await (0, prompts_1.password)({ message: "Enter your password:" });
|
|
92
|
+
authHeader = `Basic ${Buffer.from(`${userEmail}:${userPass}`).toString("base64")}`;
|
|
93
|
+
}
|
|
69
94
|
const deviceName = os.hostname();
|
|
70
95
|
const spinner = (0, ora_1.default)("Authenticating with Cloud...").start();
|
|
71
96
|
try {
|
|
72
|
-
const
|
|
73
|
-
const response = await fetch("https://cloud.flowstride.io/api/auth/cli-sync", {
|
|
97
|
+
const response = await fetch(`${API_BASE}/api/auth/cli-sync`, {
|
|
74
98
|
method: "POST",
|
|
75
99
|
headers: {
|
|
76
100
|
"Content-Type": "application/json",
|
|
77
|
-
Authorization:
|
|
101
|
+
Authorization: authHeader,
|
|
78
102
|
},
|
|
79
103
|
body: JSON.stringify({ deviceName }),
|
|
80
104
|
});
|
|
@@ -84,56 +108,61 @@ program
|
|
|
84
108
|
process.exit(1);
|
|
85
109
|
}
|
|
86
110
|
spinner.succeed(chalk_1.default.green("Authentication Successful!"));
|
|
87
|
-
const configDir = path.join(
|
|
111
|
+
const configDir = path.join(process.cwd(), ".flowstride", "login");
|
|
88
112
|
if (!fs.existsSync(configDir)) {
|
|
89
113
|
fs.mkdirSync(configDir, { recursive: true });
|
|
90
114
|
}
|
|
91
|
-
const credentialsPath = path.join(configDir, "
|
|
115
|
+
const credentialsPath = path.join(configDir, "login.json");
|
|
92
116
|
fs.writeFileSync(credentialsPath, JSON.stringify({
|
|
93
117
|
machineToken: data.machineToken,
|
|
94
118
|
workspaceId: data.workspaceId,
|
|
95
119
|
deviceName: deviceName,
|
|
96
120
|
syncedAt: new Date().toISOString(),
|
|
97
121
|
}, null, 2));
|
|
98
|
-
console.log(chalk_1.default.gray(`\nCredentials
|
|
122
|
+
console.log(chalk_1.default.gray(`\nCredentials securely scoped to ${credentialsPath}`));
|
|
99
123
|
console.log(chalk_1.default.bold.green(`\n✅ Machine synchronized with Flowstride Enterprise.`));
|
|
100
|
-
if (data.
|
|
124
|
+
if (data.isProEligible) {
|
|
101
125
|
console.log(chalk_1.default.yellow(`\n⚙️ System Check: You have access to Enterprise features (AI Healing, Parallel Workers).`));
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
!
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
126
|
+
const nodeModulesPath = path.join(process.cwd(), "node_modules", "@flowstride", "pro");
|
|
127
|
+
if (!fs.existsSync(nodeModulesPath)) {
|
|
128
|
+
let installPro = true;
|
|
129
|
+
if (!process.env.FLOWSTRIDE_API_KEY && !process.env.CI) {
|
|
130
|
+
installPro = await (0, prompts_1.confirm)({
|
|
131
|
+
message: "The Pro Engine is not installed in this project. Would you like Flowstride to automatically install it now?",
|
|
132
|
+
default: true,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
110
135
|
if (installPro) {
|
|
111
136
|
const installSpinner = (0, ora_1.default)("Downloading Enterprise Engine via secure proxy...").start();
|
|
112
137
|
const tarballPath = path.join(process.cwd(), "flowstride-pro.tgz");
|
|
113
138
|
try {
|
|
114
|
-
const tarballResponse = await fetch(
|
|
139
|
+
const tarballResponse = await fetch(`${API_BASE}/api/workspace/download-pro`, {
|
|
115
140
|
method: "GET",
|
|
116
|
-
headers: {
|
|
117
|
-
Authorization: `Bearer ${data.machineToken}`,
|
|
118
|
-
},
|
|
141
|
+
headers: { Authorization: `Bearer ${data.machineToken}` },
|
|
119
142
|
});
|
|
120
143
|
if (!tarballResponse.ok) {
|
|
121
144
|
throw new Error(`Secure proxy rejected request: ${tarballResponse.statusText}`);
|
|
122
145
|
}
|
|
123
146
|
const buffer = await tarballResponse.arrayBuffer();
|
|
124
147
|
fs.writeFileSync(tarballPath, Buffer.from(buffer));
|
|
125
|
-
installSpinner.
|
|
126
|
-
|
|
127
|
-
(
|
|
128
|
-
|
|
129
|
-
|
|
148
|
+
installSpinner.text = "Silently extracting Enterprise Engine...";
|
|
149
|
+
installSpinner.color = "cyan";
|
|
150
|
+
if (!fs.existsSync(nodeModulesPath)) {
|
|
151
|
+
fs.mkdirSync(nodeModulesPath, { recursive: true });
|
|
152
|
+
}
|
|
153
|
+
await tar.x({
|
|
154
|
+
file: tarballPath,
|
|
155
|
+
cwd: nodeModulesPath,
|
|
156
|
+
strip: 1,
|
|
130
157
|
});
|
|
131
|
-
|
|
158
|
+
installSpinner.succeed(chalk_1.default.green("Enterprise Engine installed successfully!"));
|
|
132
159
|
}
|
|
133
160
|
catch (installError) {
|
|
134
161
|
installSpinner.stop();
|
|
135
|
-
console.log(chalk_1.default.red("\n✖ Failed to install the Enterprise Engine
|
|
136
|
-
|
|
162
|
+
console.log(chalk_1.default.red("\n✖ Failed to install the Enterprise Engine. Please check your internet connection or verify your project configuration."));
|
|
163
|
+
if (fs.existsSync(nodeModulesPath)) {
|
|
164
|
+
fs.rmSync(nodeModulesPath, { recursive: true, force: true });
|
|
165
|
+
}
|
|
137
166
|
}
|
|
138
167
|
finally {
|
|
139
168
|
if (fs.existsSync(tarballPath)) {
|
|
@@ -152,6 +181,51 @@ program
|
|
|
152
181
|
process.exit(1);
|
|
153
182
|
}
|
|
154
183
|
});
|
|
184
|
+
program
|
|
185
|
+
.command("status")
|
|
186
|
+
.description("Display the current Flowstride CLI authentication and engine tier")
|
|
187
|
+
.action(async () => {
|
|
188
|
+
let token = process.env.FLOWSTRIDE_API_KEY || null;
|
|
189
|
+
const credentialsPath = path.join(process.cwd(), ".flowstride", "login", "login.json");
|
|
190
|
+
if (!token && fs.existsSync(credentialsPath)) {
|
|
191
|
+
try {
|
|
192
|
+
const credentials = JSON.parse(fs.readFileSync(credentialsPath, "utf8"));
|
|
193
|
+
token = credentials.machineToken;
|
|
194
|
+
}
|
|
195
|
+
catch (err) { }
|
|
196
|
+
}
|
|
197
|
+
if (!token) {
|
|
198
|
+
console.log(chalk_1.default.white("⚪ [OS]: (Local Mode / Not Logged In)"));
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
const response = await fetch(`${API_BASE}/api/auth/verify-cli`, {
|
|
203
|
+
method: "GET",
|
|
204
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
205
|
+
});
|
|
206
|
+
if (response.status === 401) {
|
|
207
|
+
console.log(chalk_1.default.red("🔴 AUTH EXPIRED: Your device session was revoked or expired."));
|
|
208
|
+
if (fs.existsSync(credentialsPath))
|
|
209
|
+
fs.unlinkSync(credentialsPath);
|
|
210
|
+
}
|
|
211
|
+
else if (response.ok) {
|
|
212
|
+
const data = await response.json();
|
|
213
|
+
const tier = data.tier.toUpperCase();
|
|
214
|
+
if (tier === "PERSONAL") {
|
|
215
|
+
console.log(chalk_1.default.yellow(`🟡 [OS]: [${data.workspaceName}] (Tier: PERSONAL)`));
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
console.log(chalk_1.default.green(`🟢 [PRO]: [${data.workspaceName}] (Tier: ${tier})`));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
console.log(chalk_1.default.yellow("🛜 OFFLINE: Unable to reach Flowstride Cloud. Enterprise Sync paused."));
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
console.log(chalk_1.default.yellow("🛜 OFFLINE: Unable to reach Flowstride Cloud. Enterprise Sync paused."));
|
|
227
|
+
}
|
|
228
|
+
});
|
|
155
229
|
program
|
|
156
230
|
.command("run")
|
|
157
231
|
.description("Execute all .flow automation journeys in the ./flows directory")
|
|
@@ -160,20 +234,49 @@ program
|
|
|
160
234
|
.option("--headless <boolean>", "Run browser in headless mode", (val) => val === "true", true)
|
|
161
235
|
.option("--workers <number>", "Number of parallel workers to spawn (Pro feature)")
|
|
162
236
|
.action(async (options) => {
|
|
163
|
-
|
|
164
|
-
let
|
|
165
|
-
|
|
237
|
+
let token = process.env.FLOWSTRIDE_API_KEY || null;
|
|
238
|
+
let forceOS = false;
|
|
239
|
+
const credentialsPath = path.join(process.cwd(), ".flowstride", "login", "login.json");
|
|
240
|
+
if (!token && fs.existsSync(credentialsPath)) {
|
|
166
241
|
try {
|
|
167
242
|
const credentials = JSON.parse(fs.readFileSync(credentialsPath, "utf8"));
|
|
168
|
-
|
|
169
|
-
console.log(`[PRO]: Machine Synced to Enterprise Cloud`);
|
|
170
|
-
}
|
|
171
|
-
catch (err) {
|
|
172
|
-
console.log(`[AUTH ERROR]: Invalid credentials file. Run 'flowstride login' to reconnect.`);
|
|
243
|
+
token = credentials.machineToken;
|
|
173
244
|
}
|
|
245
|
+
catch (err) { }
|
|
246
|
+
}
|
|
247
|
+
if (!token) {
|
|
248
|
+
console.log(chalk_1.default.white("⚪ [OS]: (Local Mode / Not Logged In)"));
|
|
249
|
+
forceOS = true;
|
|
174
250
|
}
|
|
175
251
|
else {
|
|
176
|
-
|
|
252
|
+
try {
|
|
253
|
+
const response = await fetch(`${API_BASE}/api/auth/verify-cli`, {
|
|
254
|
+
method: "GET",
|
|
255
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
256
|
+
});
|
|
257
|
+
if (response.status === 401) {
|
|
258
|
+
console.log(chalk_1.default.red("🔴 AUTH EXPIRED: Your device session was revoked or expired."));
|
|
259
|
+
if (fs.existsSync(credentialsPath))
|
|
260
|
+
fs.unlinkSync(credentialsPath);
|
|
261
|
+
forceOS = true;
|
|
262
|
+
}
|
|
263
|
+
else if (response.ok) {
|
|
264
|
+
const data = await response.json();
|
|
265
|
+
const tier = data.tier.toUpperCase();
|
|
266
|
+
if (tier === "PERSONAL") {
|
|
267
|
+
console.log(chalk_1.default.yellow(`🟡 [OS]: [${data.workspaceName}] (Tier: PERSONAL)`));
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
console.log(chalk_1.default.green(`🟢 [PRO]: [${data.workspaceName}] (Tier: ${tier})`));
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
forceOS = await handleOfflinePrompt();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
catch (err) {
|
|
278
|
+
forceOS = await handleOfflinePrompt();
|
|
279
|
+
}
|
|
177
280
|
}
|
|
178
281
|
if (options.headed) {
|
|
179
282
|
options.headless = false;
|
|
@@ -184,8 +287,25 @@ program
|
|
|
184
287
|
console.error(`Flowstride requires all UI tests to be inside a './flows' directory.`);
|
|
185
288
|
process.exit(1);
|
|
186
289
|
}
|
|
290
|
+
// Inject our DRM state into options before passing to runner
|
|
291
|
+
options.forceOS = forceOS;
|
|
187
292
|
await (0, run_1.runAction)(strictUiFlowsDir, options);
|
|
188
293
|
});
|
|
294
|
+
async function handleOfflinePrompt() {
|
|
295
|
+
console.log(chalk_1.default.yellow("🛜 OFFLINE: Unable to reach Flowstride Cloud. Enterprise Sync paused."));
|
|
296
|
+
if (process.env.CI || process.env.FLOWSTRIDE_API_KEY) {
|
|
297
|
+
console.log(chalk_1.default.yellow("⚠️ CI/CD Environment: Automatically falling back to OS Engine."));
|
|
298
|
+
return true; // Force OS
|
|
299
|
+
}
|
|
300
|
+
const runAnyway = await (0, prompts_1.confirm)({
|
|
301
|
+
message: "⚠️ Execute a local OS run anyway? (Pro features are disabled on OS)",
|
|
302
|
+
default: true,
|
|
303
|
+
});
|
|
304
|
+
if (!runAnyway) {
|
|
305
|
+
process.exit(0);
|
|
306
|
+
}
|
|
307
|
+
return true; // User said yes, Force OS
|
|
308
|
+
}
|
|
189
309
|
program
|
|
190
310
|
.command("report")
|
|
191
311
|
.description("Launch the interactive Debug Dashboard")
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flowstride",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "An opensource flowfirst test automation framework",
|
|
5
5
|
"workspaces": [
|
|
6
6
|
"packages/flowstride_report"
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"playwright": "^1.59.1",
|
|
42
42
|
"playwright-extra": "^4.3.6",
|
|
43
43
|
"puppeteer-extra-plugin-stealth": "^2.11.2",
|
|
44
|
+
"tar": "^7.5.16",
|
|
44
45
|
"ts-node": "^10.9.2",
|
|
45
46
|
"undici": "^7.25.0",
|
|
46
47
|
"ws": "^8.20.1"
|
|
@@ -245,7 +245,7 @@ Error generating stack: `+o.message+`
|
|
|
245
245
|
*
|
|
246
246
|
* This source code is licensed under the ISC license.
|
|
247
247
|
* See the LICENSE file in the root directory of this source tree.
|
|
248
|
-
*/const ih=O("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]),sh=""+new URL("flow_logo-CjiL4Lvy.png",import.meta.url).href,uh=({isTestFlowsOpen:e,setTestFlowsOpen:t})=>{const{activeView:n,setActiveView:r}=Se(),l=[{id:"Flows",icon:Qp,label:"Flows"},{id:"Logs",icon:th,label:"Logs"},{id:"Reports",icon:Pc,label:"Reports"},{id:"TestCase",icon:Lc,label:"TestCase"}];return s.jsxs("nav",{style:{width:"75px",backgroundColor:"#0d1117",borderRight:"1px solid #30363d",display:"flex",flexDirection:"column",alignItems:"center",flexShrink:0,height:"100%",overflow:"hidden"},children:[s.jsx("div",{style:{padding:"25px 0",cursor:"pointer"},onClick:()=>r("Flows"),children:s.jsx("img",{src:sh,alt:"Flowstride",style:{width:"42px",height:"auto"}})}),n==="Flows"&&s.jsxs("div",{onClick:()=>t(!e),style:{width:"100%",display:"flex",flexDirection:"column",alignItems:"center",padding:"12px 0",cursor:"pointer",color:e?"#a78bfa":"#8b949e",borderBottom:"1px solid #21262d",marginBottom:"10px"},children:[s.jsx(Yp,{size:22}),s.jsx("span",{style:{fontSize:"10px",marginTop:"4px",fontWeight:"bold"},children:e?"Hide":"Show"})]}),s.jsx("div",{style:{flex:1,width:"100%"},children:l.map(o=>{const i=n===o.id;return s.jsxs("div",{onClick:()=>r(o.id),style:{width:"100%",display:"flex",flexDirection:"column",alignItems:"center",padding:"18px 0",cursor:"pointer",backgroundColor:i?"rgba(124, 58, 237, 0.08)":"transparent",borderLeft:i?"3px solid #7c3aed":"3px solid transparent",color:i?"#a78bfa":"#8b949e",transition:"color 0.2s ease"},children:[s.jsx(o.icon,{size:22,strokeWidth:i?2.5:2}),s.jsx("span",{style:{fontSize:"10px",marginTop:"6px",fontWeight:i?"600":"400"},children:o.label})]},o.id)})}),s.jsxs("
|
|
248
|
+
*/const ih=O("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]),sh=""+new URL("flow_logo-CjiL4Lvy.png",import.meta.url).href,uh=({isTestFlowsOpen:e,setTestFlowsOpen:t})=>{const{activeView:n,setActiveView:r}=Se(),l=[{id:"Flows",icon:Qp,label:"Flows"},{id:"Logs",icon:th,label:"Logs"},{id:"Reports",icon:Pc,label:"Reports"},{id:"TestCase",icon:Lc,label:"TestCase"}];return s.jsxs("nav",{style:{width:"75px",backgroundColor:"#0d1117",borderRight:"1px solid #30363d",display:"flex",flexDirection:"column",alignItems:"center",flexShrink:0,height:"100%",overflow:"hidden"},children:[s.jsx("div",{style:{padding:"25px 0",cursor:"pointer"},onClick:()=>r("Flows"),children:s.jsx("img",{src:sh,alt:"Flowstride",style:{width:"42px",height:"auto"}})}),n==="Flows"&&s.jsxs("div",{onClick:()=>t(!e),style:{width:"100%",display:"flex",flexDirection:"column",alignItems:"center",padding:"12px 0",cursor:"pointer",color:e?"#a78bfa":"#8b949e",borderBottom:"1px solid #21262d",marginBottom:"10px"},children:[s.jsx(Yp,{size:22}),s.jsx("span",{style:{fontSize:"10px",marginTop:"4px",fontWeight:"bold"},children:e?"Hide":"Show"})]}),s.jsx("div",{style:{flex:1,width:"100%"},children:l.map(o=>{const i=n===o.id;return s.jsxs("div",{onClick:()=>r(o.id),style:{width:"100%",display:"flex",flexDirection:"column",alignItems:"center",padding:"18px 0",cursor:"pointer",backgroundColor:i?"rgba(124, 58, 237, 0.08)":"transparent",borderLeft:i?"3px solid #7c3aed":"3px solid transparent",color:i?"#a78bfa":"#8b949e",transition:"color 0.2s ease"},children:[s.jsx(o.icon,{size:22,strokeWidth:i?2.5:2}),s.jsx("span",{style:{fontSize:"10px",marginTop:"6px",fontWeight:i?"600":"400"},children:o.label})]},o.id)})}),s.jsxs("a",{href:"https://cloud.flowstride.io/register",target:"_blank",rel:"noopener noreferrer",style:{padding:"25px 0",width:"100%",borderTop:"1px solid #30363d",display:"flex",flexDirection:"column",alignItems:"center",textDecoration:"none"},children:[s.jsx("div",{style:{width:"38px",height:"38px",borderRadius:"50%",border:"2px solid #30363d",backgroundColor:"#1f2937",display:"flex",alignItems:"center",justifyContent:"center",color:"#a78bfa",fontWeight:"bold",fontSize:"14px"},children:"OS"}),s.jsx("span",{style:{fontSize:"11px",marginTop:"10px",fontWeight:"bold",color:"#ffffff"},children:"Open Source"}),s.jsx("span",{style:{fontSize:"9px",color:"#8b949e",marginTop:"2px",textAlign:"center",padding:"0 4px"},children:"COMMUNITY EDITION"})]})]})},ah=()=>{const{currentUrls:e,pageTitles:t,browserFrames:n,testScenarios:r,activeStepId:l,setActiveStepId:o,isRunning:i,activeTestFile:u,setActiveTestFile:a}=Se();F.useEffect(()=>{if(i){const c=r.find(p=>p.steps.some(g=>g.status==="running"));c&&c.fileName!==u&&a(c.fileName)}},[r,i,u,a]);let d=i?u:null,m=l;if(l&&l.includes(":::")){const c=l.split(":::");d=c[0],m=c[1]}const y=r.filter(c=>!d||c.fileName===d).flatMap(c=>c.steps).find(c=>c.id===m),h=!i&&!!(y&&y.screenshot),x=e[u]||"about:blank",v=t[u]||"New Tab",w=n[u]||null,_=h?y.screenshot:w,f=Array.from(new Set(r.map(c=>c.fileName)));return s.jsxs("div",{style:{height:"100%",display:"flex",flexDirection:"column",backgroundColor:"#1c2128"},children:[s.jsxs("div",{onWheel:c=>{c.currentTarget.scrollLeft+=c.deltaY},style:{display:"flex",alignItems:"center",padding:"8px 8px 0 8px",gap:"4px",overflowX:"auto",overflowY:"hidden",scrollbarWidth:"none",msOverflowStyle:"none"},children:[s.jsx("style",{children:`
|
|
249
249
|
div::-webkit-scrollbar { display: none; }
|
|
250
250
|
`}),f.length>0?f.map((c,p)=>{const g=u===c;return s.jsxs("div",{onClick:()=>a(c),style:{backgroundColor:g?"var(--fs-bg-base)":"rgba(255,255,255,0.05)",padding:"6px 15px",borderRadius:"8px 8px 0 0",display:"flex",alignItems:"center",gap:"8px",border:g?"1px solid var(--fs-border)":"1px solid transparent",borderBottom:"none",minWidth:"130px",maxWidth:"200px",flexShrink:0,cursor:"pointer",opacity:g?1:.6},children:[s.jsx(no,{size:12,color:g?"var(--fs-accent-purple)":"#8b949e",style:{flexShrink:0}}),s.jsx("span",{style:{fontSize:"10px",color:g?"white":"#8b949e",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",fontWeight:g?"bold":"normal"},children:c})]},p)}):s.jsxs("div",{style:{backgroundColor:"var(--fs-bg-base)",padding:"6px 15px",borderRadius:"8px 8px 0 0",display:"flex",alignItems:"center",gap:"8px",border:"1px solid var(--fs-border)",borderBottom:"none",minWidth:"140px",flexShrink:0},children:[s.jsx(no,{size:12,color:"var(--fs-accent-purple)"}),s.jsx("span",{style:{fontSize:"10px",color:"white"},children:v})]})]}),s.jsxs("div",{style:{backgroundColor:"var(--fs-bg-base)",borderTop:"1px solid var(--fs-border)",padding:"6px 12px",display:"flex",alignItems:"center",gap:"12px"},children:[s.jsxs("div",{style:{display:"flex",gap:"8px",color:"#8b949e"},children:[s.jsx(Bp,{size:14}),s.jsx(or,{size:14}),s.jsx(Mc,{size:14}),s.jsx(Gp,{size:14})]}),s.jsxs("div",{style:{flex:1,backgroundColor:"#05070a",border:"1px solid var(--fs-border)",borderRadius:"15px",padding:"3px 12px",display:"flex",alignItems:"center",gap:"8px"},children:[s.jsx(Xp,{size:10,color:"#22c55e"}),s.jsx("span",{style:{fontSize:"10px",color:"#8b949e",whiteSpace:"nowrap",overflow:"hidden"},children:x})]}),s.jsxs("div",{style:{display:"flex",gap:"10px",color:"#444",borderLeft:"1px solid #333",paddingLeft:"12px"},children:[s.jsx(Zp,{size:14,color:"var(--fs-accent-purple)"}),s.jsx(lh,{size:14}),s.jsx(nh,{size:14}),s.jsx($p,{size:14})]})]}),s.jsxs("div",{style:{flex:1,margin:"10px",backgroundColor:"white",borderRadius:"4px",boxShadow:"0 4px 12px rgba(0,0,0,0.5)",display:"flex",alignItems:"center",justifyContent:"center",overflow:"hidden",position:"relative"},children:[h&&s.jsxs("div",{style:{position:"absolute",top:"12px",left:"12px",right:"12px",backgroundColor:"rgba(15, 23, 42, 0.95)",border:"1px solid rgba(167, 139, 250, 0.3)",padding:"10px 16px",borderRadius:"6px",display:"flex",justifyContent:"space-between",alignItems:"center",zIndex:30,boxShadow:"0 4px 20px rgba(0,0,0,0.4)",backdropFilter:"blur(4px)"},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"10px"},children:[s.jsx("div",{style:{backgroundColor:"rgba(167, 139, 250, 0.1)",padding:"6px",borderRadius:"4px"},children:s.jsx(Hp,{size:14,color:"#a78bfa"})}),s.jsxs("div",{children:[s.jsx("div",{style:{fontSize:"11px",fontWeight:"bold",color:"#a78bfa",textTransform:"uppercase",letterSpacing:"0.05em"},children:"Viewing Historical State"}),s.jsx("div",{style:{fontSize:"12px",color:"#e2e8f0",fontFamily:"monospace",marginTop:"2px"},children:y==null?void 0:y.command})]})]}),s.jsx("button",{onClick:()=>o(null),style:{backgroundColor:"#7c3aed",color:"white",border:"none",padding:"6px 14px",borderRadius:"4px",fontSize:"11px",fontWeight:"bold",cursor:"pointer",transition:"background 0.2s"},onMouseEnter:c=>c.currentTarget.style.backgroundColor="#6d28d9",onMouseLeave:c=>c.currentTarget.style.backgroundColor="#7c3aed",children:"Return to Live"})]}),_?s.jsx("img",{src:`data:image/png;base64,${_}`,style:{width:"100%",height:"100%",objectFit:"contain",opacity:h?.95:1},alt:"Browser frame"}):s.jsxs("div",{style:{textAlign:"center",color:"#ccc"},children:[s.jsx(no,{size:40,style:{marginBottom:"8px",opacity:.1}}),s.jsx("div",{style:{fontSize:"11px",fontWeight:500,opacity:.3},children:"WAITING FOR RENDER..."})]})]})]})},ch=()=>{const{networkLogs:e,activeNetworkTab:t,setNetworkTab:n,setSelectedLogId:r,setActiveView:l}=Se(),o=["REST","GraphQL","Network","WS"],i=e.filter(a=>t==="GraphQL"?a.url.includes("graphql"):t==="REST"?!a.url.includes("graphql")&&!a.url.includes("ws"):!0),u=a=>{r(a),l("Logs")};return s.jsxs("div",{style:{height:"100%",display:"flex",flexDirection:"column",backgroundColor:"#0d1117"},children:[s.jsx("div",{style:{display:"flex",borderBottom:"1px solid var(--fs-border)",backgroundColor:"#05070a"},children:o.map(a=>s.jsx("button",{onClick:()=>n(a),style:{padding:"10px 16px",fontSize:"11px",fontWeight:"600",background:"none",border:"none",color:t===a?"#a78bfa":"#444",borderBottom:t===a?"2px solid #7c3aed":"2px solid transparent",cursor:"pointer",transition:"all 0.2s"},children:a},a))}),s.jsxs("div",{style:{padding:"8px 12px",display:"flex",gap:"10px",alignItems:"center",borderBottom:"1px solid #161b22"},children:[s.jsxs("div",{style:{flex:1,position:"relative"},children:[s.jsx(Gi,{size:12,style:{position:"absolute",left:"8px",top:"50%",transform:"translateY(-50%)",color:"#444"}}),s.jsx("input",{type:"text",placeholder:`Filter ${t}...`,style:{width:"100%",background:"#05070a",border:"1px solid #30363d",borderRadius:"4px",padding:"4px 8px 4px 28px",fontSize:"10px",color:"white"}})]}),s.jsx(bp,{size:14,color:"#444"})]}),s.jsx("div",{style:{flex:1,overflowY:"auto"},children:i.length===0?s.jsxs("div",{style:{padding:"40px",textAlign:"center",color:"#444",fontSize:"11px"},children:["No ",t," traffic detected"]}):i.map((a,d)=>s.jsx("div",{onClick:()=>u(a.id),style:{borderBottom:"1px solid #161b22",cursor:"pointer",transition:"background 0.2s"},onMouseEnter:m=>m.currentTarget.style.backgroundColor="#161b22",onMouseLeave:m=>m.currentTarget.style.backgroundColor="transparent",children:s.jsxs("div",{style:{display:"flex",alignItems:"center",padding:"8px 12px",fontSize:"11px",gap:"10px"},children:[s.jsx("span",{style:{color:a.status<400?"#34d399":"#f87171",fontWeight:"bold",width:"25px"},children:a.status}),s.jsx("span",{style:{fontWeight:"bold",width:"35px",color:"#8b949e"},children:a.method}),s.jsx("span",{style:{flex:1,color:"white",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:a.name||a.url}),s.jsx("span",{style:{color:"#444",fontSize:"10px"},children:a.time})]})},d))})]})},dh=()=>{const{logs:e}=Se(),t=F.useRef(null);return F.useEffect(()=>{t.current&&(t.current.scrollTop=t.current.scrollHeight)},[e]),s.jsxs("div",{ref:t,style:{flex:1,backgroundColor:"#0d1117",padding:"10px 15px",fontFamily:"monospace",fontSize:"12px",overflowY:"auto",color:"#d1d5db",lineHeight:"1.5"},children:[e.length===0&&s.jsx("div",{style:{color:"#4b5563",fontStyle:"italic"},children:"System ready. Awaiting execution..."}),e.map((n,r)=>{const l=(n.type||n.status||"INFO").toUpperCase();let o="#34d399";return(n.status==="error"||n.type==="ERROR")&&(o="#f87171"),n.status==="warning"&&(o="#fbbf24"),n.type==="ACTION"&&(o="#60a5fa"),s.jsxs("div",{style:{marginBottom:"4px",display:"flex",gap:"8px"},children:[s.jsxs("span",{style:{color:"#6e7681",flexShrink:0},children:["[",n.timestamp||"--:--:--","]"]}),s.jsx("span",{style:{color:o,fontWeight:"bold",flexShrink:0,width:"55px"},children:l}),s.jsx("span",{style:{color:"#c9d1d9",wordBreak:"break-all"},children:n.summary})]},n.id||r)})]})},fh=({isRightPanelOpen:e})=>{const{logs:t,pageTitles:n,activeTestFile:r}=Se(),l=t[t.length-1],o=n[r]||"New Tab";return s.jsxs("div",{style:{position:"absolute",top:0,left:0,right:0,bottom:0,display:"flex",flexDirection:"column",backgroundColor:"var(--fs-bg-base)",overflow:"hidden"},children:[s.jsxs("div",{style:{height:"35px",backgroundColor:"#161b22",borderBottom:"1px solid var(--fs-border)",display:"flex",alignItems:"center",padding:"0 15px",fontSize:"11px",color:"#8b949e",flexShrink:0},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px",flex:1},children:[s.jsx("span",{style:{color:"#a78bfa",fontWeight:"bold"},children:"LOG:"}),s.jsx("span",{style:{color:"#c9d1d9",fontFamily:"monospace",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:(l==null?void 0:l.summary)||"System ready. Awaiting connection..."})]}),s.jsx("div",{style:{opacity:.5,fontStyle:"italic"},children:o})]}),s.jsxs("div",{style:{flex:1,display:"flex",overflow:"hidden"},children:[s.jsx("div",{style:{flex:1,borderRight:"1px solid var(--fs-border)",height:"100%",overflow:"hidden"},children:s.jsx(ah,{})}),s.jsxs("div",{style:{width:e?"400px":"0px",transition:"width 0.2s ease",display:"flex",flexDirection:"column",height:"100%",backgroundColor:"#0d1117",overflow:"hidden",flexShrink:0},children:[s.jsx("div",{style:{flex:1,overflow:"hidden",display:"flex",flexDirection:"column"},children:s.jsx(ch,{})}),s.jsxs("div",{style:{flex:1,borderTop:"1px solid var(--fs-border)",backgroundColor:"#0d1117",overflow:"hidden",display:"flex",flexDirection:"column"},children:[s.jsx("div",{style:{padding:"8px 15px",fontSize:"11px",fontWeight:"bold",color:"#8b949e",borderBottom:"1px solid var(--fs-border)",flexShrink:0},children:"LIVE INFO"}),s.jsx("div",{style:{flex:1,overflow:"hidden",position:"relative"},children:s.jsx(dh,{})})]})]})]})]})},ph=()=>{var h,x;const[e,t]=F.useState(null),{testScenarios:n,logs:r}=Se(),l=n.reduce((v,w)=>v+w.steps.length,0),o=n.reduce((v,w)=>v+w.steps.filter(_=>["pass","passed","success"].includes(_.status)).length,0),i=n.reduce((v,w)=>v+w.steps.filter(_=>_.status==="failed").length,0),u=n.reduce((v,w)=>{const _=w.fileName||"General";return v[_]||(v[_]=[]),v[_].push(w),v},{});let a="Verified.",d=null,m=null,y=null;if(e){const v=e.status==="failed",w=["pass","passed","success"].includes(e.status);if(m=e.screenshot,v){const f=`${e.type} ${e.description}`,c=r.slice().reverse().find(p=>p.type==="ERROR"&&p.fileName===e.fileName&&p.stepContext===f);a=c?c.summary:"Validation Failed.",!m&&((h=c==null?void 0:c.details)!=null&&h.screenshot)&&(m=c.details.screenshot),(x=c==null?void 0:c.details)!=null&&x.boundingBox&&(y=c.details.boundingBox)}else e.status==="running"?a="Executing...":w&&(a="Action verified successfully.");const _=r.slice().reverse().find(f=>(f.type==="REST"||f.type==="GRAPHQL")&&f.fileName===e.fileName);d=_?_.details:null}return s.jsxs("div",{style:{height:"100%",width:"100%",backgroundColor:"#f8fafc",overflowY:"auto",position:"relative",color:"#0f172a"},children:[s.jsxs("div",{style:{maxWidth:"1200px",margin:"0 auto",padding:"40px 20px",marginRight:e?"450px":"auto",transition:"margin-right 0.3s"},children:[s.jsxs("header",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-end",borderBottom:"1px solid #e2e8f0",paddingBottom:"24px",marginBottom:"40px"},children:[s.jsxs("div",{children:[s.jsx("h1",{style:{fontSize:"30px",fontWeight:"800",margin:0,color:"#1e293b"},children:"Flowstride Reports"}),s.jsx("p",{style:{color:"#64748b",margin:"4px 0 0 0",fontWeight:"500"},children:"Multi-Flow Execution Analysis"})]}),s.jsxs("div",{style:{display:"flex",gap:"16px"},children:[s.jsx(ro,{label:"PASSED",value:o,color:"#10b981",icon:s.jsx(Tc,{size:20})}),s.jsx(ro,{label:"FAILED",value:i,color:"#ef4444",icon:s.jsx(_c,{size:20})}),s.jsx(ro,{label:"TOTAL",value:l,color:"#3b82f6",icon:s.jsx(Pc,{size:20})})]})]}),Object.keys(u).map(v=>s.jsxs("div",{style:{marginBottom:"60px"},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"20px",marginBottom:"24px"},children:[s.jsx("div",{style:{height:"2px",flex:1,backgroundColor:"#7c3aed",opacity:.15}}),s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"10px",color:"#7c3aed",fontWeight:"900",fontSize:"11px",textTransform:"uppercase",letterSpacing:"0.1em",backgroundColor:"rgba(124, 58, 237, 0.05)",padding:"6px 16px",borderRadius:"20px",border:"1px solid rgba(124, 58, 237, 0.1)"},children:[s.jsx(Nc,{size:14})," ",v]}),s.jsx("div",{style:{height:"2px",flex:1,backgroundColor:"#7c3aed",opacity:.15}})]}),s.jsx("div",{style:{backgroundColor:"white",borderRadius:"12px",border:"1px solid #e2e8f0",boxShadow:"0 1px 3px rgba(0,0,0,0.05)",overflow:"hidden"},children:s.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",textAlign:"left"},children:[s.jsx("thead",{style:{backgroundColor:"#f1f5f9",borderBottom:"1px solid #e2e8f0"},children:s.jsx("tr",{children:["S/N","Scenario","Action","Status",""].map((w,_)=>s.jsx("th",{style:{padding:"16px 24px",fontSize:"10px",fontWeight:"800",color:"#64748b",textTransform:"uppercase"},children:w},_))})}),s.jsx("tbody",{children:u[v].flatMap(w=>w.steps.map((_,f)=>s.jsxs("tr",{onClick:()=>t({..._,scenarioName:w.name,fileName:v}),style:{cursor:"pointer",borderBottom:"1px solid #f1f5f9",backgroundColor:(e==null?void 0:e.id)===_.id?"#eff6ff":"transparent"},children:[s.jsx("td",{style:{padding:"18px 24px",fontSize:"12px",color:"#94a3b8",fontFamily:"monospace",fontWeight:"bold"},children:f+1}),s.jsx("td",{style:{padding:"18px 24px",fontWeight:"600",color:"#334155"},children:w.name}),s.jsxs("td",{style:{padding:"18px 24px",fontSize:"14px",color:"#475569"},children:[s.jsx("b",{style:{color:"#7c3aed",marginRight:"8px"},children:_.type})," ",_.description]}),s.jsx("td",{style:{padding:"18px 24px"},children:s.jsx(yh,{status:_.status})}),s.jsx("td",{style:{padding:"18px 24px",textAlign:"right"},children:s.jsx(or,{size:16,color:(e==null?void 0:e.id)===_.id?"#3b82f6":"#cbd5e1",style:{transform:(e==null?void 0:e.id)===_.id?"rotate(90deg)":"none",transition:"0.2s"}})})]},_.id)))})]})})]},v))]}),s.jsx("aside",{style:{position:"fixed",top:0,right:0,height:"100%",width:"450px",backgroundColor:"white",boxShadow:"-10px 0 40px rgba(0,0,0,0.1)",borderLeft:"1px solid #e2e8f0",zIndex:100,transform:e?"translateX(0)":"translateX(100%)",transition:"transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)",padding:"30px",overflowY:"auto"},children:e&&s.jsxs(s.Fragment,{children:[s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"32px"},children:[s.jsxs("h2",{style:{fontSize:"18px",fontWeight:"700",display:"flex",alignItems:"center",gap:"10px"},children:[s.jsx(oh,{size:18,color:"#3b82f6"})," Step Diagnostics"]}),s.jsx(ih,{onClick:()=>t(null),style:{cursor:"pointer",color:"#94a3b8"}})]}),m&&s.jsx(Rn,{label:`Visual State (${(e.status||"").toUpperCase()})`,children:s.jsx(hh,{screenshot:m,boundingBox:y})}),s.jsx(Rn,{label:"Context",children:s.jsx("div",{style:{fontWeight:"bold",color:"#1e293b"},children:e.scenarioName})}),s.jsx(Rn,{label:"Requirement Proof",children:s.jsxs("div",{style:{padding:"16px",backgroundColor:"#f8fafc",borderRadius:"8px",fontSize:"14px",fontStyle:"italic",color:"#475569",border:"1px solid #f1f5f9"},children:['"',e.type," ",e.description,'"']})}),s.jsx(Rn,{label:"Runtime Outcome",children:s.jsx("div",{style:{padding:"16px",borderRadius:"8px",fontSize:"14px",fontWeight:"500",backgroundColor:["pass","success","passed"].includes(e.status)?"#ecfdf5":"#fef2f2",color:["pass","success","passed"].includes(e.status)?"#065f46":"#991b1b",border:`1px solid ${["pass","success","passed"].includes(e.status)?"#d1fae5":"#fee2e2"}`},children:a})}),d&&s.jsx(Rn,{label:"Network Activity",children:s.jsx("div",{style:{backgroundColor:"#0f172a",padding:"16px",borderRadius:"8px",color:"#7dd3fc",fontFamily:"monospace",fontSize:"11px",overflowX:"auto"},children:s.jsx("pre",{children:JSON.stringify({status:d.responseStatus,url:d.url},null,2)})})})]})})]})},hh=({screenshot:e,boundingBox:t})=>{const[n,r]=F.useState({w:0,h:0}),[l,o]=F.useState(!1),i=()=>{const u=window.open();u&&(u.document.write(`
|
|
251
251
|
<html>
|
package/src/ui/dist/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<link rel="icon" type="image/png" href="./favicon.png" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>Flowstride</title>
|
|
8
|
-
<script type="module" crossorigin src="./assets/index-
|
|
8
|
+
<script type="module" crossorigin src="./assets/index-BrbAbAha.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="./assets/index-DXTn_ThB.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|