@enactprotocol/shared 1.2.13 → 2.0.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 +44 -0
- package/package.json +16 -58
- package/src/config.ts +476 -0
- package/src/constants.ts +36 -0
- package/src/execution/command.ts +314 -0
- package/src/execution/index.ts +73 -0
- package/src/execution/runtime.ts +308 -0
- package/src/execution/types.ts +379 -0
- package/src/execution/validation.ts +508 -0
- package/src/index.ts +237 -30
- package/src/manifest/index.ts +36 -0
- package/src/manifest/loader.ts +187 -0
- package/src/manifest/parser.ts +173 -0
- package/src/manifest/validator.ts +309 -0
- package/src/paths.ts +108 -0
- package/src/registry.ts +219 -0
- package/src/resolver.ts +345 -0
- package/src/types/index.ts +30 -0
- package/src/types/manifest.ts +255 -0
- package/src/types.ts +5 -188
- package/src/utils/fs.ts +281 -0
- package/src/utils/logger.ts +270 -59
- package/src/utils/version.ts +304 -36
- package/tests/config.test.ts +515 -0
- package/tests/execution/command.test.ts +317 -0
- package/tests/execution/validation.test.ts +384 -0
- package/tests/fixtures/invalid-tool.yaml +4 -0
- package/tests/fixtures/valid-tool.md +62 -0
- package/tests/fixtures/valid-tool.yaml +40 -0
- package/tests/index.test.ts +8 -0
- package/tests/manifest/loader.test.ts +291 -0
- package/tests/manifest/parser.test.ts +345 -0
- package/tests/manifest/validator.test.ts +394 -0
- package/tests/manifest-types.test.ts +358 -0
- package/tests/paths.test.ts +153 -0
- package/tests/registry.test.ts +231 -0
- package/tests/resolver.test.ts +272 -0
- package/tests/utils/fs.test.ts +388 -0
- package/tests/utils/logger.test.ts +480 -0
- package/tests/utils/version.test.ts +390 -0
- package/tsconfig.json +12 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/dist/LocalToolResolver.d.ts +0 -84
- package/dist/LocalToolResolver.js +0 -353
- package/dist/api/enact-api.d.ts +0 -130
- package/dist/api/enact-api.js +0 -428
- package/dist/api/index.d.ts +0 -2
- package/dist/api/index.js +0 -2
- package/dist/api/types.d.ts +0 -103
- package/dist/api/types.js +0 -1
- package/dist/constants.d.ts +0 -7
- package/dist/constants.js +0 -10
- package/dist/core/DaggerExecutionProvider.d.ts +0 -169
- package/dist/core/DaggerExecutionProvider.js +0 -1029
- package/dist/core/DirectExecutionProvider.d.ts +0 -23
- package/dist/core/DirectExecutionProvider.js +0 -406
- package/dist/core/EnactCore.d.ts +0 -162
- package/dist/core/EnactCore.js +0 -597
- package/dist/core/NativeExecutionProvider.d.ts +0 -9
- package/dist/core/NativeExecutionProvider.js +0 -16
- package/dist/core/index.d.ts +0 -3
- package/dist/core/index.js +0 -3
- package/dist/exec/index.d.ts +0 -3
- package/dist/exec/index.js +0 -3
- package/dist/exec/logger.d.ts +0 -11
- package/dist/exec/logger.js +0 -57
- package/dist/exec/validate.d.ts +0 -5
- package/dist/exec/validate.js +0 -167
- package/dist/index.d.ts +0 -21
- package/dist/index.js +0 -25
- package/dist/lib/enact-direct.d.ts +0 -150
- package/dist/lib/enact-direct.js +0 -159
- package/dist/lib/index.d.ts +0 -1
- package/dist/lib/index.js +0 -1
- package/dist/security/index.d.ts +0 -3
- package/dist/security/index.js +0 -3
- package/dist/security/security.d.ts +0 -23
- package/dist/security/security.js +0 -137
- package/dist/security/sign.d.ts +0 -103
- package/dist/security/sign.js +0 -666
- package/dist/security/verification-enforcer.d.ts +0 -53
- package/dist/security/verification-enforcer.js +0 -204
- package/dist/services/McpCoreService.d.ts +0 -98
- package/dist/services/McpCoreService.js +0 -124
- package/dist/services/index.d.ts +0 -1
- package/dist/services/index.js +0 -1
- package/dist/types.d.ts +0 -132
- package/dist/types.js +0 -3
- package/dist/utils/config.d.ts +0 -111
- package/dist/utils/config.js +0 -342
- package/dist/utils/env-loader.d.ts +0 -54
- package/dist/utils/env-loader.js +0 -270
- package/dist/utils/help.d.ts +0 -36
- package/dist/utils/help.js +0 -248
- package/dist/utils/index.d.ts +0 -7
- package/dist/utils/index.js +0 -7
- package/dist/utils/logger.d.ts +0 -35
- package/dist/utils/logger.js +0 -75
- package/dist/utils/silent-monitor.d.ts +0 -67
- package/dist/utils/silent-monitor.js +0 -242
- package/dist/utils/timeout.d.ts +0 -5
- package/dist/utils/timeout.js +0 -23
- package/dist/utils/version.d.ts +0 -4
- package/dist/utils/version.js +0 -35
- package/dist/web/env-manager-server.d.ts +0 -29
- package/dist/web/env-manager-server.js +0 -367
- package/dist/web/index.d.ts +0 -1
- package/dist/web/index.js +0 -1
- package/src/LocalToolResolver.ts +0 -424
- package/src/api/enact-api.ts +0 -604
- package/src/api/index.ts +0 -2
- package/src/api/types.ts +0 -114
- package/src/core/DaggerExecutionProvider.ts +0 -1357
- package/src/core/DirectExecutionProvider.ts +0 -484
- package/src/core/EnactCore.ts +0 -847
- package/src/core/index.ts +0 -3
- package/src/exec/index.ts +0 -3
- package/src/exec/logger.ts +0 -63
- package/src/exec/validate.ts +0 -238
- package/src/lib/enact-direct.ts +0 -254
- package/src/lib/index.ts +0 -1
- package/src/services/McpCoreService.ts +0 -201
- package/src/services/index.ts +0 -1
- package/src/utils/config.ts +0 -438
- package/src/utils/env-loader.ts +0 -370
- package/src/utils/help.ts +0 -257
- package/src/utils/index.ts +0 -7
- package/src/utils/silent-monitor.ts +0 -328
- package/src/utils/timeout.ts +0 -26
- package/src/web/env-manager-server.ts +0 -465
- package/src/web/index.ts +0 -1
- package/src/web/static/app.js +0 -663
- package/src/web/static/index.html +0 -117
- package/src/web/static/style.css +0 -291
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import {
|
|
3
|
+
isValidTimeout,
|
|
4
|
+
isValidToolName,
|
|
5
|
+
isValidVersion,
|
|
6
|
+
validateManifest,
|
|
7
|
+
validateManifestStrict,
|
|
8
|
+
} from "../../src/manifest/validator";
|
|
9
|
+
|
|
10
|
+
describe("manifest validator", () => {
|
|
11
|
+
describe("validateManifest", () => {
|
|
12
|
+
test("validates minimal valid manifest", () => {
|
|
13
|
+
const manifest = {
|
|
14
|
+
name: "org/tool",
|
|
15
|
+
description: "A test tool",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const result = validateManifest(manifest);
|
|
19
|
+
expect(result.valid).toBe(true);
|
|
20
|
+
expect(result.errors).toBeUndefined();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("validates complete manifest", () => {
|
|
24
|
+
const manifest = {
|
|
25
|
+
enact: "2.0.0",
|
|
26
|
+
name: "acme/utils/greeter",
|
|
27
|
+
description: "Greets users by name",
|
|
28
|
+
version: "1.0.0",
|
|
29
|
+
from: "node:18-alpine",
|
|
30
|
+
command: "echo 'Hello ${name}'",
|
|
31
|
+
timeout: "30s",
|
|
32
|
+
license: "MIT",
|
|
33
|
+
tags: ["greeting", "utility"],
|
|
34
|
+
inputSchema: {
|
|
35
|
+
type: "object",
|
|
36
|
+
properties: {
|
|
37
|
+
name: { type: "string" },
|
|
38
|
+
},
|
|
39
|
+
required: ["name"],
|
|
40
|
+
},
|
|
41
|
+
outputSchema: {
|
|
42
|
+
type: "object",
|
|
43
|
+
properties: {
|
|
44
|
+
message: { type: "string" },
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
env: {
|
|
48
|
+
API_KEY: {
|
|
49
|
+
description: "API authentication key",
|
|
50
|
+
secret: true,
|
|
51
|
+
},
|
|
52
|
+
LOG_LEVEL: {
|
|
53
|
+
description: "Logging level",
|
|
54
|
+
default: "info",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
annotations: {
|
|
58
|
+
readOnlyHint: true,
|
|
59
|
+
idempotentHint: true,
|
|
60
|
+
},
|
|
61
|
+
resources: {
|
|
62
|
+
memory: "512Mi",
|
|
63
|
+
},
|
|
64
|
+
authors: [
|
|
65
|
+
{
|
|
66
|
+
name: "Alice",
|
|
67
|
+
email: "alice@example.com",
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
examples: [
|
|
71
|
+
{
|
|
72
|
+
input: { name: "World" },
|
|
73
|
+
output: { message: "Hello World" },
|
|
74
|
+
description: "Basic greeting",
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const result = validateManifest(manifest);
|
|
80
|
+
expect(result.valid).toBe(true);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("fails for missing name", () => {
|
|
84
|
+
const manifest = {
|
|
85
|
+
description: "A test tool",
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const result = validateManifest(manifest);
|
|
89
|
+
expect(result.valid).toBe(false);
|
|
90
|
+
expect(result.errors).toBeDefined();
|
|
91
|
+
expect(result.errors?.some((e) => e.path === "name")).toBe(true);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("fails for missing description", () => {
|
|
95
|
+
const manifest = {
|
|
96
|
+
name: "org/tool",
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const result = validateManifest(manifest);
|
|
100
|
+
expect(result.valid).toBe(false);
|
|
101
|
+
expect(result.errors?.some((e) => e.path === "description")).toBe(true);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("fails for invalid tool name format", () => {
|
|
105
|
+
const manifest = {
|
|
106
|
+
name: "invalid-name", // Must have at least one slash
|
|
107
|
+
description: "Test",
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const result = validateManifest(manifest);
|
|
111
|
+
expect(result.valid).toBe(false);
|
|
112
|
+
expect(result.errors?.some((e) => e.path === "name")).toBe(true);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("fails for tool name with uppercase", () => {
|
|
116
|
+
const manifest = {
|
|
117
|
+
name: "Org/Tool", // Must be lowercase
|
|
118
|
+
description: "Test",
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const result = validateManifest(manifest);
|
|
122
|
+
expect(result.valid).toBe(false);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("fails for invalid version format", () => {
|
|
126
|
+
const manifest = {
|
|
127
|
+
name: "org/tool",
|
|
128
|
+
description: "Test",
|
|
129
|
+
version: "invalid", // Not semver
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const result = validateManifest(manifest);
|
|
133
|
+
expect(result.valid).toBe(false);
|
|
134
|
+
expect(result.errors?.some((e) => e.path === "version")).toBe(true);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test("fails for invalid timeout format", () => {
|
|
138
|
+
const manifest = {
|
|
139
|
+
name: "org/tool",
|
|
140
|
+
description: "Test",
|
|
141
|
+
timeout: "30seconds", // Should be "30s"
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const result = validateManifest(manifest);
|
|
145
|
+
expect(result.valid).toBe(false);
|
|
146
|
+
expect(result.errors?.some((e) => e.path === "timeout")).toBe(true);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("accepts valid timeout formats", () => {
|
|
150
|
+
const timeouts = ["30s", "5m", "1h", "100ms", "1000ns"];
|
|
151
|
+
|
|
152
|
+
for (const timeout of timeouts) {
|
|
153
|
+
const manifest = {
|
|
154
|
+
name: "org/tool",
|
|
155
|
+
description: "Test",
|
|
156
|
+
timeout,
|
|
157
|
+
};
|
|
158
|
+
const result = validateManifest(manifest);
|
|
159
|
+
expect(result.valid).toBe(true);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test("accepts valid semver versions", () => {
|
|
164
|
+
const versions = [
|
|
165
|
+
"1.0.0",
|
|
166
|
+
"0.1.0",
|
|
167
|
+
"10.20.30",
|
|
168
|
+
"1.0.0-alpha",
|
|
169
|
+
"1.0.0-beta.1",
|
|
170
|
+
"1.0.0+build.123",
|
|
171
|
+
];
|
|
172
|
+
|
|
173
|
+
for (const version of versions) {
|
|
174
|
+
const manifest = {
|
|
175
|
+
name: "org/tool",
|
|
176
|
+
description: "Test",
|
|
177
|
+
version,
|
|
178
|
+
};
|
|
179
|
+
const result = validateManifest(manifest);
|
|
180
|
+
expect(result.valid).toBe(true);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test("fails for description over 500 characters", () => {
|
|
185
|
+
const manifest = {
|
|
186
|
+
name: "org/tool",
|
|
187
|
+
description: "a".repeat(501),
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const result = validateManifest(manifest);
|
|
191
|
+
expect(result.valid).toBe(false);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
test("validates env variable with missing description", () => {
|
|
195
|
+
const manifest = {
|
|
196
|
+
name: "org/tool",
|
|
197
|
+
description: "Test",
|
|
198
|
+
env: {
|
|
199
|
+
API_KEY: {
|
|
200
|
+
// Missing description
|
|
201
|
+
secret: true,
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const result = validateManifest(manifest);
|
|
207
|
+
expect(result.valid).toBe(false);
|
|
208
|
+
expect(result.errors?.some((e) => e.path.includes("env"))).toBe(true);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test("allows custom x- fields", () => {
|
|
212
|
+
const manifest = {
|
|
213
|
+
name: "org/tool",
|
|
214
|
+
description: "Test",
|
|
215
|
+
"x-custom": "value",
|
|
216
|
+
"x-another": { nested: true },
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const result = validateManifest(manifest);
|
|
220
|
+
expect(result.valid).toBe(true);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
test("accepts valid tool name formats", () => {
|
|
224
|
+
const names = [
|
|
225
|
+
"org/tool",
|
|
226
|
+
"acme/utils/greeter",
|
|
227
|
+
"my-org/category/sub-category/tool-name",
|
|
228
|
+
"a/b",
|
|
229
|
+
"org_name/tool_name",
|
|
230
|
+
];
|
|
231
|
+
|
|
232
|
+
for (const name of names) {
|
|
233
|
+
const manifest = { name, description: "Test" };
|
|
234
|
+
const result = validateManifest(manifest);
|
|
235
|
+
expect(result.valid).toBe(true);
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
describe("warnings", () => {
|
|
241
|
+
test("warns about missing recommended fields", () => {
|
|
242
|
+
const manifest = {
|
|
243
|
+
name: "org/tool",
|
|
244
|
+
description: "Test",
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
const result = validateManifest(manifest);
|
|
248
|
+
expect(result.valid).toBe(true);
|
|
249
|
+
expect(result.warnings).toBeDefined();
|
|
250
|
+
expect(result.warnings?.length).toBeGreaterThan(0);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
test("warns about missing version", () => {
|
|
254
|
+
const manifest = {
|
|
255
|
+
name: "org/tool",
|
|
256
|
+
description: "Test",
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const result = validateManifest(manifest);
|
|
260
|
+
expect(result.warnings?.some((w) => w.path === "version")).toBe(true);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test("warns about missing license", () => {
|
|
264
|
+
const manifest = {
|
|
265
|
+
name: "org/tool",
|
|
266
|
+
description: "Test",
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const result = validateManifest(manifest);
|
|
270
|
+
expect(result.warnings?.some((w) => w.path === "license")).toBe(true);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test("warns about missing timeout for command tools", () => {
|
|
274
|
+
const manifest = {
|
|
275
|
+
name: "org/tool",
|
|
276
|
+
description: "Test",
|
|
277
|
+
command: "echo hello",
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
const result = validateManifest(manifest);
|
|
281
|
+
expect(result.warnings?.some((w) => w.path === "timeout")).toBe(true);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
test("warns about secret with default value", () => {
|
|
285
|
+
const manifest = {
|
|
286
|
+
name: "org/tool",
|
|
287
|
+
description: "Test",
|
|
288
|
+
env: {
|
|
289
|
+
API_KEY: {
|
|
290
|
+
description: "API key",
|
|
291
|
+
secret: true,
|
|
292
|
+
default: "bad-idea", // Secrets shouldn't have defaults
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const result = validateManifest(manifest);
|
|
298
|
+
expect(result.warnings?.some((w) => w.code === "SECRET_WITH_DEFAULT")).toBe(true);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
test("no extra warnings for complete manifest", () => {
|
|
302
|
+
const manifest = {
|
|
303
|
+
enact: "2.0.0",
|
|
304
|
+
name: "org/tool",
|
|
305
|
+
description: "Test",
|
|
306
|
+
version: "1.0.0",
|
|
307
|
+
license: "MIT",
|
|
308
|
+
outputSchema: { type: "object" },
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
const result = validateManifest(manifest);
|
|
312
|
+
expect(result.valid).toBe(true);
|
|
313
|
+
// May still have some warnings but they should be reasonable
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
describe("validateManifestStrict", () => {
|
|
318
|
+
test("returns manifest on success", () => {
|
|
319
|
+
const manifest = {
|
|
320
|
+
name: "org/tool",
|
|
321
|
+
description: "Test",
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
const result = validateManifestStrict(manifest);
|
|
325
|
+
expect(result.name).toBe("org/tool");
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
test("throws on validation failure", () => {
|
|
329
|
+
const manifest = {
|
|
330
|
+
description: "Missing name",
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
expect(() => validateManifestStrict(manifest)).toThrow("Manifest validation failed");
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
test("error message includes field path", () => {
|
|
337
|
+
const manifest = {
|
|
338
|
+
name: "invalid",
|
|
339
|
+
description: "Test",
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
expect(() => validateManifestStrict(manifest)).toThrow("name");
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
describe("helper functions", () => {
|
|
347
|
+
describe("isValidToolName", () => {
|
|
348
|
+
test("returns true for valid names", () => {
|
|
349
|
+
expect(isValidToolName("org/tool")).toBe(true);
|
|
350
|
+
expect(isValidToolName("acme/utils/greeter")).toBe(true);
|
|
351
|
+
expect(isValidToolName("my-org/my-tool")).toBe(true);
|
|
352
|
+
expect(isValidToolName("org_name/tool_name")).toBe(true);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
test("returns false for invalid names", () => {
|
|
356
|
+
expect(isValidToolName("tool")).toBe(false); // No slash
|
|
357
|
+
expect(isValidToolName("Org/Tool")).toBe(false); // Uppercase
|
|
358
|
+
expect(isValidToolName("org/ tool")).toBe(false); // Space
|
|
359
|
+
expect(isValidToolName("")).toBe(false);
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
describe("isValidVersion", () => {
|
|
364
|
+
test("returns true for valid semver", () => {
|
|
365
|
+
expect(isValidVersion("1.0.0")).toBe(true);
|
|
366
|
+
expect(isValidVersion("0.0.1")).toBe(true);
|
|
367
|
+
expect(isValidVersion("1.0.0-alpha")).toBe(true);
|
|
368
|
+
expect(isValidVersion("1.0.0+build")).toBe(true);
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
test("returns false for invalid semver", () => {
|
|
372
|
+
expect(isValidVersion("1.0")).toBe(false);
|
|
373
|
+
expect(isValidVersion("v1.0.0")).toBe(false); // No 'v' prefix
|
|
374
|
+
expect(isValidVersion("1.0.0.0")).toBe(false);
|
|
375
|
+
expect(isValidVersion("")).toBe(false);
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
describe("isValidTimeout", () => {
|
|
380
|
+
test("returns true for valid Go duration", () => {
|
|
381
|
+
expect(isValidTimeout("30s")).toBe(true);
|
|
382
|
+
expect(isValidTimeout("5m")).toBe(true);
|
|
383
|
+
expect(isValidTimeout("1h")).toBe(true);
|
|
384
|
+
expect(isValidTimeout("100ms")).toBe(true);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
test("returns false for invalid duration", () => {
|
|
388
|
+
expect(isValidTimeout("30seconds")).toBe(false);
|
|
389
|
+
expect(isValidTimeout("5 minutes")).toBe(false);
|
|
390
|
+
expect(isValidTimeout("")).toBe(false);
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
});
|