openworkflow 0.5.0 → 0.6.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/README.md +40 -347
- package/dist/{testing → backend-test}/backend.testsuite.d.ts +1 -1
- package/dist/backend-test/backend.testsuite.d.ts.map +1 -0
- package/dist/{testing → backend-test}/backend.testsuite.js +8 -9
- package/dist/backend-test/index.d.ts +2 -0
- package/dist/backend-test/index.d.ts.map +1 -0
- package/dist/{testing → backend-test}/index.js +0 -1
- package/dist/backend.js +0 -1
- package/dist/backend.testsuite.d.ts +20 -0
- package/dist/backend.testsuite.d.ts.map +1 -0
- package/dist/backend.testsuite.js +1090 -0
- package/dist/bin/openworkflow.js +0 -1
- package/dist/chaos.test.d.ts +2 -0
- package/dist/chaos.test.d.ts.map +1 -0
- package/dist/chaos.test.js +88 -0
- package/dist/client.js +0 -1
- package/dist/client.test.d.ts +2 -0
- package/dist/client.test.d.ts.map +1 -0
- package/dist/client.test.js +311 -0
- package/dist/core/duration.js +0 -1
- package/dist/core/duration.test.d.ts +2 -0
- package/dist/core/duration.test.d.ts.map +1 -0
- package/dist/core/duration.test.js +263 -0
- package/dist/core/error.js +0 -1
- package/dist/core/error.test.d.ts +2 -0
- package/dist/core/error.test.d.ts.map +1 -0
- package/dist/core/error.test.js +60 -0
- package/dist/core/json.js +0 -1
- package/dist/core/result.js +0 -1
- package/dist/core/result.test.d.ts +2 -0
- package/dist/core/result.test.d.ts.map +1 -0
- package/dist/core/result.test.js +11 -0
- package/dist/core/retry.js +0 -1
- package/dist/core/schema.js +0 -1
- package/dist/core/step.js +0 -1
- package/dist/core/step.test.d.ts +2 -0
- package/dist/core/step.test.d.ts.map +1 -0
- package/dist/core/step.test.js +266 -0
- package/dist/core/workflow.js +0 -1
- package/dist/core/workflow.test.d.ts +2 -0
- package/dist/core/workflow.test.d.ts.map +1 -0
- package/dist/core/workflow.test.js +113 -0
- package/dist/driver.d.ts +116 -0
- package/dist/driver.d.ts.map +1 -0
- package/dist/driver.js +1 -0
- package/dist/execution.js +0 -1
- package/dist/execution.test.d.ts +2 -0
- package/dist/execution.test.d.ts.map +1 -0
- package/dist/execution.test.js +381 -0
- package/dist/factory.d.ts +74 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +72 -0
- package/dist/index.js +0 -1
- package/dist/internal.d.ts +4 -5
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -4
- package/dist/{backend-sqlite/index.d.ts → node-sqlite/backend.d.ts} +14 -4
- package/dist/node-sqlite/backend.d.ts.map +1 -0
- package/dist/{backend-sqlite/index.js → node-sqlite/backend.js} +23 -5
- package/dist/node-sqlite/index.d.ts +11 -0
- package/dist/node-sqlite/index.d.ts.map +1 -0
- package/dist/node-sqlite/index.js +7 -0
- package/dist/{backend-sqlite → node-sqlite}/sqlite.d.ts +2 -3
- package/dist/node-sqlite/sqlite.d.ts.map +1 -0
- package/dist/{backend-sqlite → node-sqlite}/sqlite.js +0 -1
- package/dist/{pg → postgres}/backend.d.ts +3 -1
- package/dist/postgres/backend.d.ts.map +1 -0
- package/dist/{pg → postgres}/backend.js +5 -5
- package/dist/postgres/backend.test.d.ts +2 -0
- package/dist/postgres/backend.test.d.ts.map +1 -0
- package/dist/postgres/backend.test.js +19 -0
- package/dist/postgres/driver.d.ts +81 -0
- package/dist/postgres/driver.d.ts.map +1 -0
- package/dist/postgres/driver.js +63 -0
- package/dist/postgres/index.d.ts +11 -0
- package/dist/postgres/index.d.ts.map +1 -0
- package/dist/postgres/index.js +7 -0
- package/dist/postgres/internal.d.ts +2 -0
- package/dist/postgres/internal.d.ts.map +1 -0
- package/dist/postgres/internal.js +1 -0
- package/dist/postgres/postgres.d.ts.map +1 -0
- package/dist/{backend-postgres → postgres}/postgres.js +0 -1
- package/dist/postgres/postgres.test.d.ts +2 -0
- package/dist/postgres/postgres.test.d.ts.map +1 -0
- package/dist/postgres/postgres.test.js +45 -0
- package/dist/postgres/scripts/db-migrate.d.ts.map +1 -0
- package/dist/{pg → postgres}/scripts/db-migrate.js +0 -1
- package/dist/postgres/scripts/db-reset.d.ts.map +1 -0
- package/dist/{pg → postgres}/scripts/db-reset.js +0 -1
- package/dist/{pg → postgres}/scripts/squawk.d.ts.map +1 -1
- package/dist/{pg → postgres}/scripts/squawk.js +0 -1
- package/dist/postgres/vitest.global-setup.d.ts.map +1 -0
- package/dist/{pg → postgres}/vitest.global-setup.js +0 -1
- package/dist/postgres.d.ts +2 -0
- package/dist/postgres.d.ts.map +1 -0
- package/dist/postgres.js +1 -0
- package/dist/registry.js +0 -1
- package/dist/registry.test.d.ts +2 -0
- package/dist/registry.test.d.ts.map +1 -0
- package/dist/registry.test.js +109 -0
- package/dist/sqlite/backend.d.ts +3 -1
- package/dist/sqlite/backend.d.ts.map +1 -1
- package/dist/sqlite/backend.js +5 -5
- package/dist/sqlite/backend.test.d.ts +2 -0
- package/dist/sqlite/backend.test.d.ts.map +1 -0
- package/dist/sqlite/backend.test.js +50 -0
- package/dist/sqlite/driver.d.ts +79 -0
- package/dist/sqlite/driver.d.ts.map +1 -0
- package/dist/sqlite/driver.js +62 -0
- package/dist/sqlite/index.d.ts +12 -2
- package/dist/sqlite/index.d.ts.map +1 -1
- package/dist/sqlite/index.js +11 -3
- package/dist/sqlite/internal.d.ts +2 -0
- package/dist/sqlite/internal.d.ts.map +1 -0
- package/dist/sqlite/internal.js +1 -0
- package/dist/sqlite/sqlite.js +0 -1
- package/dist/sqlite/sqlite.test.d.ts +2 -0
- package/dist/sqlite/sqlite.test.d.ts.map +1 -0
- package/dist/sqlite/sqlite.test.js +171 -0
- package/dist/sqlite.d.ts +2 -0
- package/dist/sqlite.d.ts.map +1 -0
- package/dist/sqlite.js +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/worker.js +0 -1
- package/dist/worker.test.d.ts +2 -0
- package/dist/worker.test.d.ts.map +1 -0
- package/dist/worker.test.js +900 -0
- package/dist/workflow.js +0 -1
- package/dist/workflow.test.d.ts +2 -0
- package/dist/workflow.test.d.ts.map +1 -0
- package/dist/workflow.test.js +84 -0
- package/package.json +19 -5
- package/dist/backend-postgres/index.d.ts +0 -44
- package/dist/backend-postgres/index.d.ts.map +0 -1
- package/dist/backend-postgres/index.js +0 -535
- package/dist/backend-postgres/index.js.map +0 -1
- package/dist/backend-postgres/postgres.d.ts.map +0 -1
- package/dist/backend-postgres/postgres.js.map +0 -1
- package/dist/backend-sqlite/index.d.ts.map +0 -1
- package/dist/backend-sqlite/index.js.map +0 -1
- package/dist/backend-sqlite/sqlite.d.ts.map +0 -1
- package/dist/backend-sqlite/sqlite.js.map +0 -1
- package/dist/backend.js.map +0 -1
- package/dist/bin/openworkflow.js.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/config.d.ts +0 -34
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -49
- package/dist/config.js.map +0 -1
- package/dist/core/duration.js.map +0 -1
- package/dist/core/error.js.map +0 -1
- package/dist/core/json.js.map +0 -1
- package/dist/core/result.js.map +0 -1
- package/dist/core/retry.js.map +0 -1
- package/dist/core/schema.js.map +0 -1
- package/dist/core/step.js.map +0 -1
- package/dist/core/workflow.js.map +0 -1
- package/dist/execution.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/internal.js.map +0 -1
- package/dist/pg/backend.d.ts.map +0 -1
- package/dist/pg/backend.js.map +0 -1
- package/dist/pg/index.d.ts +0 -3
- package/dist/pg/index.d.ts.map +0 -1
- package/dist/pg/index.js +0 -3
- package/dist/pg/index.js.map +0 -1
- package/dist/pg/postgres.d.ts +0 -42
- package/dist/pg/postgres.d.ts.map +0 -1
- package/dist/pg/postgres.js +0 -234
- package/dist/pg/postgres.js.map +0 -1
- package/dist/pg/scripts/db-migrate.d.ts.map +0 -1
- package/dist/pg/scripts/db-migrate.js.map +0 -1
- package/dist/pg/scripts/db-reset.d.ts.map +0 -1
- package/dist/pg/scripts/db-reset.js.map +0 -1
- package/dist/pg/scripts/squawk.js.map +0 -1
- package/dist/pg/vitest.global-setup.d.ts.map +0 -1
- package/dist/pg/vitest.global-setup.js.map +0 -1
- package/dist/registry.js.map +0 -1
- package/dist/sqlite/backend.js.map +0 -1
- package/dist/sqlite/index.js.map +0 -1
- package/dist/sqlite/sqlite.js.map +0 -1
- package/dist/testing/backend.testsuite.d.ts.map +0 -1
- package/dist/testing/backend.testsuite.js.map +0 -1
- package/dist/testing/index.d.ts +0 -2
- package/dist/testing/index.d.ts.map +0 -1
- package/dist/testing/index.js.map +0 -1
- package/dist/worker.js.map +0 -1
- package/dist/workflow.js.map +0 -1
- /package/dist/{backend-postgres → postgres}/postgres.d.ts +0 -0
- /package/dist/{pg → postgres}/scripts/db-migrate.d.ts +0 -0
- /package/dist/{pg → postgres}/scripts/db-reset.d.ts +0 -0
- /package/dist/{pg → postgres}/scripts/squawk.d.ts +0 -0
- /package/dist/{pg → postgres}/vitest.global-setup.d.ts +0 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { parseDuration } from "./duration.js";
|
|
2
|
+
import { ok, err } from "./result.js";
|
|
3
|
+
import { describe, expect, test } from "vitest";
|
|
4
|
+
describe("parseDuration", () => {
|
|
5
|
+
describe("milliseconds", () => {
|
|
6
|
+
test("parses integer milliseconds", () => {
|
|
7
|
+
expect(parseDuration("100ms")).toEqual(ok(100));
|
|
8
|
+
expect(parseDuration("1ms")).toEqual(ok(1));
|
|
9
|
+
expect(parseDuration("5000ms")).toEqual(ok(5000));
|
|
10
|
+
});
|
|
11
|
+
test("parses decimal milliseconds", () => {
|
|
12
|
+
expect(parseDuration("1.5ms")).toEqual(ok(1.5));
|
|
13
|
+
expect(parseDuration("10.25ms")).toEqual(ok(10.25));
|
|
14
|
+
});
|
|
15
|
+
test("parses milliseconds with long format", () => {
|
|
16
|
+
expect(parseDuration("53 milliseconds")).toEqual(ok(53));
|
|
17
|
+
expect(parseDuration("17 msecs")).toEqual(ok(17));
|
|
18
|
+
expect(parseDuration("100 millisecond")).toEqual(ok(100));
|
|
19
|
+
});
|
|
20
|
+
test("parses numbers without unit as milliseconds", () => {
|
|
21
|
+
expect(parseDuration("100")).toEqual(ok(100));
|
|
22
|
+
expect(parseDuration("1000")).toEqual(ok(1000));
|
|
23
|
+
});
|
|
24
|
+
test("parses negative milliseconds", () => {
|
|
25
|
+
expect(parseDuration("-100ms")).toEqual(ok(-100));
|
|
26
|
+
expect(parseDuration("-100 milliseconds")).toEqual(ok(-100));
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
describe("seconds", () => {
|
|
30
|
+
test("parses integer seconds", () => {
|
|
31
|
+
expect(parseDuration("1s")).toEqual(ok(1000));
|
|
32
|
+
expect(parseDuration("5s")).toEqual(ok(5000));
|
|
33
|
+
expect(parseDuration("60s")).toEqual(ok(60_000));
|
|
34
|
+
});
|
|
35
|
+
test("parses decimal seconds", () => {
|
|
36
|
+
expect(parseDuration("1.5s")).toEqual(ok(1500));
|
|
37
|
+
expect(parseDuration("0.1s")).toEqual(ok(100));
|
|
38
|
+
expect(parseDuration("2.5s")).toEqual(ok(2500));
|
|
39
|
+
expect(parseDuration("0.001s")).toEqual(ok(1));
|
|
40
|
+
});
|
|
41
|
+
test("parses seconds with long format", () => {
|
|
42
|
+
expect(parseDuration("1 sec")).toEqual(ok(1000));
|
|
43
|
+
expect(parseDuration("5 seconds")).toEqual(ok(5000));
|
|
44
|
+
expect(parseDuration("10 secs")).toEqual(ok(10_000));
|
|
45
|
+
});
|
|
46
|
+
test("parses seconds with leading decimal", () => {
|
|
47
|
+
expect(parseDuration(".5s")).toEqual(ok(500));
|
|
48
|
+
expect(parseDuration(".5ms")).toEqual(ok(0.5));
|
|
49
|
+
});
|
|
50
|
+
test("parses negative seconds", () => {
|
|
51
|
+
expect(parseDuration("-5s")).toEqual(ok(-5000));
|
|
52
|
+
expect(parseDuration("-.5s")).toEqual(ok(-500));
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
describe("minutes", () => {
|
|
56
|
+
test("parses integer minutes", () => {
|
|
57
|
+
expect(parseDuration("1m")).toEqual(ok(60 * 1000));
|
|
58
|
+
expect(parseDuration("5m")).toEqual(ok(5 * 60 * 1000));
|
|
59
|
+
expect(parseDuration("30m")).toEqual(ok(30 * 60 * 1000));
|
|
60
|
+
});
|
|
61
|
+
test("parses decimal minutes", () => {
|
|
62
|
+
expect(parseDuration("1.5m")).toEqual(ok(1.5 * 60 * 1000));
|
|
63
|
+
expect(parseDuration("0.5m")).toEqual(ok(30 * 1000));
|
|
64
|
+
});
|
|
65
|
+
test("parses minutes with long format", () => {
|
|
66
|
+
expect(parseDuration("1 min")).toEqual(ok(60_000));
|
|
67
|
+
expect(parseDuration("5 minutes")).toEqual(ok(5 * 60 * 1000));
|
|
68
|
+
expect(parseDuration("10 mins")).toEqual(ok(10 * 60 * 1000));
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe("hours", () => {
|
|
72
|
+
test("parses integer hours", () => {
|
|
73
|
+
expect(parseDuration("1h")).toEqual(ok(60 * 60 * 1000));
|
|
74
|
+
expect(parseDuration("2h")).toEqual(ok(2 * 60 * 60 * 1000));
|
|
75
|
+
expect(parseDuration("24h")).toEqual(ok(24 * 60 * 60 * 1000));
|
|
76
|
+
});
|
|
77
|
+
test("parses decimal hours", () => {
|
|
78
|
+
expect(parseDuration("1.5h")).toEqual(ok(1.5 * 60 * 60 * 1000));
|
|
79
|
+
expect(parseDuration("0.25h")).toEqual(ok(15 * 60 * 1000));
|
|
80
|
+
});
|
|
81
|
+
test("parses hours with long format", () => {
|
|
82
|
+
expect(parseDuration("1 hr")).toEqual(ok(3_600_000));
|
|
83
|
+
expect(parseDuration("2 hours")).toEqual(ok(2 * 60 * 60 * 1000));
|
|
84
|
+
expect(parseDuration("3 hrs")).toEqual(ok(3 * 60 * 60 * 1000));
|
|
85
|
+
expect(parseDuration("1.5 hours")).toEqual(ok(5_400_000));
|
|
86
|
+
});
|
|
87
|
+
test("parses negative hours", () => {
|
|
88
|
+
expect(parseDuration("-1.5h")).toEqual(ok(-5_400_000));
|
|
89
|
+
expect(parseDuration("-10.5h")).toEqual(ok(-37_800_000));
|
|
90
|
+
expect(parseDuration("-.5h")).toEqual(ok(-1_800_000));
|
|
91
|
+
expect(parseDuration("-1.5 hours")).toEqual(ok(-5_400_000));
|
|
92
|
+
expect(parseDuration("-.5 hr")).toEqual(ok(-1_800_000));
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
describe("days", () => {
|
|
96
|
+
test("parses integer days", () => {
|
|
97
|
+
expect(parseDuration("1d")).toEqual(ok(24 * 60 * 60 * 1000));
|
|
98
|
+
expect(parseDuration("7d")).toEqual(ok(7 * 24 * 60 * 60 * 1000));
|
|
99
|
+
expect(parseDuration("30d")).toEqual(ok(30 * 24 * 60 * 60 * 1000));
|
|
100
|
+
});
|
|
101
|
+
test("parses decimal days", () => {
|
|
102
|
+
expect(parseDuration("1.5d")).toEqual(ok(1.5 * 24 * 60 * 60 * 1000));
|
|
103
|
+
expect(parseDuration("0.5d")).toEqual(ok(12 * 60 * 60 * 1000));
|
|
104
|
+
});
|
|
105
|
+
test("parses days with long format", () => {
|
|
106
|
+
expect(parseDuration("2 days")).toEqual(ok(172_800_000));
|
|
107
|
+
expect(parseDuration("1 day")).toEqual(ok(24 * 60 * 60 * 1000));
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
describe("weeks", () => {
|
|
111
|
+
test("parses integer weeks", () => {
|
|
112
|
+
expect(parseDuration("1w")).toEqual(ok(7 * 24 * 60 * 60 * 1000));
|
|
113
|
+
expect(parseDuration("2w")).toEqual(ok(2 * 7 * 24 * 60 * 60 * 1000));
|
|
114
|
+
expect(parseDuration("3w")).toEqual(ok(1_814_400_000));
|
|
115
|
+
});
|
|
116
|
+
test("parses decimal weeks", () => {
|
|
117
|
+
expect(parseDuration("1.5w")).toEqual(ok(1.5 * 7 * 24 * 60 * 60 * 1000));
|
|
118
|
+
expect(parseDuration("0.5w")).toEqual(ok(3.5 * 24 * 60 * 60 * 1000));
|
|
119
|
+
});
|
|
120
|
+
test("parses weeks with long format", () => {
|
|
121
|
+
expect(parseDuration("1 week")).toEqual(ok(604_800_000));
|
|
122
|
+
expect(parseDuration("2 weeks")).toEqual(ok(2 * 7 * 24 * 60 * 60 * 1000));
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
describe("months", () => {
|
|
126
|
+
test("parses integer months", () => {
|
|
127
|
+
expect(parseDuration("1mo")).toEqual(ok(2_629_800_000));
|
|
128
|
+
expect(parseDuration("2mo")).toEqual(ok(2 * 2_629_800_000));
|
|
129
|
+
expect(parseDuration("6mo")).toEqual(ok(6 * 2_629_800_000));
|
|
130
|
+
});
|
|
131
|
+
test("parses decimal months", () => {
|
|
132
|
+
expect(parseDuration("1.5mo")).toEqual(ok(1.5 * 2_629_800_000));
|
|
133
|
+
expect(parseDuration("0.5mo")).toEqual(ok(0.5 * 2_629_800_000));
|
|
134
|
+
});
|
|
135
|
+
test("parses months with long format", () => {
|
|
136
|
+
expect(parseDuration("1 month")).toEqual(ok(2_629_800_000));
|
|
137
|
+
expect(parseDuration("2 months")).toEqual(ok(2 * 2_629_800_000));
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
describe("years", () => {
|
|
141
|
+
test("parses integer years", () => {
|
|
142
|
+
expect(parseDuration("1y")).toEqual(ok(31_557_600_000));
|
|
143
|
+
expect(parseDuration("2y")).toEqual(ok(2 * 31_557_600_000));
|
|
144
|
+
expect(parseDuration("5y")).toEqual(ok(5 * 31_557_600_000));
|
|
145
|
+
});
|
|
146
|
+
test("parses decimal years", () => {
|
|
147
|
+
expect(parseDuration("1.5y")).toEqual(ok(1.5 * 31_557_600_000));
|
|
148
|
+
expect(parseDuration("0.5y")).toEqual(ok(0.5 * 31_557_600_000));
|
|
149
|
+
});
|
|
150
|
+
test("parses years with long format", () => {
|
|
151
|
+
expect(parseDuration("1 year")).toEqual(ok(31_557_600_000));
|
|
152
|
+
expect(parseDuration("2 years")).toEqual(ok(2 * 31_557_600_000));
|
|
153
|
+
expect(parseDuration("1 yr")).toEqual(ok(31_557_600_000));
|
|
154
|
+
expect(parseDuration("2 yrs")).toEqual(ok(2 * 31_557_600_000));
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
describe("case insensitivity", () => {
|
|
158
|
+
test("parses case-insensitive units", () => {
|
|
159
|
+
expect(parseDuration("5S")).toEqual(ok(5000));
|
|
160
|
+
expect(parseDuration("5M")).toEqual(ok(5 * 60 * 1000));
|
|
161
|
+
expect(parseDuration("5H")).toEqual(ok(5 * 60 * 60 * 1000));
|
|
162
|
+
expect(parseDuration("5D")).toEqual(ok(5 * 24 * 60 * 60 * 1000));
|
|
163
|
+
expect(parseDuration("5W")).toEqual(ok(5 * 7 * 24 * 60 * 60 * 1000));
|
|
164
|
+
});
|
|
165
|
+
test("parses case-insensitive long format", () => {
|
|
166
|
+
// @ts-expect-error - mixed-case (not in type but accepted at runtime)
|
|
167
|
+
expect(parseDuration("53 YeArS")).toEqual(ok(1_672_552_800_000));
|
|
168
|
+
// @ts-expect-error - mixed-case (not in type but accepted at runtime)
|
|
169
|
+
expect(parseDuration("53 WeEkS")).toEqual(ok(32_054_400_000));
|
|
170
|
+
// @ts-expect-error - mixed-case (not in type but accepted at runtime)
|
|
171
|
+
expect(parseDuration("53 DaYS")).toEqual(ok(4_579_200_000));
|
|
172
|
+
// @ts-expect-error - mixed-case (not in type but accepted at runtime)
|
|
173
|
+
expect(parseDuration("53 HoUrs")).toEqual(ok(190_800_000));
|
|
174
|
+
// @ts-expect-error - mixed-case (not in type but accepted at runtime)
|
|
175
|
+
expect(parseDuration("53 MiLliSeCondS")).toEqual(ok(53));
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
describe("whitespace handling", () => {
|
|
179
|
+
test("parses with single space", () => {
|
|
180
|
+
expect(parseDuration("1 s")).toEqual(ok(1000));
|
|
181
|
+
expect(parseDuration("5 m")).toEqual(ok(5 * 60 * 1000));
|
|
182
|
+
expect(parseDuration("2 h")).toEqual(ok(2 * 60 * 60 * 1000));
|
|
183
|
+
});
|
|
184
|
+
test("parses with multiple spaces", () => {
|
|
185
|
+
expect(parseDuration("1 s")).toEqual(ok(1000));
|
|
186
|
+
expect(parseDuration("5 m")).toEqual(ok(5 * 60 * 1000));
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
describe("edge cases", () => {
|
|
190
|
+
test("parses zero values", () => {
|
|
191
|
+
expect(parseDuration("0ms")).toEqual(ok(0));
|
|
192
|
+
expect(parseDuration("0s")).toEqual(ok(0));
|
|
193
|
+
expect(parseDuration("0m")).toEqual(ok(0));
|
|
194
|
+
expect(parseDuration("0h")).toEqual(ok(0));
|
|
195
|
+
expect(parseDuration("0d")).toEqual(ok(0));
|
|
196
|
+
expect(parseDuration("0")).toEqual(ok(0));
|
|
197
|
+
});
|
|
198
|
+
test("parses very small decimals", () => {
|
|
199
|
+
expect(parseDuration("0.001s")).toEqual(ok(1));
|
|
200
|
+
expect(parseDuration("0.1ms")).toEqual(ok(0.1));
|
|
201
|
+
});
|
|
202
|
+
test("parses large numbers", () => {
|
|
203
|
+
expect(parseDuration("999999ms")).toEqual(ok(999_999));
|
|
204
|
+
expect(parseDuration("1000s")).toEqual(ok(1_000_000));
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
describe("error cases", () => {
|
|
208
|
+
test("returns error on invalid format", () => {
|
|
209
|
+
// @ts-expect-error - invalid format
|
|
210
|
+
expect(parseDuration("invalid")).toEqual(err(new Error('Invalid duration format: "invalid"')));
|
|
211
|
+
// @ts-expect-error - invalid format
|
|
212
|
+
expect(parseDuration("10-.5")).toEqual(err(new Error('Invalid duration format: "10-.5"')));
|
|
213
|
+
// @ts-expect-error - invalid format
|
|
214
|
+
expect(parseDuration("foo")).toEqual(err(new Error('Invalid duration format: "foo"')));
|
|
215
|
+
});
|
|
216
|
+
test("returns error on empty string", () => {
|
|
217
|
+
// @ts-expect-error - empty string
|
|
218
|
+
expect(parseDuration("")).toEqual(err(new Error('Invalid duration format: ""')));
|
|
219
|
+
});
|
|
220
|
+
test("returns error on missing number", () => {
|
|
221
|
+
// @ts-expect-error - unit without number
|
|
222
|
+
expect(parseDuration("ms")).toEqual(err(new Error('Invalid duration format: "ms"')));
|
|
223
|
+
// @ts-expect-error - unit without number
|
|
224
|
+
expect(parseDuration("s")).toEqual(err(new Error('Invalid duration format: "s"')));
|
|
225
|
+
// @ts-expect-error - unit without number
|
|
226
|
+
expect(parseDuration("m")).toEqual(err(new Error('Invalid duration format: "m"')));
|
|
227
|
+
// @ts-expect-error - unit without number
|
|
228
|
+
expect(parseDuration("h")).toEqual(err(new Error('Invalid duration format: "h"')));
|
|
229
|
+
});
|
|
230
|
+
test("returns error on unknown unit", () => {
|
|
231
|
+
// @ts-expect-error - unknown unit
|
|
232
|
+
expect(parseDuration("100x")).toEqual(err(new Error('Invalid duration format: "100x"')));
|
|
233
|
+
// @ts-expect-error - unknown unit
|
|
234
|
+
expect(parseDuration("5z")).toEqual(err(new Error('Invalid duration format: "5z"')));
|
|
235
|
+
});
|
|
236
|
+
test("returns error on multiple units", () => {
|
|
237
|
+
// @ts-expect-error - multiple units
|
|
238
|
+
expect(parseDuration("1h30m")).toEqual(err(new Error('Invalid duration format: "1h30m"')));
|
|
239
|
+
// @ts-expect-error - multiple units
|
|
240
|
+
expect(parseDuration("5s100ms")).toEqual(err(new Error('Invalid duration format: "5s100ms"')));
|
|
241
|
+
});
|
|
242
|
+
test("returns error on leading/trailing spaces", () => {
|
|
243
|
+
expect(parseDuration(" 5s")).toEqual(err(new Error('Invalid duration format: " 5s"')));
|
|
244
|
+
// @ts-expect-error - trailing space
|
|
245
|
+
expect(parseDuration("5s ")).toEqual(err(new Error('Invalid duration format: "5s "')));
|
|
246
|
+
});
|
|
247
|
+
test("returns error on special characters", () => {
|
|
248
|
+
// @ts-expect-error - special characters
|
|
249
|
+
expect(parseDuration("5s!")).toEqual(err(new Error('Invalid duration format: "5s!"')));
|
|
250
|
+
// @ts-expect-error - special characters
|
|
251
|
+
expect(parseDuration("@5s")).toEqual(err(new Error('Invalid duration format: "@5s"')));
|
|
252
|
+
});
|
|
253
|
+
test("returns error on non-string types", () => {
|
|
254
|
+
expect(parseDuration(undefined)).toEqual(err(new TypeError("Invalid duration format: expected a string but received undefined")));
|
|
255
|
+
expect(parseDuration(null)).toEqual(err(new TypeError("Invalid duration format: expected a string but received object")));
|
|
256
|
+
expect(parseDuration([])).toEqual(err(new TypeError("Invalid duration format: expected a string but received object")));
|
|
257
|
+
expect(parseDuration({})).toEqual(err(new TypeError("Invalid duration format: expected a string but received object")));
|
|
258
|
+
expect(parseDuration(Number.NaN)).toEqual(err(new TypeError("Invalid duration format: expected a string but received number")));
|
|
259
|
+
expect(parseDuration(Number.POSITIVE_INFINITY)).toEqual(err(new TypeError("Invalid duration format: expected a string but received number")));
|
|
260
|
+
expect(parseDuration(Number.NEGATIVE_INFINITY)).toEqual(err(new TypeError("Invalid duration format: expected a string but received number")));
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
});
|
package/dist/core/error.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.test.d.ts","sourceRoot":"","sources":["../../core/error.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { serializeError } from "./error.js";
|
|
2
|
+
import { describe, expect, test } from "vitest";
|
|
3
|
+
describe("serializeError", () => {
|
|
4
|
+
test("serializes Error instance with name, message, and stack", () => {
|
|
5
|
+
const error = new Error("Something went wrong");
|
|
6
|
+
const result = serializeError(error);
|
|
7
|
+
expect(result.name).toBe("Error");
|
|
8
|
+
expect(result.message).toBe("Something went wrong");
|
|
9
|
+
expect(result.stack).toBeDefined();
|
|
10
|
+
expect(typeof result.stack).toBe("string");
|
|
11
|
+
});
|
|
12
|
+
test("serializes TypeError with correct name", () => {
|
|
13
|
+
const error = new TypeError("Invalid type");
|
|
14
|
+
const result = serializeError(error);
|
|
15
|
+
expect(result.name).toBe("TypeError");
|
|
16
|
+
expect(result.message).toBe("Invalid type");
|
|
17
|
+
});
|
|
18
|
+
test("serializes custom Error subclass", () => {
|
|
19
|
+
class CustomError extends Error {
|
|
20
|
+
constructor(message) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = "CustomError";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const error = new CustomError("Custom error message");
|
|
26
|
+
const result = serializeError(error);
|
|
27
|
+
expect(result.name).toBe("CustomError");
|
|
28
|
+
expect(result.message).toBe("Custom error message");
|
|
29
|
+
});
|
|
30
|
+
test("serializes Error without stack as undefined", () => {
|
|
31
|
+
const error = new Error("No stack");
|
|
32
|
+
// @ts-expect-error testing edge case
|
|
33
|
+
error.stack = undefined;
|
|
34
|
+
const result = serializeError(error);
|
|
35
|
+
expect(result.stack).toBeUndefined();
|
|
36
|
+
});
|
|
37
|
+
test("serializes string to message", () => {
|
|
38
|
+
const result = serializeError("string error");
|
|
39
|
+
expect(result.message).toBe("string error");
|
|
40
|
+
expect(result.name).toBeUndefined();
|
|
41
|
+
expect(result.stack).toBeUndefined();
|
|
42
|
+
});
|
|
43
|
+
test("serializes number to message", () => {
|
|
44
|
+
const result = serializeError(42);
|
|
45
|
+
expect(result.message).toBe("42");
|
|
46
|
+
});
|
|
47
|
+
test("serializes null to message", () => {
|
|
48
|
+
const result = serializeError(null);
|
|
49
|
+
expect(result.message).toBe("null");
|
|
50
|
+
});
|
|
51
|
+
test("serializes undefined to message", () => {
|
|
52
|
+
// eslint-disable-next-line unicorn/no-useless-undefined
|
|
53
|
+
const result = serializeError(undefined);
|
|
54
|
+
expect(result.message).toBe("undefined");
|
|
55
|
+
});
|
|
56
|
+
test("serializes object to message using String()", () => {
|
|
57
|
+
const result = serializeError({ foo: "bar" });
|
|
58
|
+
expect(result.message).toBe("[object Object]");
|
|
59
|
+
});
|
|
60
|
+
});
|
package/dist/core/json.js
CHANGED
package/dist/core/result.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.test.d.ts","sourceRoot":"","sources":["../../core/result.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ok, err } from "./result.js";
|
|
2
|
+
import { describe, expect, test } from "vitest";
|
|
3
|
+
describe("Result helpers", () => {
|
|
4
|
+
test("ok creates success result", () => {
|
|
5
|
+
expect(ok(123)).toEqual({ ok: true, value: 123 });
|
|
6
|
+
});
|
|
7
|
+
test("err creates error result", () => {
|
|
8
|
+
const error = new Error("oops");
|
|
9
|
+
expect(err(error)).toEqual({ ok: false, error });
|
|
10
|
+
});
|
|
11
|
+
});
|
package/dist/core/retry.js
CHANGED
package/dist/core/schema.js
CHANGED
package/dist/core/step.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step.test.d.ts","sourceRoot":"","sources":["../../core/step.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { ok } from "./result.js";
|
|
2
|
+
import { createStepAttemptCacheFromAttempts, getCachedStepAttempt, addToStepAttemptCache, normalizeStepOutput, calculateSleepResumeAt, createSleepContext, } from "./step.js";
|
|
3
|
+
import { describe, expect, test } from "vitest";
|
|
4
|
+
describe("createStepAttemptCacheFromAttempts", () => {
|
|
5
|
+
test("creates empty cache from empty array", () => {
|
|
6
|
+
const cache = createStepAttemptCacheFromAttempts([]);
|
|
7
|
+
expect(cache.size).toBe(0);
|
|
8
|
+
});
|
|
9
|
+
test("includes completed attempts in cache", () => {
|
|
10
|
+
const attempt = createMockStepAttempt({
|
|
11
|
+
stepName: "step-a",
|
|
12
|
+
status: "completed",
|
|
13
|
+
output: "result",
|
|
14
|
+
});
|
|
15
|
+
const cache = createStepAttemptCacheFromAttempts([attempt]);
|
|
16
|
+
expect(cache.size).toBe(1);
|
|
17
|
+
expect(cache.get("step-a")).toBe(attempt);
|
|
18
|
+
});
|
|
19
|
+
test("includes succeeded attempts in cache (deprecated status)", () => {
|
|
20
|
+
const attempt = createMockStepAttempt({
|
|
21
|
+
stepName: "step-b",
|
|
22
|
+
status: "succeeded",
|
|
23
|
+
output: "result",
|
|
24
|
+
});
|
|
25
|
+
const cache = createStepAttemptCacheFromAttempts([attempt]);
|
|
26
|
+
expect(cache.size).toBe(1);
|
|
27
|
+
expect(cache.get("step-b")).toBe(attempt);
|
|
28
|
+
});
|
|
29
|
+
test("excludes running attempts from cache", () => {
|
|
30
|
+
const attempt = createMockStepAttempt({
|
|
31
|
+
stepName: "step-c",
|
|
32
|
+
status: "running",
|
|
33
|
+
});
|
|
34
|
+
const cache = createStepAttemptCacheFromAttempts([attempt]);
|
|
35
|
+
expect(cache.size).toBe(0);
|
|
36
|
+
});
|
|
37
|
+
test("excludes failed attempts from cache", () => {
|
|
38
|
+
const attempt = createMockStepAttempt({
|
|
39
|
+
stepName: "step-d",
|
|
40
|
+
status: "failed",
|
|
41
|
+
error: { message: "failed" },
|
|
42
|
+
});
|
|
43
|
+
const cache = createStepAttemptCacheFromAttempts([attempt]);
|
|
44
|
+
expect(cache.size).toBe(0);
|
|
45
|
+
});
|
|
46
|
+
test("filters mixed statuses correctly", () => {
|
|
47
|
+
const attempts = [
|
|
48
|
+
createMockStepAttempt({
|
|
49
|
+
stepName: "completed-step",
|
|
50
|
+
status: "completed",
|
|
51
|
+
}),
|
|
52
|
+
createMockStepAttempt({ stepName: "running-step", status: "running" }),
|
|
53
|
+
createMockStepAttempt({ stepName: "failed-step", status: "failed" }),
|
|
54
|
+
createMockStepAttempt({
|
|
55
|
+
stepName: "succeeded-step",
|
|
56
|
+
status: "succeeded",
|
|
57
|
+
}),
|
|
58
|
+
];
|
|
59
|
+
const cache = createStepAttemptCacheFromAttempts(attempts);
|
|
60
|
+
expect(cache.size).toBe(2);
|
|
61
|
+
expect(cache.has("completed-step")).toBe(true);
|
|
62
|
+
expect(cache.has("succeeded-step")).toBe(true);
|
|
63
|
+
expect(cache.has("running-step")).toBe(false);
|
|
64
|
+
expect(cache.has("failed-step")).toBe(false);
|
|
65
|
+
});
|
|
66
|
+
test("uses step name as cache key", () => {
|
|
67
|
+
const attempt = createMockStepAttempt({
|
|
68
|
+
stepName: "my-unique-step-name",
|
|
69
|
+
status: "completed",
|
|
70
|
+
});
|
|
71
|
+
const cache = createStepAttemptCacheFromAttempts([attempt]);
|
|
72
|
+
expect(cache.get("my-unique-step-name")).toBe(attempt);
|
|
73
|
+
expect(cache.get("other-name")).toBeUndefined();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
describe("getCachedStepAttempt", () => {
|
|
77
|
+
test("returns cached attempt when present", () => {
|
|
78
|
+
const attempt = createMockStepAttempt({ stepName: "cached-step" });
|
|
79
|
+
const cache = new Map([["cached-step", attempt]]);
|
|
80
|
+
const result = getCachedStepAttempt(cache, "cached-step");
|
|
81
|
+
expect(result).toBe(attempt);
|
|
82
|
+
});
|
|
83
|
+
test("returns undefined when step not in cache", () => {
|
|
84
|
+
const cache = new Map();
|
|
85
|
+
const result = getCachedStepAttempt(cache, "missing-step");
|
|
86
|
+
expect(result).toBeUndefined();
|
|
87
|
+
});
|
|
88
|
+
test("returns undefined for similar but different step names", () => {
|
|
89
|
+
const attempt = createMockStepAttempt({ stepName: "step-1" });
|
|
90
|
+
const cache = new Map([["step-1", attempt]]);
|
|
91
|
+
expect(getCachedStepAttempt(cache, "step-2")).toBeUndefined();
|
|
92
|
+
expect(getCachedStepAttempt(cache, "Step-1")).toBeUndefined();
|
|
93
|
+
expect(getCachedStepAttempt(cache, "step-1 ")).toBeUndefined();
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
describe("addToStepAttemptCache", () => {
|
|
97
|
+
test("adds attempt to empty cache", () => {
|
|
98
|
+
const cache = new Map();
|
|
99
|
+
const attempt = createMockStepAttempt({ stepName: "new-step" });
|
|
100
|
+
const newCache = addToStepAttemptCache(cache, attempt);
|
|
101
|
+
expect(newCache.size).toBe(1);
|
|
102
|
+
expect(newCache.get("new-step")).toBe(attempt);
|
|
103
|
+
});
|
|
104
|
+
test("adds attempt to existing cache", () => {
|
|
105
|
+
const existing = createMockStepAttempt({ stepName: "existing-step" });
|
|
106
|
+
const cache = new Map([["existing-step", existing]]);
|
|
107
|
+
const newAttempt = createMockStepAttempt({ stepName: "new-step" });
|
|
108
|
+
const newCache = addToStepAttemptCache(cache, newAttempt);
|
|
109
|
+
expect(newCache.size).toBe(2);
|
|
110
|
+
expect(newCache.get("existing-step")).toBe(existing);
|
|
111
|
+
expect(newCache.get("new-step")).toBe(newAttempt);
|
|
112
|
+
});
|
|
113
|
+
test("does not mutate original cache (immutable)", () => {
|
|
114
|
+
const existing = createMockStepAttempt({ stepName: "existing-step" });
|
|
115
|
+
const cache = new Map([["existing-step", existing]]);
|
|
116
|
+
const newAttempt = createMockStepAttempt({ stepName: "new-step" });
|
|
117
|
+
const newCache = addToStepAttemptCache(cache, newAttempt);
|
|
118
|
+
expect(cache.size).toBe(1);
|
|
119
|
+
expect(cache.has("new-step")).toBe(false);
|
|
120
|
+
expect(newCache.size).toBe(2);
|
|
121
|
+
});
|
|
122
|
+
test("overwrites existing entry with same step name", () => {
|
|
123
|
+
const original = createMockStepAttempt({
|
|
124
|
+
stepName: "step",
|
|
125
|
+
output: "original",
|
|
126
|
+
});
|
|
127
|
+
const cache = new Map([["step", original]]);
|
|
128
|
+
const replacement = createMockStepAttempt({
|
|
129
|
+
stepName: "step",
|
|
130
|
+
output: "replacement",
|
|
131
|
+
});
|
|
132
|
+
const newCache = addToStepAttemptCache(cache, replacement);
|
|
133
|
+
expect(newCache.size).toBe(1);
|
|
134
|
+
expect(newCache.get("step")?.output).toBe("replacement");
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
describe("normalizeStepOutput", () => {
|
|
138
|
+
test("passes through string values", () => {
|
|
139
|
+
expect(normalizeStepOutput("hello")).toBe("hello");
|
|
140
|
+
});
|
|
141
|
+
test("passes through number values", () => {
|
|
142
|
+
expect(normalizeStepOutput(42)).toBe(42);
|
|
143
|
+
expect(normalizeStepOutput(3.14)).toBe(3.14);
|
|
144
|
+
expect(normalizeStepOutput(0)).toBe(0);
|
|
145
|
+
expect(normalizeStepOutput(-1)).toBe(-1);
|
|
146
|
+
});
|
|
147
|
+
test("passes through boolean values", () => {
|
|
148
|
+
expect(normalizeStepOutput(true)).toBe(true);
|
|
149
|
+
expect(normalizeStepOutput(false)).toBe(false);
|
|
150
|
+
});
|
|
151
|
+
test("passes through null", () => {
|
|
152
|
+
expect(normalizeStepOutput(null)).toBeNull();
|
|
153
|
+
});
|
|
154
|
+
test("converts undefined to null", () => {
|
|
155
|
+
// eslint-disable-next-line unicorn/no-useless-undefined
|
|
156
|
+
expect(normalizeStepOutput(undefined)).toBeNull();
|
|
157
|
+
});
|
|
158
|
+
test("passes through object values", () => {
|
|
159
|
+
const obj = { foo: "bar", nested: { baz: 123 } };
|
|
160
|
+
expect(normalizeStepOutput(obj)).toBe(obj);
|
|
161
|
+
});
|
|
162
|
+
test("passes through array values", () => {
|
|
163
|
+
const arr = [1, 2, 3];
|
|
164
|
+
expect(normalizeStepOutput(arr)).toBe(arr);
|
|
165
|
+
});
|
|
166
|
+
test("passes through empty object", () => {
|
|
167
|
+
const obj = {};
|
|
168
|
+
expect(normalizeStepOutput(obj)).toBe(obj);
|
|
169
|
+
});
|
|
170
|
+
test("passes through empty array", () => {
|
|
171
|
+
const arr = [];
|
|
172
|
+
expect(normalizeStepOutput(arr)).toBe(arr);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
describe("calculateSleepResumeAt", () => {
|
|
176
|
+
test("calculates resume time from duration string", () => {
|
|
177
|
+
const now = 1_000_000;
|
|
178
|
+
const result = calculateSleepResumeAt("5s", now);
|
|
179
|
+
expect(result).toEqual(ok(new Date(now + 5000)));
|
|
180
|
+
});
|
|
181
|
+
test("calculates resume time with milliseconds", () => {
|
|
182
|
+
const now = 1_000_000;
|
|
183
|
+
const result = calculateSleepResumeAt("500ms", now);
|
|
184
|
+
expect(result).toEqual(ok(new Date(now + 500)));
|
|
185
|
+
});
|
|
186
|
+
test("calculates resume time with minutes", () => {
|
|
187
|
+
const now = 1_000_000;
|
|
188
|
+
const result = calculateSleepResumeAt("2m", now);
|
|
189
|
+
expect(result).toEqual(ok(new Date(now + 2 * 60 * 1000)));
|
|
190
|
+
});
|
|
191
|
+
test("calculates resume time with hours", () => {
|
|
192
|
+
const now = 1_000_000;
|
|
193
|
+
const result = calculateSleepResumeAt("1h", now);
|
|
194
|
+
expect(result).toEqual(ok(new Date(now + 60 * 60 * 1000)));
|
|
195
|
+
});
|
|
196
|
+
test("uses Date.now() when now is not provided", () => {
|
|
197
|
+
const before = Date.now();
|
|
198
|
+
const result = calculateSleepResumeAt("1s");
|
|
199
|
+
const after = Date.now();
|
|
200
|
+
expect(result.ok).toBe(true);
|
|
201
|
+
if (result.ok) {
|
|
202
|
+
const resumeTime = result.value.getTime();
|
|
203
|
+
expect(resumeTime).toBeGreaterThanOrEqual(before + 1000);
|
|
204
|
+
expect(resumeTime).toBeLessThanOrEqual(after + 1000);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
test("returns error for invalid duration", () => {
|
|
208
|
+
// @ts-expect-error testing invalid input
|
|
209
|
+
const result = calculateSleepResumeAt("invalid");
|
|
210
|
+
expect(result.ok).toBe(false);
|
|
211
|
+
if (!result.ok) {
|
|
212
|
+
expect(result.error).toBeInstanceOf(Error);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
test("returns error for empty duration", () => {
|
|
216
|
+
// @ts-expect-error testing invalid input
|
|
217
|
+
const result = calculateSleepResumeAt("");
|
|
218
|
+
expect(result.ok).toBe(false);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
describe("createSleepContext", () => {
|
|
222
|
+
test("creates sleep context with ISO string timestamp", () => {
|
|
223
|
+
const resumeAt = new Date("2025-06-15T10:30:00.000Z");
|
|
224
|
+
const context = createSleepContext(resumeAt);
|
|
225
|
+
expect(context).toEqual({
|
|
226
|
+
kind: "sleep",
|
|
227
|
+
resumeAt: "2025-06-15T10:30:00.000Z",
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
test("preserves millisecond precision", () => {
|
|
231
|
+
const resumeAt = new Date("2025-01-01T00:00:00.123Z");
|
|
232
|
+
const context = createSleepContext(resumeAt);
|
|
233
|
+
expect(context.resumeAt).toBe("2025-01-01T00:00:00.123Z");
|
|
234
|
+
});
|
|
235
|
+
test("always has kind set to sleep", () => {
|
|
236
|
+
const resumeAt = new Date();
|
|
237
|
+
const context = createSleepContext(resumeAt);
|
|
238
|
+
expect(context.kind).toBe("sleep");
|
|
239
|
+
});
|
|
240
|
+
test("creates context from current date", () => {
|
|
241
|
+
const now = new Date();
|
|
242
|
+
const context = createSleepContext(now);
|
|
243
|
+
expect(context.resumeAt).toBe(now.toISOString());
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
function createMockStepAttempt(overrides = {}) {
|
|
247
|
+
return {
|
|
248
|
+
namespaceId: "default",
|
|
249
|
+
id: "step-1",
|
|
250
|
+
workflowRunId: "workflow-1",
|
|
251
|
+
stepName: "test-step",
|
|
252
|
+
kind: "function",
|
|
253
|
+
status: "completed",
|
|
254
|
+
config: {},
|
|
255
|
+
context: null,
|
|
256
|
+
output: null,
|
|
257
|
+
error: null,
|
|
258
|
+
childWorkflowRunNamespaceId: null,
|
|
259
|
+
childWorkflowRunId: null,
|
|
260
|
+
startedAt: new Date("2025-01-01T00:00:00Z"),
|
|
261
|
+
finishedAt: new Date("2025-01-01T00:00:01Z"),
|
|
262
|
+
createdAt: new Date("2025-01-01T00:00:00Z"),
|
|
263
|
+
updatedAt: new Date("2025-01-01T00:00:01Z"),
|
|
264
|
+
...overrides,
|
|
265
|
+
};
|
|
266
|
+
}
|
package/dist/core/workflow.js
CHANGED