From d892adc5c241301784281c4c64ec7154ad8ed8e6 Mon Sep 17 00:00:00 2001
From: timbrinded <79199034+timbrinded@users.noreply.github.com>
Date: Thu, 5 Dec 2024 12:30:15 +0000
Subject: [PATCH] feat: :sparkles: added vitest arg passthrough

---
 .changeset/good-shoes-grab.md             |  6 +++
 .changeset/smooth-bears-hunt.md           | 13 ++++++
 packages/cli/src/cmds/entrypoint.ts       |  6 +++
 packages/cli/src/cmds/runTests.ts         | 33 ++++++++++---
 test/moonwall.config.json                 | 12 +++++
 test/suites/multi_fail/test_multifails.ts | 57 +++++++++++++++++++++++
 6 files changed, 120 insertions(+), 7 deletions(-)
 create mode 100644 .changeset/good-shoes-grab.md
 create mode 100644 .changeset/smooth-bears-hunt.md
 create mode 100644 test/suites/multi_fail/test_multifails.ts

diff --git a/.changeset/good-shoes-grab.md b/.changeset/good-shoes-grab.md
new file mode 100644
index 00000000..8ae39deb
--- /dev/null
+++ b/.changeset/good-shoes-grab.md
@@ -0,0 +1,6 @@
+---
+"@moonwall/cli": patch
+"@moonwall/tests": patch
+---
+
+Added vitest arg pass through
diff --git a/.changeset/smooth-bears-hunt.md b/.changeset/smooth-bears-hunt.md
new file mode 100644
index 00000000..857b661d
--- /dev/null
+++ b/.changeset/smooth-bears-hunt.md
@@ -0,0 +1,13 @@
+---
+"@moonwall/cli": patch
+---
+
+### Enhanced Test CLI Options
+
+#### New Features
+
+- Added support for passing Vitest configuration options directly through CLI
+
+  ```bash
+  moonwall test dev_test --vitest "bail=2 retry=2"
+  ```
diff --git a/packages/cli/src/cmds/entrypoint.ts b/packages/cli/src/cmds/entrypoint.ts
index bc1ce774..e4877e20 100755
--- a/packages/cli/src/cmds/entrypoint.ts
+++ b/packages/cli/src/cmds/entrypoint.ts
@@ -118,6 +118,11 @@ yargs(hideBin(process.argv))
           describe: "Update all snapshots",
           alias: "u",
           type: "boolean",
+        })
+        .option("vitestArgPassthrough", {
+          describe: "Arguments to pass directly to Vitest (space-delimited)",
+          alias: "vitest",
+          type: "string",
         });
     },
     async (args) => {
@@ -129,6 +134,7 @@ yargs(hideBin(process.argv))
             subDirectory: args.subDirectory,
             shard: args.testShard,
             update: args.update,
+            vitestPassthroughArgs: args.vitestArgPassthrough?.split(" "),
           }))
         ) {
           process.exitCode = 1;
diff --git a/packages/cli/src/cmds/runTests.ts b/packages/cli/src/cmds/runTests.ts
index 0d31efd6..b75745cf 100644
--- a/packages/cli/src/cmds/runTests.ts
+++ b/packages/cli/src/cmds/runTests.ts
@@ -55,6 +55,7 @@ export type testRunArgs = {
   subDirectory?: string;
   shard?: string;
   update?: boolean;
+  vitestPassthroughArgs?: string[];
 };
 
 export async function executeTests(env: Environment, testRunArgs?: testRunArgs) {
@@ -92,7 +93,23 @@ export async function executeTests(env: Environment, testRunArgs?: testRunArgs)
       }
     }
 
-    const additionalArgs: testRunArgs = testRunArgs || {};
+    const additionalArgs: Omit<testRunArgs, "vitestPassthroughArgs"> = testRunArgs
+      ? {
+          testNamePattern: testRunArgs.testNamePattern,
+          subDirectory: testRunArgs.subDirectory,
+          shard: testRunArgs.shard,
+          update: testRunArgs.update,
+        }
+      : {};
+
+    const vitestOptions = testRunArgs?.vitestPassthroughArgs?.reduce<UserConfig>((acc, arg) => {
+      const [key, value] = arg.split("=");
+      return {
+        // biome-ignore lint/performance/noAccumulatingSpread: this is fine
+        ...acc,
+        [key]: Number(value) || value,
+      };
+    }, {});
 
     // transform  in regexp pattern
     if (env.skipTests && env.skipTests.length > 0) {
@@ -126,12 +143,14 @@ export async function executeTests(env: Environment, testRunArgs?: testRunArgs)
           : env.testFileDir;
 
       const folders = testFileDir.map((folder) => path.join(".", folder, "/"));
-      resolve(
-        (await startVitest("test", folders, {
-          ...options,
-          ...additionalArgs,
-        })) as Vitest
-      );
+      const optionsToUse = {
+        ...options,
+        ...additionalArgs,
+        ...vitestOptions,
+      } satisfies UserConfig;
+
+      console.log(`Options to use: ${JSON.stringify(optionsToUse, null, 2)}`);
+      resolve((await startVitest("test", folders, optionsToUse)) as Vitest);
     } catch (e) {
       console.error(e);
       reject(e);
diff --git a/test/moonwall.config.json b/test/moonwall.config.json
index 42fa1756..9bf50a27 100644
--- a/test/moonwall.config.json
+++ b/test/moonwall.config.json
@@ -89,6 +89,18 @@
       },
       "connections": []
     },
+    {
+      "name": "passthrough_test",
+      "testFileDir": ["suites/multi_fail"],
+      "description": "Testing that bail can be passed through",
+      "foundation": {
+        "type": "read_only",
+        "launchSpec": {
+          "disableRuntimeVersionCheck": true
+        }
+      },
+      "connections": []
+    },
     {
       "name": "failing_prescript",
       "testFileDir": ["suites/basic"],
diff --git a/test/suites/multi_fail/test_multifails.ts b/test/suites/multi_fail/test_multifails.ts
new file mode 100644
index 00000000..9fdd7b44
--- /dev/null
+++ b/test/suites/multi_fail/test_multifails.ts
@@ -0,0 +1,57 @@
+import { expect, describeSuite, beforeAll } from "@moonwall/cli";
+import { setupLogger } from "@moonwall/util";
+import { setTimeout } from "timers/promises";
+describeSuite({
+  id: "F01",
+  title: "This test suite fails multiple times",
+  foundationMethods: "read_only",
+  testCases: ({ it, log }) => {
+    const anotherLogger = setupLogger("additional");
+
+    beforeAll(() => {
+      log("Test suite setup");
+    });
+
+    it({
+      id: "T01",
+      title: "This is a bool test case",
+      test: async() => {
+        await setTimeout(500)
+        expect(false).to.be.true;
+      },
+    });
+    it({
+      id: "T02",
+      title: "This is a bool test case",
+      test: async() => {
+        const rand = Math.floor(Math.random() * 1000);
+        expect(rand).toBeGreaterThan(800)
+      },
+    });
+    it({
+      id: "T03",
+      title: "This is a bool test case",
+      test: async() => {
+        await setTimeout(500)
+        expect(false).to.be.true;
+      },
+    });
+    it({
+      id: "T04",
+      title: "This is a bool test case",
+      test: async() => {
+        await setTimeout(500)
+        expect(false).to.be.true;
+      },
+    });
+    it({
+      id: "T05",
+      title: "This is a bool test case",
+      test: async() => {
+        await setTimeout(500)
+        expect(false).to.be.true;
+      },
+    });
+
+  },
+});