From da27b5e3e142094d8bbe18518696cbf87fe70676 Mon Sep 17 00:00:00 2001
From: CahidArda <cahidardaooz@hotmail.com>
Date: Wed, 16 Apr 2025 15:33:56 +0300
Subject: [PATCH 01/11] fix: bump version to 0.2.13

---
 src/constants.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/constants.ts b/src/constants.ts
index 904ec74..6bcc433 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -16,7 +16,7 @@ export const NO_CONCURRENCY = 1;
 export const NOT_SET = "not-set";
 export const DEFAULT_RETRIES = 3;
 
-export const VERSION = "v0.2.7";
+export const VERSION = "v0.2.13";
 export const SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
 
 export const TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk" as const;

From dd2d6895f663ea54c1dbb1db51c7f8684f04e95b Mon Sep 17 00:00:00 2001
From: CahidArda <cahidardaooz@hotmail.com>
Date: Wed, 16 Apr 2025 15:55:13 +0300
Subject: [PATCH 02/11] fix: tests

---
 src/serve/serve-many.test.ts | 10 +++++-----
 src/serve/serve.test.ts      | 20 ++++++++++----------
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/src/serve/serve-many.test.ts b/src/serve/serve-many.test.ts
index a2a234d..6bae7df 100644
--- a/src/serve/serve-many.test.ts
+++ b/src/serve/serve-many.test.ts
@@ -17,7 +17,7 @@ describe("serveMany", () => {
     test("should throw if workflowId contains '/'", () => {
       const throws = () =>
         serveMany({
-          "workflow/one": createWorkflow(async () => {}),
+          "workflow/one": createWorkflow(async () => { }),
         });
       expect(throws).toThrow(
         "Invalid workflow name found: 'workflow/one'. Workflow name cannot contain '/'."
@@ -26,7 +26,7 @@ describe("serveMany", () => {
 
     test("should throw if workflowId doesn't match", async () => {
       const { POST: handler } = serveMany({
-        "workflow-one": createWorkflow(async () => {}),
+        "workflow-one": createWorkflow(async () => { }),
       });
 
       const request = new Request("http://localhost:3001/workflow-two", { method: "POST" });
@@ -160,7 +160,7 @@ describe("serveMany", () => {
               "Upstash-Forward-Upstash-Workflow-Sdk-Version": ["1"],
               "Upstash-Telemetry-Framework": ["nextjs"],
               "Upstash-Telemetry-Runtime": ["node@v22.6.0"],
-              "Upstash-Telemetry-Sdk": ["@upstash/workflow@v0.2.7"],
+              "Upstash-Telemetry-Sdk": ["@upstash/workflow@v0.2.13"],
               "Upstash-Workflow-Init": ["false"],
               "Upstash-Workflow-RunId": ["wfr_id"],
               "Upstash-Workflow-Runid": ["wfr_id"],
@@ -215,7 +215,7 @@ describe("serveMany", () => {
               "Upstash-Forward-Upstash-Workflow-Sdk-Version": ["1"],
               "Upstash-Telemetry-Framework": ["nextjs"],
               "Upstash-Telemetry-Runtime": ["node@v22.6.0"],
-              "Upstash-Telemetry-Sdk": ["@upstash/workflow@v0.2.7"],
+              "Upstash-Telemetry-Sdk": ["@upstash/workflow@v0.2.13"],
               "Upstash-Workflow-Init": ["false"],
               "Upstash-Workflow-RunId": ["wfr_id"],
               "Upstash-Workflow-Runid": ["wfr_id"],
@@ -289,7 +289,7 @@ describe("serveMany", () => {
                 "upstash-retries": "0",
                 "upstash-telemetry-framework": "nextjs",
                 "upstash-telemetry-runtime": "node@v22.6.0",
-                "upstash-telemetry-sdk": "@upstash/workflow@v0.2.7",
+                "upstash-telemetry-sdk": "@upstash/workflow@v0.2.13",
                 "upstash-workflow-calltype": "toCallback",
                 "upstash-workflow-init": "false",
                 "upstash-workflow-runid": "wfr_id",
diff --git a/src/serve/serve.test.ts b/src/serve/serve.test.ts
index ed7c446..4b55acc 100644
--- a/src/serve/serve.test.ts
+++ b/src/serve/serve.test.ts
@@ -133,9 +133,9 @@ describe("serve", () => {
       execute: async (initialPayload, steps, first) => {
         const request = first
           ? new Request(WORKFLOW_ENDPOINT, {
-              body: JSON.stringify(initialPayload),
-              method: "POST",
-            })
+            body: JSON.stringify(initialPayload),
+            method: "POST",
+          })
           : getRequest(WORKFLOW_ENDPOINT, workflowRunId, initialPayload, steps);
 
         request.headers.set(WORKFLOW_INVOKE_COUNT_HEADER, "2");
@@ -409,7 +409,7 @@ describe("serve", () => {
                 "upstash-workflow-url": WORKFLOW_ENDPOINT,
                 "upstash-telemetry-framework": "unknown",
                 "upstash-telemetry-runtime": "unknown",
-                "upstash-telemetry-sdk": "@upstash/workflow@v0.2.7",
+                "upstash-telemetry-sdk": "@upstash/workflow@v0.2.13",
               },
               body: '{"stepId":3,"stepName":"step 3","stepType":"Run","out":"\\"combined results: result 1,result 2\\"","concurrent":1}',
             },
@@ -458,7 +458,7 @@ describe("serve", () => {
                 "upstash-workflow-url": WORKFLOW_ENDPOINT,
                 "upstash-telemetry-framework": "unknown",
                 "upstash-telemetry-runtime": "unknown",
-                "upstash-telemetry-sdk": "@upstash/workflow@v0.2.7",
+                "upstash-telemetry-sdk": "@upstash/workflow@v0.2.13",
               },
               body: '{"stepId":1,"stepName":"sleep-step","stepType":"SleepFor","sleepFor":1,"concurrent":1}',
             },
@@ -511,7 +511,7 @@ describe("serve", () => {
                 "upstash-failure-callback-workflow-url": "https://requestcatcher.com/api",
                 "upstash-telemetry-framework": "unknown",
                 "upstash-telemetry-runtime": "unknown",
-                "upstash-telemetry-sdk": "@upstash/workflow@v0.2.7",
+                "upstash-telemetry-sdk": "@upstash/workflow@v0.2.13",
               },
               body: '{"stepId":1,"stepName":"sleep-step","stepType":"SleepFor","sleepFor":1,"concurrent":1}',
             },
@@ -566,7 +566,7 @@ describe("serve", () => {
                 "upstash-failure-callback-workflow-url": "https://requestcatcher.com/api",
                 "upstash-telemetry-framework": "unknown",
                 "upstash-telemetry-runtime": "unknown",
-                "upstash-telemetry-sdk": "@upstash/workflow@v0.2.7",
+                "upstash-telemetry-sdk": "@upstash/workflow@v0.2.13",
               },
               body: '{"stepId":1,"stepName":"sleep-step","stepType":"SleepFor","sleepFor":1,"concurrent":1}',
             },
@@ -661,7 +661,7 @@ describe("serve", () => {
                 "upstash-retries": "4",
                 "upstash-telemetry-framework": "unknown",
                 "upstash-telemetry-runtime": "unknown",
-                "upstash-telemetry-sdk": "@upstash/workflow@v0.2.7",
+                "upstash-telemetry-sdk": "@upstash/workflow@v0.2.13",
                 "upstash-timeout": "10",
                 "upstash-workflow-calltype": "toCallback",
                 "upstash-workflow-init": "false",
@@ -875,7 +875,7 @@ describe("serve", () => {
             "Upstash-Workflow-Url": [WORKFLOW_ENDPOINT],
             "Upstash-Telemetry-Framework": ["unknown"],
             "Upstash-Telemetry-Runtime": ["unknown"],
-            "Upstash-Telemetry-Sdk": ["@upstash/workflow@v0.2.7"],
+            "Upstash-Telemetry-Sdk": ["@upstash/workflow@v0.2.13"],
           },
           timeoutUrl: WORKFLOW_ENDPOINT,
           url: WORKFLOW_ENDPOINT,
@@ -1158,7 +1158,7 @@ describe("serve", () => {
               "upstash-forward-test-header": headerValue,
               "upstash-telemetry-framework": "unknown",
               "upstash-telemetry-runtime": "unknown",
-              "upstash-telemetry-sdk": "@upstash/workflow@v0.2.7",
+              "upstash-telemetry-sdk": "@upstash/workflow@v0.2.13",
             },
             body: '{"stepId":1,"stepName":"sleep-step","stepType":"SleepFor","sleepFor":1,"concurrent":1}',
           },

From 5990e9f1d076c222b933b8778e89069c8f00fd6e Mon Sep 17 00:00:00 2001
From: CahidArda <cahidardaooz@hotmail.com>
Date: Mon, 5 May 2025 16:37:20 +0300
Subject: [PATCH 03/11] ci: add debug logs to test ci

---
 examples/ci/app/ci/upstash/redis.ts | 2 ++
 examples/ci/app/ci/utils.ts         | 6 ++++++
 2 files changed, 8 insertions(+)

diff --git a/examples/ci/app/ci/upstash/redis.ts b/examples/ci/app/ci/upstash/redis.ts
index a76a76c..5ef7970 100644
--- a/examples/ci/app/ci/upstash/redis.ts
+++ b/examples/ci/app/ci/upstash/redis.ts
@@ -120,6 +120,8 @@ export const checkRedisForResults = async (
 
   const retryCount = retryOverride ?? RETRY_COUNT
   for ( let i=1; i <= retryCount; i++ ) {
+    console.log(`check ${i}`);
+    
     testResult = await redis.get<RedisResult>(key)
     if (testResult) {
       break
diff --git a/examples/ci/app/ci/utils.ts b/examples/ci/app/ci/utils.ts
index 0dc06f8..f80d416 100644
--- a/examples/ci/app/ci/utils.ts
+++ b/examples/ci/app/ci/utils.ts
@@ -64,15 +64,20 @@ export const getTestConfig = async (route: string) => {
 
 export const initiateTest = async (route: string) => {
   const randomTestId = nanoid()
+  console.log(`initiating test for ${route}`);
+  
   const { headers, payload, expectedCallCount, expectedResult, shouldWorkflowStart = true } = await getTestConfig(route)
+  console.log(`got config`);
 
   const { messageId } = await qstash.startWorkflow({ route, headers, payload }, randomTestId)
+  console.log(`starting workflow`);
 
   // sleep for 4 secs and check that message is delivered
   await new Promise(r => setTimeout(r, CHECK_WF_AFTER_INIT_DURATION));
 
   try {
     await qstash.checkWorkflowStart(messageId);
+    console.log(`workflow started`);
   } catch (error) {
     console.error(error);
     if (shouldWorkflowStart) {
@@ -80,6 +85,7 @@ export const initiateTest = async (route: string) => {
     };
   }
 
+  console.log("checking redis for results");
   await redis.checkRedisForResults(route, randomTestId, expectedCallCount, expectedResult)
 }
 

From 7d3b68ca8956b33c598df6c27a7fc0aa0292679a Mon Sep 17 00:00:00 2001
From: CahidArda <cahidardaooz@hotmail.com>
Date: Mon, 5 May 2025 17:22:37 +0300
Subject: [PATCH 04/11] fix: mock request

---
 src/serve/serve.test.ts | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/src/serve/serve.test.ts b/src/serve/serve.test.ts
index 4b55acc..4e7e2b8 100644
--- a/src/serve/serve.test.ts
+++ b/src/serve/serve.test.ts
@@ -1,6 +1,6 @@
 /* eslint-disable @typescript-eslint/no-unused-vars */
 /* eslint-disable @typescript-eslint/require-await */
-import { describe, expect, spyOn, test } from "bun:test";
+import { describe, expect, jest, spyOn, test } from "bun:test";
 import { serve } from ".";
 import {
   driveWorkflow,
@@ -133,9 +133,9 @@ describe("serve", () => {
       execute: async (initialPayload, steps, first) => {
         const request = first
           ? new Request(WORKFLOW_ENDPOINT, {
-            body: JSON.stringify(initialPayload),
-            method: "POST",
-          })
+              body: JSON.stringify(initialPayload),
+              method: "POST",
+            })
           : getRequest(WORKFLOW_ENDPOINT, workflowRunId, initialPayload, steps);
 
         request.headers.set(WORKFLOW_INVOKE_COUNT_HEADER, "2");
@@ -1017,10 +1017,17 @@ describe("serve", () => {
 
   describe("incorrect url will throw", () => {
     const qstashClient = new Client({ token: process.env.QSTASH_TOKEN! });
+
+    qstashClient.publish = jest.fn().mockImplementation(() => {
+      return {
+        messageId: "some-message-id",
+        deduplicationId: "some-deduplication-id",
+      };
+    });
     const client = new WorkflowClient({ token: process.env.QSTASH_TOKEN! });
 
     test("allow http://", async () => {
-      const url = "http://requestcatcher.com";
+      const url = "http://some-website.com";
       const { handler } = serve(
         async (context) => {
           await context.sleep("sleeping", 1);

From e6d15f62e539a2c9b8aacedf0c3280b4d5e420b0 Mon Sep 17 00:00:00 2001
From: CahidArda <cahidardaooz@hotmail.com>
Date: Tue, 6 May 2025 10:43:36 +0300
Subject: [PATCH 05/11] fix: flaky tests

---
 src/client/index.test.ts     | 34 ++++++++++++++++++++++++----------
 src/serve/serve-many.test.ts |  4 ++--
 2 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/src/client/index.test.ts b/src/client/index.test.ts
index c39292b..3899fde 100644
--- a/src/client/index.test.ts
+++ b/src/client/index.test.ts
@@ -133,10 +133,18 @@ describe("workflow client", () => {
           url: "http://requestcatcher.com",
         });
 
-        const firstCancel = await liveClient.cancel({
-          ids: [workflowRunIdOne, workflowRunIdTwo, "non-existent"],
-        });
-        expect(firstCancel).toEqual({ cancelled: 2 });
+        await new Promise((r) => setTimeout(r, 1000));
+
+        await eventually(
+          async () => {
+            const firstCancel = await liveClient.cancel({
+              ids: [workflowRunIdOne, workflowRunIdTwo, "non-existent"],
+            });
+            expect(firstCancel).toEqual({ cancelled: 2 });
+          },
+          { timeout: 5000, interval: 1000 }
+        );
+        await new Promise((r) => setTimeout(r, 1000));
 
         // trying to cancel the workflows one by one gives error, as they were canceled above
         const secondCancel = await liveClient.cancel({ ids: workflowRunIdOne });
@@ -147,7 +155,7 @@ describe("workflow client", () => {
         expect(thirdCancel).toEqual({ cancelled: 0 });
       },
       {
-        timeout: 10000,
+        timeout: 20000,
       }
     );
 
@@ -161,14 +169,20 @@ describe("workflow client", () => {
           url: "http://requestcatcher.com/second",
         });
 
-        const cancel = await liveClient.cancel({
-          urlStartingWith: "http://requestcatcher.com",
-        });
+        await new Promise((r) => setTimeout(r, 2000));
 
-        expect(cancel).toEqual({ cancelled: 2 });
+        await eventually(
+          async () => {
+            const cancel = await liveClient.cancel({
+              urlStartingWith: "http://requestcatcher.com",
+            });
+            expect(cancel).toEqual({ cancelled: 2 });
+          },
+          { timeout: 5000, interval: 1000 }
+        );
       },
       {
-        timeout: 10000,
+        timeout: 15000,
       }
     );
 
diff --git a/src/serve/serve-many.test.ts b/src/serve/serve-many.test.ts
index 6bae7df..9a81d36 100644
--- a/src/serve/serve-many.test.ts
+++ b/src/serve/serve-many.test.ts
@@ -17,7 +17,7 @@ describe("serveMany", () => {
     test("should throw if workflowId contains '/'", () => {
       const throws = () =>
         serveMany({
-          "workflow/one": createWorkflow(async () => { }),
+          "workflow/one": createWorkflow(async () => {}),
         });
       expect(throws).toThrow(
         "Invalid workflow name found: 'workflow/one'. Workflow name cannot contain '/'."
@@ -26,7 +26,7 @@ describe("serveMany", () => {
 
     test("should throw if workflowId doesn't match", async () => {
       const { POST: handler } = serveMany({
-        "workflow-one": createWorkflow(async () => { }),
+        "workflow-one": createWorkflow(async () => {}),
       });
 
       const request = new Request("http://localhost:3001/workflow-two", { method: "POST" });

From 7501ed69768379fc2df95dad1f10edbb5fd6dfc3 Mon Sep 17 00:00:00 2001
From: CahidArda <cahidardaooz@hotmail.com>
Date: Tue, 6 May 2025 10:54:58 +0300
Subject: [PATCH 06/11] fix: add sleeps

---
 src/client/index.test.ts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/client/index.test.ts b/src/client/index.test.ts
index 3899fde..9b0b99a 100644
--- a/src/client/index.test.ts
+++ b/src/client/index.test.ts
@@ -134,7 +134,6 @@ describe("workflow client", () => {
         });
 
         await new Promise((r) => setTimeout(r, 1000));
-
         await eventually(
           async () => {
             const firstCancel = await liveClient.cancel({

From 11460af1100f6b7eb2f53aefb17f70e53c30e2b5 Mon Sep 17 00:00:00 2001
From: CahidArda <cahidardaooz@hotmail.com>
Date: Tue, 6 May 2025 10:57:47 +0300
Subject: [PATCH 07/11] fix: increase sleep duration

---
 src/client/index.test.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/client/index.test.ts b/src/client/index.test.ts
index 9b0b99a..456b8a1 100644
--- a/src/client/index.test.ts
+++ b/src/client/index.test.ts
@@ -168,7 +168,7 @@ describe("workflow client", () => {
           url: "http://requestcatcher.com/second",
         });
 
-        await new Promise((r) => setTimeout(r, 2000));
+        await new Promise((r) => setTimeout(r, 5000));
 
         await eventually(
           async () => {

From 788029eb40634f55dd2295adc5485c54b475c434 Mon Sep 17 00:00:00 2001
From: CahidArda <cahidardaooz@hotmail.com>
Date: Tue, 6 May 2025 13:54:26 +0300
Subject: [PATCH 08/11] ci: increase retry and sleep times

---
 examples/ci/app/ci/constants.ts                              | 2 +-
 examples/ci/app/test-routes/wait-for-event/notifier/route.ts | 2 +-
 examples/ci/app/test-routes/wait-for-event/workflow/route.ts | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/examples/ci/app/ci/constants.ts b/examples/ci/app/ci/constants.ts
index d010cea..18c5e4a 100644
--- a/examples/ci/app/ci/constants.ts
+++ b/examples/ci/app/ci/constants.ts
@@ -1,6 +1,6 @@
 import { TestConfig } from "./types"
 
-export const RETRY_COUNT = 20
+export const RETRY_COUNT = 30
 export const RETRY_INTERVAL_DURATION = 2000
 export const CHECK_WF_AFTER_INIT_DURATION = 10000
 const TEST_BUFFER_DURATION = 5000
diff --git a/examples/ci/app/test-routes/wait-for-event/notifier/route.ts b/examples/ci/app/test-routes/wait-for-event/notifier/route.ts
index 88a1a7d..afe801f 100644
--- a/examples/ci/app/test-routes/wait-for-event/notifier/route.ts
+++ b/examples/ci/app/test-routes/wait-for-event/notifier/route.ts
@@ -16,7 +16,7 @@ export const POST = async (request: Request) => {
 
   const sleepAndNotify = async () => {
     
-    await new Promise(r => setTimeout(r, 1000));
+    await new Promise(r => setTimeout(r, 3000));
     
     const result = await client.notify({
       eventId: sdkEventId,
diff --git a/examples/ci/app/test-routes/wait-for-event/workflow/route.ts b/examples/ci/app/test-routes/wait-for-event/workflow/route.ts
index a321240..c33a353 100644
--- a/examples/ci/app/test-routes/wait-for-event/workflow/route.ts
+++ b/examples/ci/app/test-routes/wait-for-event/workflow/route.ts
@@ -54,7 +54,7 @@ export const { POST, GET } = testServe(
           }
         ),
         context.waitForEvent("wait sdk", config.sdkEventId, {
-          timeout: "5s"
+          timeout: "10s"
         })
       ])
 

From 9aba17c268d6b07b05f9c71be3b9d27c88b69b15 Mon Sep 17 00:00:00 2001
From: CahidArda <cahidardaooz@hotmail.com>
Date: Wed, 7 May 2025 14:48:00 +0300
Subject: [PATCH 09/11] fix: switch to vitest

---
 examples/ci/app/ci/ci.test.ts            |  2 +-
 examples/ci/app/ci/upstash/qstash.ts     |  2 +-
 examples/ci/app/ci/upstash/redis.test.ts | 19 +++++++++----------
 examples/ci/app/ci/utils.test.ts         |  2 +-
 examples/ci/package.json                 |  6 ++++--
 5 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/examples/ci/app/ci/ci.test.ts b/examples/ci/app/ci/ci.test.ts
index 3db0e20..a0dec1d 100644
--- a/examples/ci/app/ci/ci.test.ts
+++ b/examples/ci/app/ci/ci.test.ts
@@ -1,4 +1,4 @@
-import { test, describe } from "bun:test"
+import { test, describe } from "vitest";
 import { TEST_ROUTES, TEST_TIMEOUT_DURATION } from "./constants";
 import { initiateTest } from "./utils";
 
diff --git a/examples/ci/app/ci/upstash/qstash.ts b/examples/ci/app/ci/upstash/qstash.ts
index a4ade99..44a5539 100644
--- a/examples/ci/app/ci/upstash/qstash.ts
+++ b/examples/ci/app/ci/upstash/qstash.ts
@@ -2,7 +2,7 @@ import { Client, QstashError } from "@upstash/qstash"
 import { TEST_ROUTE_PREFIX, CI_RANDOM_ID_HEADER, CI_ROUTE_HEADER } from "../constants"
 import { TestConfig } from "../types"
 
-const client = new Client({ baseUrl: process.env.QSTASH_URL, token: process.env.QSTASH_TOKEN! })
+const client = new Client({ baseUrl: process.env.QSTASH_URL, token: process.env.QSTASH_TOKEN!, retry: false })
 
 /**
  * starts a workflow run given the config
diff --git a/examples/ci/app/ci/upstash/redis.test.ts b/examples/ci/app/ci/upstash/redis.test.ts
index b82c590..c0c16b1 100644
--- a/examples/ci/app/ci/upstash/redis.test.ts
+++ b/examples/ci/app/ci/upstash/redis.test.ts
@@ -1,5 +1,4 @@
-
-import { describe, test, expect, beforeAll } from "bun:test";
+import { describe, test, expect, beforeAll } from "vitest";
 import * as redis from "./redis"
 import { nanoid } from "../utils";
 
@@ -33,23 +32,23 @@ describe("redis", () => {
     })
 
     test("should throw on mismatching result", () => {
-      expect(async () =>
+      expect(() =>
         redis.checkRedisForResults(route, randomId, 2, "not-correct")
       ).toThrow(
-        `Unexpected value.\n\tReceived "${result}"\n\tExpected "not-correct"`
+        `Unexpected value.\n\tReceived \"${result}\"\n\tExpected \"not-correct\"`
       )
     })
 
     test("should throw on mismatching call count", () => {
-      expect(async () =>
+      expect(() =>
         redis.checkRedisForResults(route, randomId, 123, result)
       ).toThrow(
-        `Unexpected value.\n\tReceived "2"\n\tExpected "123"`
+        `Unexpected value.\n\tReceived \"2\"\n\tExpected \"123\"`
       )
     })
 
     test("should not throw on correct results", () => {
-      expect(async () =>
+      expect(() =>
         redis.checkRedisForResults(route, randomId, 2, result)
       ).not.toThrow()
     })
@@ -68,14 +67,14 @@ describe("redis", () => {
 
     await redis.saveResultsWithoutContext(route, randomId, result, override)
 
-    expect(async () =>
+    expect(() =>
       redis.checkRedisForResults(route, randomId, 3, result)
     ).toThrow(
-      `Unexpected value.\n\tReceived "-3"\n\tExpected "3"`
+      `Unexpected value.\n\tReceived \"-3\"\n\tExpected \"3\"`
     )
 
     test("should not throw on correct results", () => {
-      expect(async () =>
+      expect(() =>
         redis.checkRedisForResults(route, randomId, override, result)
       ).not.toThrow()
     })
diff --git a/examples/ci/app/ci/utils.test.ts b/examples/ci/app/ci/utils.test.ts
index a0e5879..f7abb77 100644
--- a/examples/ci/app/ci/utils.test.ts
+++ b/examples/ci/app/ci/utils.test.ts
@@ -1,4 +1,4 @@
-import { test, expect } from "bun:test";
+import { test, expect } from "vitest";
 import { expect as utilsExpect } from "./utils"
 
 test("expect", () => {
diff --git a/examples/ci/package.json b/examples/ci/package.json
index cbfa8d5..a158d6f 100644
--- a/examples/ci/package.json
+++ b/examples/ci/package.json
@@ -6,7 +6,8 @@
     "dev": "next dev -p 3001",
     "build": "next build",
     "start": "next start -p 3001",
-    "lint": "next lint"
+    "lint": "next lint",
+    "test": "vitest"
   },
   "dependencies": {
     "@upstash/qstash": "^2.7.12",
@@ -30,6 +31,7 @@
     "prettier": "^3.3.3",
     "prettier-plugin-tailwindcss": "^0.6.6",
     "tailwindcss": "^3.4.1",
-    "typescript": "^5.6.2"
+    "typescript": "^5.6.2",
+    "vitest": "^3.1.3"
   }
 }

From 731c482880ef89ad9cb824a7d7da8ee8e8a2b936 Mon Sep 17 00:00:00 2001
From: CahidArda <cahidardaooz@hotmail.com>
Date: Wed, 7 May 2025 14:56:57 +0300
Subject: [PATCH 10/11] ci: use vitest

---
 .github/workflows/test.yaml | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index 011b873..654ecd7 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -590,15 +590,14 @@ jobs:
         with:
           node-version: 20
 
-      - name: Setup Bun
-        uses: oven-sh/setup-bun@v1
-        with:
-          bun-version: latest
-
       - uses: pnpm/action-setup@v2
         with:
           version: latest
 
+      - name: Install Dependencies
+        run: pnpm i
+        working-directory: examples/ci
+
       - name: Deploy
         run: |
           pnpm add @upstash/workflow@${{needs.release.outputs.version}}
@@ -610,7 +609,7 @@ jobs:
         working-directory: examples/ci
 
       - name: Test
-        run: bun test .
+        run: pnpm test
         working-directory: examples/ci
 
   cloudflare-workers-hono-deployed:

From 2638be50b792965dd8f964b937728797507910c5 Mon Sep 17 00:00:00 2001
From: CahidArda <cahidardaooz@hotmail.com>
Date: Wed, 7 May 2025 17:19:02 +0300
Subject: [PATCH 11/11] fix: vitest tests

---
 examples/ci/app/ci/ci.test.ts            |  3 +
 examples/ci/app/ci/upstash/qstash.ts     |  2 +-
 examples/ci/app/ci/upstash/redis.test.ts | 77 ++++++++++++------------
 examples/ci/app/ci/utils.test.ts         |  4 +-
 examples/ci/package.json                 |  1 +
 examples/ci/vitest.config.js             | 15 +++++
 6 files changed, 60 insertions(+), 42 deletions(-)
 create mode 100644 examples/ci/vitest.config.js

diff --git a/examples/ci/app/ci/ci.test.ts b/examples/ci/app/ci/ci.test.ts
index a0dec1d..8295bb4 100644
--- a/examples/ci/app/ci/ci.test.ts
+++ b/examples/ci/app/ci/ci.test.ts
@@ -1,6 +1,9 @@
 import { test, describe } from "vitest";
 import { TEST_ROUTES, TEST_TIMEOUT_DURATION } from "./constants";
 import { initiateTest } from "./utils";
+import { config } from "dotenv";
+
+config();
 
 describe("workflow integration tests", () => {
   TEST_ROUTES.forEach(testConfig => {
diff --git a/examples/ci/app/ci/upstash/qstash.ts b/examples/ci/app/ci/upstash/qstash.ts
index 44a5539..1b40c9a 100644
--- a/examples/ci/app/ci/upstash/qstash.ts
+++ b/examples/ci/app/ci/upstash/qstash.ts
@@ -22,7 +22,7 @@ export const startWorkflow = async (
       [ CI_ROUTE_HEADER ]: testConfig.route,
       ...testConfig.headers
     },
-    body: testConfig.payload
+    body: testConfig.payload,
   })
   return result
 }
diff --git a/examples/ci/app/ci/upstash/redis.test.ts b/examples/ci/app/ci/upstash/redis.test.ts
index c0c16b1..95b7807 100644
--- a/examples/ci/app/ci/upstash/redis.test.ts
+++ b/examples/ci/app/ci/upstash/redis.test.ts
@@ -3,18 +3,16 @@ import * as redis from "./redis"
 import { nanoid } from "../utils";
 
 describe("redis", () => {
-  test("should throw on missing results", () => {
-    expect(() =>
-      redis.checkRedisForResults("some-route", "some-id", -1, "some-result", 1)
-    ).toThrow(
-      "result not found for route some-route with randomTestId some-id"
+  test("should throw on missing results", { timeout: 15000 },async () => {
+    await expect(redis.checkRedisForResults("some-route", "some-id", -1, "some-result", 1)).rejects.toThrowError(
+            "result not found for route some-route with randomTestId some-id"
     )
-  }, { timeout: 15000 })
+  })
 
   test("should throw when saving results without any increment", () => {
-    expect(() =>
-      redis.saveResultsWithoutContext("some-route", "some-id", "some-result")
-    ).toThrow(
+    expect(async () =>
+      await redis.saveResultsWithoutContext("some-route", "some-id", "some-result")
+    ).rejects.toThrowError(
       "callCount shouldn't be 0. It was 0 in test of the route 'some-route'"
     )
   })
@@ -32,53 +30,54 @@ describe("redis", () => {
     })
 
     test("should throw on mismatching result", () => {
-      expect(() =>
-        redis.checkRedisForResults(route, randomId, 2, "not-correct")
-      ).toThrow(
+      expect(async () =>
+        await redis.checkRedisForResults(route, randomId, 2, "not-correct")
+      ).rejects.toThrowError(
         `Unexpected value.\n\tReceived \"${result}\"\n\tExpected \"not-correct\"`
       )
     })
 
     test("should throw on mismatching call count", () => {
-      expect(() =>
-        redis.checkRedisForResults(route, randomId, 123, result)
-      ).toThrow(
+      expect(async () =>
+        await redis.checkRedisForResults(route, randomId, 123, result)
+      ).rejects.toThrowError(
         `Unexpected value.\n\tReceived \"2\"\n\tExpected \"123\"`
       )
     })
 
     test("should not throw on correct results", () => {
-      expect(() =>
-        redis.checkRedisForResults(route, randomId, 2, result)
-      ).not.toThrow()
+      expect(async () =>
+        await redis.checkRedisForResults(route, randomId, 2, result)
+      ).not.toThrowError()
     })
   })
 
-  test("should override call count", async () => {
+  describe("override call count", () => {
+    test("should override call count", async () => {
+      const route = "override-route";
+      const randomId = `random-id-${nanoid()}`;
+      const result = `random-result-${nanoid()}`;
+      const override = -3;
 
-    const route = "override-route"
-    const randomId = `random-id-${nanoid()}`
-    const result = `random-result-${nanoid()}`
-    const override = -3
-
-    await redis.increment(route, randomId)
-    await redis.increment(route, randomId)
-    await redis.increment(route, randomId)
+      await redis.increment(route, randomId);
+      await redis.increment(route, randomId);
+      await redis.increment(route, randomId);
 
-    await redis.saveResultsWithoutContext(route, randomId, result, override)
+      await redis.saveResultsWithoutContext(route, randomId, result, override);
 
-    expect(() =>
-      redis.checkRedisForResults(route, randomId, 3, result)
-    ).toThrow(
-      `Unexpected value.\n\tReceived \"-3\"\n\tExpected \"3\"`
-    )
+      expect(async () =>
+        await redis.checkRedisForResults(route, randomId, 3, result)
+      ).rejects.toThrowError(
+        `Unexpected value.\n\tReceived \"-3\"\n\tExpected \"3\"`
+      );
+    });
 
     test("should not throw on correct results", () => {
-      expect(() =>
-        redis.checkRedisForResults(route, randomId, override, result)
-      ).not.toThrow()
-    })
-  })
+      expect(async () =>
+        await redis.checkRedisForResults("override-route", `random-id-${nanoid()}`, -3, `random-result-${nanoid()}`)
+      ).not.toThrowError();
+    });
+  });
 
   test("should fail if marked as failed", async () => {
 
@@ -93,7 +92,7 @@ describe("redis", () => {
 
     // mark as failed and check
     await redis.failWithoutContext(route, randomId)
-    expect(redis.checkRedisForResults(route, randomId, 1, result)).rejects.toThrow(redis.FAILED_TEXT)
+    expect(redis.checkRedisForResults(route, randomId, 1, result)).rejects.toThrowError(redis.FAILED_TEXT)
       
   })
 })
\ No newline at end of file
diff --git a/examples/ci/app/ci/utils.test.ts b/examples/ci/app/ci/utils.test.ts
index f7abb77..4b3be90 100644
--- a/examples/ci/app/ci/utils.test.ts
+++ b/examples/ci/app/ci/utils.test.ts
@@ -2,6 +2,6 @@ import { test, expect } from "vitest";
 import { expect as utilsExpect } from "./utils"
 
 test("expect", () => {
-  expect(() => utilsExpect("same", "same")).not.toThrow()
-  expect(() => utilsExpect("not", "same")).toThrow(`Unexpected value.\n\tReceived "not"\n\tExpected "same"`)
+  expect(() => utilsExpect("same", "same")).not.toThrowError()
+  expect(() => utilsExpect("not", "same")).toThrowError()
 })
\ No newline at end of file
diff --git a/examples/ci/package.json b/examples/ci/package.json
index a158d6f..0fbf54f 100644
--- a/examples/ci/package.json
+++ b/examples/ci/package.json
@@ -15,6 +15,7 @@
     "@upstash/workflow": "latest",
     "@vercel/functions": "^1.5.0",
     "clsx": "^2.1.1",
+    "dotenv": "^16.5.0",
     "next": "14.2.23",
     "react": "^18.3.1",
     "react-dom": "^18.3.1",
diff --git a/examples/ci/vitest.config.js b/examples/ci/vitest.config.js
new file mode 100644
index 0000000..df8d429
--- /dev/null
+++ b/examples/ci/vitest.config.js
@@ -0,0 +1,15 @@
+import { config } from "dotenv";
+import { defineConfig } from "vitest/config";
+
+export default defineConfig({
+  test: {
+    passWithNoTests: true,
+    globals: true,
+    coverage: {
+      provider: "v8",
+    },
+    env: {
+      ...config({ path: "./.env" }).parsed,
+    },
+  },
+});
\ No newline at end of file