limits-openclaw 0.0.7 → 0.0.9
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/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/dist/test/integration/mock-saas.test.js +0 -143
- package/dist/test/unit/failmode.test.js +0 -101
- package/dist/test/unit/post.test.js +0 -79
- package/dist/test/unit/pre.test.js +0 -72
- package/dist/test/unit/token.test.js +0 -48
- /package/dist/{src/config.js → config.js} +0 -0
- /package/dist/{src/configure-wizard.js → configure-wizard.js} +0 -0
- /package/dist/{src/enforcer.js → enforcer.js} +0 -0
- /package/dist/{src/index.js → index.js} +0 -0
- /package/dist/{src/logger.js → logger.js} +0 -0
- /package/dist/{src/token.js → token.js} +0 -0
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "limits-openclaw",
|
|
3
3
|
"name": "limits-openclaw",
|
|
4
4
|
"description": "Delegates policy enforcement to the Limits platform before and after every tool call. Optional policy-generator tools for creating/updating policies from natural language.",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.8",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"configSchema": {
|
|
8
8
|
"type": "object",
|
package/package.json
CHANGED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeAll, afterAll } from "vitest";
|
|
2
|
-
import { createServer } from "http";
|
|
3
|
-
/**
|
|
4
|
-
* Integration test: real HTTP server, real enforcer client, full pre+post flow.
|
|
5
|
-
* SaaS returns BLOCK for stripe.* tools, ALLOW for others.
|
|
6
|
-
*/
|
|
7
|
-
describe("mock-saas integration", () => {
|
|
8
|
-
let server;
|
|
9
|
-
let baseUrl;
|
|
10
|
-
let beforeHandler = null;
|
|
11
|
-
let afterHandler = null;
|
|
12
|
-
beforeAll(async () => {
|
|
13
|
-
await new Promise((resolve) => {
|
|
14
|
-
server = createServer((req, res) => {
|
|
15
|
-
if (req.method !== "POST" || req.url !== "/openclaw/enforce") {
|
|
16
|
-
res.writeHead(404);
|
|
17
|
-
res.end();
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
let body = "";
|
|
21
|
-
req.on("data", (ch) => (body += ch));
|
|
22
|
-
req.on("end", () => {
|
|
23
|
-
try {
|
|
24
|
-
const data = JSON.parse(body);
|
|
25
|
-
const name = data.tool?.name ?? "";
|
|
26
|
-
const isStripe = /^stripe\./.test(name) || name.startsWith("stripe_");
|
|
27
|
-
if (data.phase === "pre" || data.phase === "post") {
|
|
28
|
-
if (isStripe) {
|
|
29
|
-
res.writeHead(200, { "Content-Type": "application/json" });
|
|
30
|
-
res.end(JSON.stringify({
|
|
31
|
-
action: "BLOCK",
|
|
32
|
-
reason: "Stripe tools are disabled in this environment",
|
|
33
|
-
}));
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
res.writeHead(200, { "Content-Type": "application/json" });
|
|
37
|
-
res.end(JSON.stringify({ action: "ALLOW" }));
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
res.writeHead(400);
|
|
42
|
-
res.end();
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
catch {
|
|
46
|
-
res.writeHead(400);
|
|
47
|
-
res.end();
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
server.listen(0, "127.0.0.1", () => {
|
|
52
|
-
const addr = server.address();
|
|
53
|
-
const port = typeof addr === "object" && addr && "port" in addr ? addr.port : 0;
|
|
54
|
-
baseUrl = `http://127.0.0.1:${port}`;
|
|
55
|
-
resolve();
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
afterAll(() => {
|
|
60
|
-
return new Promise((resolve) => {
|
|
61
|
-
server.close(() => resolve());
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
it("registers and runs pre-hook: stripe tool blocked, other allowed", async () => {
|
|
65
|
-
const api = {
|
|
66
|
-
config: {
|
|
67
|
-
plugins: {
|
|
68
|
-
entries: {
|
|
69
|
-
"limits-openclaw": {
|
|
70
|
-
enabled: true,
|
|
71
|
-
config: {
|
|
72
|
-
baseUrl: baseUrl,
|
|
73
|
-
failMode: "allow",
|
|
74
|
-
tokenSource: "event.metadata.apiToken",
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
on(event, handler) {
|
|
81
|
-
if (event === "before_tool_call")
|
|
82
|
-
beforeHandler = handler;
|
|
83
|
-
if (event === "after_tool_call")
|
|
84
|
-
afterHandler = handler;
|
|
85
|
-
},
|
|
86
|
-
};
|
|
87
|
-
const { register } = await import("../../src/index.js");
|
|
88
|
-
register(api);
|
|
89
|
-
const eventStripe = {
|
|
90
|
-
toolName: "stripe_charge",
|
|
91
|
-
toolParams: { amount: 100 },
|
|
92
|
-
metadata: { apiToken: "sk_test" },
|
|
93
|
-
};
|
|
94
|
-
const resultBlocked = await beforeHandler(eventStripe, undefined);
|
|
95
|
-
expect(resultBlocked).toEqual({
|
|
96
|
-
block: true,
|
|
97
|
-
reason: "Stripe tools are disabled in this environment",
|
|
98
|
-
});
|
|
99
|
-
const eventSafe = {
|
|
100
|
-
toolName: "read_file",
|
|
101
|
-
toolParams: { path: "/tmp/foo" },
|
|
102
|
-
metadata: { apiToken: "sk_test" },
|
|
103
|
-
};
|
|
104
|
-
const resultAllowed = await beforeHandler(eventSafe, undefined);
|
|
105
|
-
expect(resultAllowed).toBe(null);
|
|
106
|
-
});
|
|
107
|
-
it("post-hook: stripe result blocked, other allowed", async () => {
|
|
108
|
-
const api = {
|
|
109
|
-
config: {
|
|
110
|
-
plugins: {
|
|
111
|
-
entries: {
|
|
112
|
-
"limits-openclaw": {
|
|
113
|
-
enabled: true,
|
|
114
|
-
config: {
|
|
115
|
-
baseUrl: baseUrl,
|
|
116
|
-
failMode: "allow",
|
|
117
|
-
tokenSource: "event.metadata.apiToken",
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
on(event, handler) {
|
|
124
|
-
if (event === "after_tool_call")
|
|
125
|
-
afterHandler = handler;
|
|
126
|
-
},
|
|
127
|
-
};
|
|
128
|
-
const { register } = await import("../../src/index.js");
|
|
129
|
-
register(api);
|
|
130
|
-
const stripeResult = await afterHandler({
|
|
131
|
-
toolName: "stripe_charge",
|
|
132
|
-
metadata: { apiToken: "sk_test" },
|
|
133
|
-
}, { chargeId: "ch_secret" }, undefined);
|
|
134
|
-
expect(stripeResult).toEqual({
|
|
135
|
-
result: "[BLOCKED by policy — content withheld]",
|
|
136
|
-
});
|
|
137
|
-
const safeResult = await afterHandler({
|
|
138
|
-
toolName: "read_file",
|
|
139
|
-
metadata: { apiToken: "sk_test" },
|
|
140
|
-
}, { content: "hello" }, undefined);
|
|
141
|
-
expect(safeResult).toBe(null);
|
|
142
|
-
});
|
|
143
|
-
});
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
-
const callEnforceMock = vi.fn();
|
|
3
|
-
vi.mock("../../src/enforcer.js", () => ({ callEnforce: callEnforceMock }));
|
|
4
|
-
describe("failmode", () => {
|
|
5
|
-
let beforeHandler = null;
|
|
6
|
-
let afterHandler = null;
|
|
7
|
-
function createApi(failMode) {
|
|
8
|
-
return {
|
|
9
|
-
config: {
|
|
10
|
-
plugins: {
|
|
11
|
-
entries: {
|
|
12
|
-
"limits-openclaw": {
|
|
13
|
-
enabled: true,
|
|
14
|
-
config: {
|
|
15
|
-
baseUrl: "https://api.test.com",
|
|
16
|
-
failMode: failMode,
|
|
17
|
-
tokenSource: "event.metadata.apiToken",
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
on(event, handler) {
|
|
24
|
-
if (event === "before_tool_call")
|
|
25
|
-
beforeHandler = handler;
|
|
26
|
-
if (event === "after_tool_call")
|
|
27
|
-
afterHandler = handler;
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
beforeEach(async () => {
|
|
32
|
-
callEnforceMock.mockReset();
|
|
33
|
-
beforeHandler = null;
|
|
34
|
-
afterHandler = null;
|
|
35
|
-
});
|
|
36
|
-
it("SaaS unreachable with failMode allow returns null (pre)", async () => {
|
|
37
|
-
callEnforceMock.mockResolvedValue(null);
|
|
38
|
-
const { register } = await import("../../src/index.js");
|
|
39
|
-
register(createApi("allow"));
|
|
40
|
-
const event = { toolName: "bash", metadata: { apiToken: "sk_ok" } };
|
|
41
|
-
const result = await beforeHandler(event, undefined);
|
|
42
|
-
expect(result).toBe(null);
|
|
43
|
-
});
|
|
44
|
-
it("SaaS unreachable with failMode block returns block (pre)", async () => {
|
|
45
|
-
callEnforceMock.mockResolvedValue(null);
|
|
46
|
-
const { register } = await import("../../src/index.js");
|
|
47
|
-
register(createApi("block"));
|
|
48
|
-
const event = { toolName: "bash", metadata: { apiToken: "sk_ok" } };
|
|
49
|
-
const result = await beforeHandler(event, undefined);
|
|
50
|
-
expect(result).toEqual({
|
|
51
|
-
block: true,
|
|
52
|
-
reason: "enforcement unavailable",
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
it("no baseUrl with failMode block returns block (pre)", async () => {
|
|
56
|
-
const api = {
|
|
57
|
-
config: {
|
|
58
|
-
plugins: {
|
|
59
|
-
entries: {
|
|
60
|
-
"limits-openclaw": {
|
|
61
|
-
enabled: true,
|
|
62
|
-
config: {
|
|
63
|
-
baseUrl: "",
|
|
64
|
-
failMode: "block",
|
|
65
|
-
tokenSource: "event.metadata.apiToken",
|
|
66
|
-
},
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
on(event, handler) {
|
|
72
|
-
if (event === "before_tool_call")
|
|
73
|
-
beforeHandler = handler;
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
const { register } = await import("../../src/index.js");
|
|
77
|
-
register(api);
|
|
78
|
-
const result = await beforeHandler({ toolName: "x" }, undefined);
|
|
79
|
-
expect(result).toEqual({
|
|
80
|
-
block: true,
|
|
81
|
-
reason: "enforcement unavailable",
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
it("SaaS unreachable with failMode block (post) returns blocked result", async () => {
|
|
85
|
-
callEnforceMock.mockResolvedValue(null);
|
|
86
|
-
const { register } = await import("../../src/index.js");
|
|
87
|
-
register(createApi("block"));
|
|
88
|
-
const result = await afterHandler({ toolName: "get", metadata: { apiToken: "sk_ok" } }, { data: "secret" }, undefined);
|
|
89
|
-
expect(result).toEqual({
|
|
90
|
-
result: "[BLOCKED by policy — content withheld]",
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
it("timeout / network error returns null when failMode allow", async () => {
|
|
94
|
-
callEnforceMock.mockRejectedValue(new Error("network error"));
|
|
95
|
-
const { register } = await import("../../src/index.js");
|
|
96
|
-
register(createApi("allow"));
|
|
97
|
-
const event = { toolName: "ping", metadata: { apiToken: "sk_ok" } };
|
|
98
|
-
const result = await beforeHandler(event, undefined);
|
|
99
|
-
expect(result).toBe(null);
|
|
100
|
-
});
|
|
101
|
-
});
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
-
const callEnforceMock = vi.fn();
|
|
3
|
-
vi.mock("../../src/enforcer.js", () => ({ callEnforce: callEnforceMock }));
|
|
4
|
-
describe("postHook", () => {
|
|
5
|
-
let afterHandler = null;
|
|
6
|
-
beforeEach(async () => {
|
|
7
|
-
callEnforceMock.mockReset();
|
|
8
|
-
afterHandler = null;
|
|
9
|
-
const api = {
|
|
10
|
-
config: {
|
|
11
|
-
plugins: {
|
|
12
|
-
entries: {
|
|
13
|
-
"limits-openclaw": {
|
|
14
|
-
enabled: true,
|
|
15
|
-
config: {
|
|
16
|
-
baseUrl: "https://api.test.com",
|
|
17
|
-
failMode: "allow",
|
|
18
|
-
tokenSource: "event.metadata.apiToken",
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
on(event, handler) {
|
|
25
|
-
if (event === "after_tool_call")
|
|
26
|
-
afterHandler = handler;
|
|
27
|
-
},
|
|
28
|
-
};
|
|
29
|
-
const { register } = await import("../../src/index.js");
|
|
30
|
-
register(api);
|
|
31
|
-
});
|
|
32
|
-
async function runPost(event, result, ctx) {
|
|
33
|
-
if (!afterHandler)
|
|
34
|
-
throw new Error("after_tool_call not registered");
|
|
35
|
-
if (result !== undefined && ctx !== undefined)
|
|
36
|
-
return afterHandler(event, result, ctx);
|
|
37
|
-
if (result !== undefined)
|
|
38
|
-
return afterHandler(event, result);
|
|
39
|
-
return afterHandler({ ...event, result: undefined }, undefined);
|
|
40
|
-
}
|
|
41
|
-
it("ALLOW returns null", async () => {
|
|
42
|
-
callEnforceMock.mockResolvedValue({ action: "ALLOW" });
|
|
43
|
-
const event = {
|
|
44
|
-
toolName: "read_file",
|
|
45
|
-
metadata: { apiToken: "sk_ok" },
|
|
46
|
-
};
|
|
47
|
-
const result = await runPost(event, { content: "data" }, undefined);
|
|
48
|
-
expect(result).toBe(null);
|
|
49
|
-
});
|
|
50
|
-
it("BLOCK returns blocked result message", async () => {
|
|
51
|
-
callEnforceMock.mockResolvedValue({
|
|
52
|
-
action: "BLOCK",
|
|
53
|
-
reason: "Sensitive output",
|
|
54
|
-
});
|
|
55
|
-
const event = { toolName: "query_db", metadata: { apiToken: "sk_ok" } };
|
|
56
|
-
const result = await runPost(event, { rows: [] }, undefined);
|
|
57
|
-
expect(result).toEqual({
|
|
58
|
-
result: "[BLOCKED by policy — content withheld]",
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
it("REDACT returns { result: redactedResult }", async () => {
|
|
62
|
-
callEnforceMock.mockResolvedValue({
|
|
63
|
-
action: "REDACT",
|
|
64
|
-
redactedResult: "[REDACTED]",
|
|
65
|
-
});
|
|
66
|
-
const event = { toolName: "get_user", metadata: { apiToken: "sk_ok" } };
|
|
67
|
-
const result = await runPost(event, { email: "a@b.com" }, undefined);
|
|
68
|
-
expect(result).toEqual({ result: "[REDACTED]" });
|
|
69
|
-
});
|
|
70
|
-
it("REWRITE returns { result: rewrittenResult }", async () => {
|
|
71
|
-
callEnforceMock.mockResolvedValue({
|
|
72
|
-
action: "REWRITE",
|
|
73
|
-
rewrittenResult: { summary: "Safe summary" },
|
|
74
|
-
});
|
|
75
|
-
const event = { toolName: "run_report", metadata: { apiToken: "sk_ok" } };
|
|
76
|
-
const result = await runPost(event, { raw: "long..." }, undefined);
|
|
77
|
-
expect(result).toEqual({ result: { summary: "Safe summary" } });
|
|
78
|
-
});
|
|
79
|
-
});
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
-
const callEnforceMock = vi.fn();
|
|
3
|
-
vi.mock("../../src/enforcer.js", () => ({ callEnforce: callEnforceMock }));
|
|
4
|
-
describe("preHook", () => {
|
|
5
|
-
let beforeHandler = null;
|
|
6
|
-
beforeEach(async () => {
|
|
7
|
-
callEnforceMock.mockReset();
|
|
8
|
-
beforeHandler = null;
|
|
9
|
-
const api = {
|
|
10
|
-
config: {
|
|
11
|
-
plugins: {
|
|
12
|
-
entries: {
|
|
13
|
-
"limits-openclaw": {
|
|
14
|
-
enabled: true,
|
|
15
|
-
config: {
|
|
16
|
-
baseUrl: "https://api.test.com",
|
|
17
|
-
failMode: "allow",
|
|
18
|
-
tokenSource: "event.metadata.apiToken",
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
on(event, handler) {
|
|
25
|
-
if (event === "before_tool_call")
|
|
26
|
-
beforeHandler = handler;
|
|
27
|
-
},
|
|
28
|
-
};
|
|
29
|
-
const { register } = await import("../../src/index.js");
|
|
30
|
-
register(api);
|
|
31
|
-
});
|
|
32
|
-
async function runPre(event, ctx) {
|
|
33
|
-
if (!beforeHandler)
|
|
34
|
-
throw new Error("before_tool_call not registered");
|
|
35
|
-
return beforeHandler(event, ctx);
|
|
36
|
-
}
|
|
37
|
-
it("ALLOW returns null", async () => {
|
|
38
|
-
callEnforceMock.mockResolvedValue({ action: "ALLOW" });
|
|
39
|
-
const event = {
|
|
40
|
-
toolName: "read_file",
|
|
41
|
-
toolParams: {},
|
|
42
|
-
metadata: { apiToken: "sk_ok" },
|
|
43
|
-
};
|
|
44
|
-
const result = await runPre(event, undefined);
|
|
45
|
-
expect(result).toBe(null);
|
|
46
|
-
});
|
|
47
|
-
it("BLOCK returns { block: true, reason }", async () => {
|
|
48
|
-
callEnforceMock.mockResolvedValue({
|
|
49
|
-
action: "BLOCK",
|
|
50
|
-
reason: "Policy forbids this tool",
|
|
51
|
-
});
|
|
52
|
-
const event = {
|
|
53
|
-
toolName: "stripe_charge",
|
|
54
|
-
metadata: { apiToken: "sk_ok" },
|
|
55
|
-
};
|
|
56
|
-
const result = await runPre(event, undefined);
|
|
57
|
-
expect(result).toEqual({ block: true, reason: "Policy forbids this tool" });
|
|
58
|
-
});
|
|
59
|
-
it("REWRITE returns { args }", async () => {
|
|
60
|
-
callEnforceMock.mockResolvedValue({
|
|
61
|
-
action: "REWRITE",
|
|
62
|
-
rewriteArgs: { amount: 100, currency: "usd" },
|
|
63
|
-
});
|
|
64
|
-
const event = {
|
|
65
|
-
toolName: "payment",
|
|
66
|
-
toolParams: { amount: 500 },
|
|
67
|
-
metadata: { apiToken: "sk_ok" },
|
|
68
|
-
};
|
|
69
|
-
const result = await runPre(event, undefined);
|
|
70
|
-
expect(result).toEqual({ args: { amount: 100, currency: "usd" } });
|
|
71
|
-
});
|
|
72
|
-
});
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { extractToken } from "../../src/token.js";
|
|
3
|
-
describe("extractToken", () => {
|
|
4
|
-
const origEnv = process.env;
|
|
5
|
-
beforeEach(() => {
|
|
6
|
-
process.env = { ...origEnv };
|
|
7
|
-
});
|
|
8
|
-
afterEach(() => {
|
|
9
|
-
process.env = origEnv;
|
|
10
|
-
});
|
|
11
|
-
it("reads event.metadata.apiToken", () => {
|
|
12
|
-
const event = { metadata: { apiToken: "sk_test_123" } };
|
|
13
|
-
expect(extractToken("event.metadata.apiToken", event, undefined)).toBe("sk_test_123");
|
|
14
|
-
});
|
|
15
|
-
it("reads ctx.auth.token", () => {
|
|
16
|
-
const ctx = { auth: { token: "bearer_abc" } };
|
|
17
|
-
expect(extractToken("ctx.auth.token", ctx, ctx)).toBe("bearer_abc");
|
|
18
|
-
});
|
|
19
|
-
it("reads env.LIMITS_API_TOKEN", () => {
|
|
20
|
-
process.env.LIMITS_API_TOKEN = "env_secret";
|
|
21
|
-
expect(extractToken("env.LIMITS_API_TOKEN", undefined, undefined)).toBe("env_secret");
|
|
22
|
-
});
|
|
23
|
-
it("returns undefined for missing event path", () => {
|
|
24
|
-
const event = {};
|
|
25
|
-
expect(extractToken("event.metadata.apiToken", event, undefined)).toBe(undefined);
|
|
26
|
-
});
|
|
27
|
-
it("returns undefined for missing ctx path", () => {
|
|
28
|
-
const ctx = {};
|
|
29
|
-
expect(extractToken("ctx.auth.token", undefined, ctx)).toBe(undefined);
|
|
30
|
-
});
|
|
31
|
-
it("returns undefined for missing env key", () => {
|
|
32
|
-
expect(extractToken("env.NONEXISTENT_KEY_XYZ", undefined, undefined)).toBe(undefined);
|
|
33
|
-
});
|
|
34
|
-
it("returns undefined for non-string value at path", () => {
|
|
35
|
-
const event = { metadata: { apiToken: 42 } };
|
|
36
|
-
expect(extractToken("event.metadata.apiToken", event, undefined)).toBe(undefined);
|
|
37
|
-
});
|
|
38
|
-
it("returns undefined for malformed source (single segment)", () => {
|
|
39
|
-
expect(extractToken("event", {}, undefined)).toBe(undefined);
|
|
40
|
-
});
|
|
41
|
-
it("returns undefined for empty string", () => {
|
|
42
|
-
expect(extractToken("", {}, undefined)).toBe(undefined);
|
|
43
|
-
});
|
|
44
|
-
it("trims tokenSource", () => {
|
|
45
|
-
const event = { metadata: { apiToken: "trimmed" } };
|
|
46
|
-
expect(extractToken(" event.metadata.apiToken ", event, undefined)).toBe("trimmed");
|
|
47
|
-
});
|
|
48
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|