@elvatis_com/openclaw-cli-bridge-elvatis 0.2.25 → 0.2.26
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/.ai/handoff/STATUS.md +5 -5
- package/README.md +8 -1
- package/SKILL.md +1 -1
- package/index.ts +110 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +4 -1
- package/src/grok-client.ts +428 -0
- package/src/grok-session.ts +195 -0
- package/src/proxy-server.ts +68 -3
- package/test/grok-proxy.test.ts +301 -0
- package/test/grok-session.test.ts +133 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* test/session.test.ts
|
|
3
|
+
*
|
|
4
|
+
* Unit tests for grok-session.ts — persistence, age check, cookie handling.
|
|
5
|
+
* No browser needed (mocked).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
9
|
+
import { existsSync, unlinkSync, readFileSync } from "node:fs";
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import {
|
|
13
|
+
loadSession,
|
|
14
|
+
saveSession,
|
|
15
|
+
isSessionExpiredByAge,
|
|
16
|
+
type GrokSession,
|
|
17
|
+
} from "../src/grok-session.js";
|
|
18
|
+
|
|
19
|
+
const TMP_SESSION = join(tmpdir(), `grok-test-session-${process.pid}.json`);
|
|
20
|
+
|
|
21
|
+
const MOCK_SESSION: GrokSession = {
|
|
22
|
+
cookies: [
|
|
23
|
+
{
|
|
24
|
+
name: "auth_token",
|
|
25
|
+
value: "test-token-123",
|
|
26
|
+
domain: ".grok.com",
|
|
27
|
+
path: "/",
|
|
28
|
+
expires: Date.now() / 1000 + 86400,
|
|
29
|
+
httpOnly: true,
|
|
30
|
+
secure: true,
|
|
31
|
+
sameSite: "Lax",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "ct0",
|
|
35
|
+
value: "csrf-token-abc",
|
|
36
|
+
domain: ".x.com",
|
|
37
|
+
path: "/",
|
|
38
|
+
expires: Date.now() / 1000 + 86400,
|
|
39
|
+
httpOnly: false,
|
|
40
|
+
secure: true,
|
|
41
|
+
sameSite: "Lax",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
savedAt: Date.now(),
|
|
45
|
+
userAgent: "Mozilla/5.0 (test)",
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
describe("grok-session persistence", () => {
|
|
49
|
+
afterEach(() => {
|
|
50
|
+
if (existsSync(TMP_SESSION)) unlinkSync(TMP_SESSION);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("returns null when file does not exist", () => {
|
|
54
|
+
const result = loadSession(TMP_SESSION);
|
|
55
|
+
expect(result).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("saves and loads a session round-trip", () => {
|
|
59
|
+
saveSession(TMP_SESSION, MOCK_SESSION);
|
|
60
|
+
expect(existsSync(TMP_SESSION)).toBe(true);
|
|
61
|
+
|
|
62
|
+
const loaded = loadSession(TMP_SESSION);
|
|
63
|
+
expect(loaded).not.toBeNull();
|
|
64
|
+
expect(loaded!.cookies).toHaveLength(2);
|
|
65
|
+
expect(loaded!.cookies[0].name).toBe("auth_token");
|
|
66
|
+
expect(loaded!.cookies[0].value).toBe("test-token-123");
|
|
67
|
+
expect(loaded!.userAgent).toBe("Mozilla/5.0 (test)");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("returns null for corrupted JSON", () => {
|
|
71
|
+
const { writeFileSync } = require("node:fs");
|
|
72
|
+
writeFileSync(TMP_SESSION, "{ bad json }", "utf-8");
|
|
73
|
+
const result = loadSession(TMP_SESSION);
|
|
74
|
+
expect(result).toBeNull();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("returns null for missing cookies field", () => {
|
|
78
|
+
const { writeFileSync } = require("node:fs");
|
|
79
|
+
writeFileSync(TMP_SESSION, JSON.stringify({ savedAt: Date.now() }), "utf-8");
|
|
80
|
+
const result = loadSession(TMP_SESSION);
|
|
81
|
+
expect(result).toBeNull();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("returns null for cookies field not being array", () => {
|
|
85
|
+
const { writeFileSync } = require("node:fs");
|
|
86
|
+
writeFileSync(TMP_SESSION, JSON.stringify({ cookies: "not-array", savedAt: Date.now() }), "utf-8");
|
|
87
|
+
const result = loadSession(TMP_SESSION);
|
|
88
|
+
expect(result).toBeNull();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("saves valid JSON that can be parsed independently", () => {
|
|
92
|
+
saveSession(TMP_SESSION, MOCK_SESSION);
|
|
93
|
+
const raw = readFileSync(TMP_SESSION, "utf-8");
|
|
94
|
+
expect(() => JSON.parse(raw)).not.toThrow();
|
|
95
|
+
const parsed = JSON.parse(raw);
|
|
96
|
+
expect(parsed.savedAt).toBeTypeOf("number");
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("overwrites existing session file", () => {
|
|
100
|
+
saveSession(TMP_SESSION, MOCK_SESSION);
|
|
101
|
+
|
|
102
|
+
const updated: GrokSession = { ...MOCK_SESSION, userAgent: "updated-ua", savedAt: Date.now() };
|
|
103
|
+
saveSession(TMP_SESSION, updated);
|
|
104
|
+
|
|
105
|
+
const loaded = loadSession(TMP_SESSION);
|
|
106
|
+
expect(loaded!.userAgent).toBe("updated-ua");
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe("session age check", () => {
|
|
111
|
+
it("fresh session is not expired", () => {
|
|
112
|
+
const session: GrokSession = { ...MOCK_SESSION, savedAt: Date.now() };
|
|
113
|
+
expect(isSessionExpiredByAge(session)).toBe(false);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("session saved 6 days ago is not expired", () => {
|
|
117
|
+
const sixDaysAgo = Date.now() - 6 * 24 * 60 * 60 * 1000;
|
|
118
|
+
const session: GrokSession = { ...MOCK_SESSION, savedAt: sixDaysAgo };
|
|
119
|
+
expect(isSessionExpiredByAge(session)).toBe(false);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("session saved 8 days ago is expired", () => {
|
|
123
|
+
const eightDaysAgo = Date.now() - 8 * 24 * 60 * 60 * 1000;
|
|
124
|
+
const session: GrokSession = { ...MOCK_SESSION, savedAt: eightDaysAgo };
|
|
125
|
+
expect(isSessionExpiredByAge(session)).toBe(true);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("session saved exactly 7 days ago is expired", () => {
|
|
129
|
+
const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1000 - 1;
|
|
130
|
+
const session: GrokSession = { ...MOCK_SESSION, savedAt: sevenDaysAgo };
|
|
131
|
+
expect(isSessionExpiredByAge(session)).toBe(true);
|
|
132
|
+
});
|
|
133
|
+
});
|