muagqa 1.4.2 → 1.4.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "muagqa",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "description": "MuagQA CLI — Test case runner with one-time session token and Playwright recorder",
5
5
  "author": "Mary C.N. Enwezor",
6
6
  "license": "MIT",
@@ -0,0 +1,50 @@
1
+ import fetch from "node-fetch";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import chalk from "chalk";
5
+
6
+ export async function runTemplateGeneration(token) {
7
+ console.log(chalk.cyan("\n▶ Starting smart template generation…"));
8
+ console.log(chalk.gray("Using token:"), chalk.yellow(token));
9
+
10
+ try {
11
+ const res = await fetch(
12
+ "https://muagqa.vercel.app/api/cli/generate-templates",
13
+ {
14
+ method: "POST",
15
+ headers: { "Content-Type": "application/json" },
16
+ body: JSON.stringify({ token })
17
+ }
18
+ );
19
+
20
+ const data = await res.json();
21
+
22
+ if (!res.ok || data.error) {
23
+ console.log(chalk.red("❌ Template generation failed:"), data.error);
24
+ process.exit(1);
25
+ }
26
+
27
+ // Create output folder
28
+ const saveDir = path.join(process.cwd(), "generated-tests", "templates");
29
+ fs.mkdirSync(saveDir, { recursive: true });
30
+
31
+ console.log(chalk.green("\n✔ Templates received — writing files...\n"));
32
+
33
+ // Write each generated template
34
+ for (const [fileName, content] of Object.entries(data.templates)) {
35
+ const filePath = path.join(saveDir, fileName);
36
+ fs.writeFileSync(filePath, content, "utf8");
37
+
38
+ console.log(chalk.blue("➤ Created"), chalk.yellow(fileName));
39
+ }
40
+
41
+ console.log(
42
+ chalk.green(
43
+ `\n✔ Template generation complete! Files saved in generated-tests/templates/\n`
44
+ )
45
+ );
46
+ } catch (err) {
47
+ console.error(chalk.red("💥 Template Engine Crash:"), err);
48
+ process.exit(1);
49
+ }
50
+ }
package/src/index.js CHANGED
@@ -71,7 +71,8 @@ async function startCLI() {
71
71
  return;
72
72
  }
73
73
 
74
- console.log("Please specify --template or --record mode");
74
+ checkForUpdate();
75
+ await startRecording(token);
75
76
  }
76
77
 
77
78
  startCLI();
@@ -31,7 +31,7 @@ export function buildTemplate(testCase) {
31
31
  const description = testCase.description || "";
32
32
  const expected = testCase.expected || "";
33
33
  const startUrl =
34
- testCase.startUrl || testCase.url || testCase.start_url || "";
34
+ testCase.startUrl || testCase.url || testCase.start_url || "https://example.com";
35
35
 
36
36
  const headerLines = [];
37
37
  if (description) {
@@ -47,17 +47,51 @@ export function buildTemplate(testCase) {
47
47
  const header = headerLines.length ? `${headerLines.join("\n")}\n` : "";
48
48
 
49
49
  if (lines.length === 0) {
50
- lines.push(" // TODO: add steps for this test case.");
51
- if (startUrl) {
52
- lines.push(` await page.goto("${startUrl}");`);
50
+ const context = `${title} ${description} ${expected}`.toLowerCase();
51
+ const isLogin = context.includes("login") || context.includes("sign in");
52
+ const isSearch = context.includes("search");
53
+ const isCheckout = context.includes("checkout") || context.includes("payment");
54
+
55
+ lines.push(` await page.goto("${startUrl}");`);
56
+ lines.push(" await page.getByRole(\"combobox\").selectOption(\"en\");");
57
+ lines.push(
58
+ " await page.getByLabel(\"Username\").fill(\"user@example.com\");"
59
+ );
60
+ lines.push(
61
+ " await page.getByPlaceholder(\"Password\").fill(\"Password123!\");"
62
+ );
63
+ lines.push(" await page.getByRole(\"button\", { name: \"Show password\" }).click();");
64
+ lines.push(" await page.getByTestId(\"two-factor\").fill(\"123456\");");
65
+ lines.push(" await page.getByTitle(\"Help\").click();");
66
+ lines.push(" await page.getByAltText(\"Company logo\").click();");
67
+ lines.push(" await page.locator(\"input[name='remember']\").check();");
68
+ lines.push(" await page.locator(\"xpath=//button[contains(., 'Continue')]\").click();");
69
+
70
+ if (isSearch) {
71
+ lines.push(
72
+ " await page.getByRole(\"searchbox\", { name: \"Search\" }).fill(\"example query\");"
73
+ );
74
+ lines.push(" await page.getByText(\"Search\", { exact: true }).click();");
75
+ }
76
+
77
+ if (isCheckout) {
78
+ lines.push(" await page.getByRole(\"link\", { name: \"Cart\" }).click();");
79
+ lines.push(" await page.getByRole(\"button\", { name: \"Checkout\" }).click();");
80
+ }
81
+
82
+ if (isLogin) {
83
+ lines.push(" await page.getByRole(\"button\", { name: \"Login\" }).click();");
53
84
  } else {
54
- lines.push(" // await page.goto(\"https://example.com\");");
85
+ lines.push(" await page.getByRole(\"button\", { name: \"Submit\" }).click();");
55
86
  }
56
- lines.push(" // Example:");
57
- lines.push(" // await page.getByRole(\"button\", { name: \"Sign in\" }).click();");
87
+
88
+ lines.push(" await expect(page).toHaveURL(/dashboard|home|welcome/);");
89
+ lines.push(
90
+ " await expect(page.getByRole(\"status\")).toContainText(\"Success\");"
91
+ );
58
92
  }
59
93
 
60
- return `import { test } from "@playwright/test";
94
+ return `import { test, expect } from "@playwright/test";
61
95
 
62
96
  ${header}test("${title}", async ({ page }) => {
63
97
  ${lines.join("\n")}
@@ -1,15 +1,23 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
+ import inquirer from "inquirer";
3
4
  import chalk from "chalk";
4
5
  import { validateSessionToken } from "./api.js";
5
6
  import { buildTemplate } from "./templateBuilder.js";
6
7
 
7
8
  export async function generateTemplateTests(sessionToken) {
8
- const token = sessionToken || process.env.MUAGQA_SESSION;
9
+ let token = sessionToken || process.env.MUAGQA_SESSION;
9
10
 
10
11
  if (!token) {
11
- console.error("Missing session token. Set MUAGQA_SESSION or pass a token.");
12
- return;
12
+ const answer = await inquirer.prompt([
13
+ {
14
+ type: "input",
15
+ name: "token",
16
+ message: "Enter your one-time session token:",
17
+ validate: v => v.trim() !== "" || "Token is required."
18
+ }
19
+ ]);
20
+ token = answer.token;
13
21
  }
14
22
 
15
23
  const result = await validateSessionToken(token);