@chrome-agent-bridge/mcp-server 0.1.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.
Files changed (49) hide show
  1. package/dist/__tests__/data-store.property.test.d.ts +2 -0
  2. package/dist/__tests__/data-store.property.test.d.ts.map +1 -0
  3. package/dist/__tests__/data-store.property.test.js +146 -0
  4. package/dist/__tests__/data-store.property.test.js.map +1 -0
  5. package/dist/__tests__/data-store.test.d.ts +2 -0
  6. package/dist/__tests__/data-store.test.d.ts.map +1 -0
  7. package/dist/__tests__/data-store.test.js +163 -0
  8. package/dist/__tests__/data-store.test.js.map +1 -0
  9. package/dist/__tests__/http-server.property.test.d.ts +2 -0
  10. package/dist/__tests__/http-server.property.test.d.ts.map +1 -0
  11. package/dist/__tests__/http-server.property.test.js +173 -0
  12. package/dist/__tests__/http-server.property.test.js.map +1 -0
  13. package/dist/__tests__/http-server.test.d.ts +2 -0
  14. package/dist/__tests__/http-server.test.d.ts.map +1 -0
  15. package/dist/__tests__/http-server.test.js +180 -0
  16. package/dist/__tests__/http-server.test.js.map +1 -0
  17. package/dist/__tests__/mcp-tools.property.test.d.ts +2 -0
  18. package/dist/__tests__/mcp-tools.property.test.d.ts.map +1 -0
  19. package/dist/__tests__/mcp-tools.property.test.js +189 -0
  20. package/dist/__tests__/mcp-tools.property.test.js.map +1 -0
  21. package/dist/__tests__/mcp-tools.test.d.ts +2 -0
  22. package/dist/__tests__/mcp-tools.test.d.ts.map +1 -0
  23. package/dist/__tests__/mcp-tools.test.js +53 -0
  24. package/dist/__tests__/mcp-tools.test.js.map +1 -0
  25. package/dist/__tests__/validator.test.d.ts +2 -0
  26. package/dist/__tests__/validator.test.d.ts.map +1 -0
  27. package/dist/__tests__/validator.test.js +143 -0
  28. package/dist/__tests__/validator.test.js.map +1 -0
  29. package/dist/data-store.d.ts +20 -0
  30. package/dist/data-store.d.ts.map +1 -0
  31. package/dist/data-store.js +59 -0
  32. package/dist/data-store.js.map +1 -0
  33. package/dist/http-server.d.ts +30 -0
  34. package/dist/http-server.d.ts.map +1 -0
  35. package/dist/http-server.js +164 -0
  36. package/dist/http-server.js.map +1 -0
  37. package/dist/index.d.ts +3 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +39 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/mcp-tools.d.ts +8 -0
  42. package/dist/mcp-tools.d.ts.map +1 -0
  43. package/dist/mcp-tools.js +77 -0
  44. package/dist/mcp-tools.js.map +1 -0
  45. package/dist/validator.d.ts +10 -0
  46. package/dist/validator.d.ts.map +1 -0
  47. package/dist/validator.js +68 -0
  48. package/dist/validator.js.map +1 -0
  49. package/package.json +39 -0
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const vitest_1 = require("vitest");
37
+ const http = __importStar(require("node:http"));
38
+ const http_server_1 = require("../http-server");
39
+ const data_store_1 = require("../data-store");
40
+ function makeValidCaptureBody() {
41
+ return {
42
+ id: '',
43
+ timestamp: Date.now(),
44
+ url: 'https://example.com',
45
+ title: 'Example Page',
46
+ element: {
47
+ tagName: 'div',
48
+ html: '<div>hello</div>',
49
+ text: 'hello',
50
+ classes: ['test'],
51
+ id: null,
52
+ attributes: {},
53
+ domPath: 'body > div',
54
+ },
55
+ styles: {
56
+ computed: { color: 'red' },
57
+ matched: [],
58
+ },
59
+ screenshot: null,
60
+ };
61
+ }
62
+ function request(port, method, path, body) {
63
+ return new Promise((resolve, reject) => {
64
+ const payload = body !== undefined ? JSON.stringify(body) : undefined;
65
+ const req = http.request({
66
+ hostname: '127.0.0.1',
67
+ port,
68
+ path,
69
+ method,
70
+ headers: payload
71
+ ? { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) }
72
+ : undefined,
73
+ }, (res) => {
74
+ const chunks = [];
75
+ res.on('data', (chunk) => chunks.push(chunk));
76
+ res.on('end', () => {
77
+ const raw = Buffer.concat(chunks).toString('utf-8');
78
+ resolve({
79
+ status: res.statusCode,
80
+ headers: res.headers,
81
+ body: raw ? JSON.parse(raw) : null,
82
+ });
83
+ });
84
+ });
85
+ req.on('error', reject);
86
+ if (payload)
87
+ req.write(payload);
88
+ req.end();
89
+ });
90
+ }
91
+ (0, vitest_1.describe)('HttpServer', () => {
92
+ let server;
93
+ let dataStore;
94
+ const TEST_PORT = 0; // Use random available port
95
+ let actualPort;
96
+ (0, vitest_1.beforeEach)(async () => {
97
+ dataStore = new data_store_1.DataStore();
98
+ server = new http_server_1.HttpServer(dataStore);
99
+ // Start on port 0 to get a random available port
100
+ await server.start(0);
101
+ // Get the actual port assigned
102
+ actualPort = server.server.address().port;
103
+ });
104
+ (0, vitest_1.afterEach)(async () => {
105
+ await server.stop();
106
+ });
107
+ (0, vitest_1.it)('GET /ping should return 200 with status ok', async () => {
108
+ const res = await request(actualPort, 'GET', '/ping');
109
+ (0, vitest_1.expect)(res.status).toBe(200);
110
+ (0, vitest_1.expect)(res.body.status).toBe('ok');
111
+ (0, vitest_1.expect)(typeof res.body.timestamp).toBe('number');
112
+ });
113
+ (0, vitest_1.it)('GET /ping should include CORS headers', async () => {
114
+ const res = await request(actualPort, 'GET', '/ping');
115
+ (0, vitest_1.expect)(res.headers['access-control-allow-origin']).toBe('*');
116
+ });
117
+ (0, vitest_1.it)('OPTIONS should return 204 with CORS headers', async () => {
118
+ const res = await request(actualPort, 'OPTIONS', '/capture');
119
+ (0, vitest_1.expect)(res.status).toBe(204);
120
+ (0, vitest_1.expect)(res.headers['access-control-allow-origin']).toBe('*');
121
+ (0, vitest_1.expect)(res.headers['access-control-allow-methods']).toContain('POST');
122
+ });
123
+ (0, vitest_1.it)('POST /capture with valid data should return 200 with id', async () => {
124
+ const res = await request(actualPort, 'POST', '/capture', makeValidCaptureBody());
125
+ (0, vitest_1.expect)(res.status).toBe(200);
126
+ (0, vitest_1.expect)(res.body.success).toBe(true);
127
+ (0, vitest_1.expect)(typeof res.body.id).toBe('string');
128
+ });
129
+ (0, vitest_1.it)('POST /capture should store data in DataStore', async () => {
130
+ const res = await request(actualPort, 'POST', '/capture', makeValidCaptureBody());
131
+ (0, vitest_1.expect)(res.body.success).toBe(true);
132
+ const stored = dataStore.getById(res.body.id);
133
+ (0, vitest_1.expect)(stored).not.toBeNull();
134
+ (0, vitest_1.expect)(stored.url).toBe('https://example.com');
135
+ });
136
+ (0, vitest_1.it)('POST /capture with invalid data should return 400', async () => {
137
+ const res = await request(actualPort, 'POST', '/capture', { bad: 'data' });
138
+ (0, vitest_1.expect)(res.status).toBe(400);
139
+ (0, vitest_1.expect)(res.body.success).toBe(false);
140
+ (0, vitest_1.expect)(typeof res.body.error).toBe('string');
141
+ });
142
+ (0, vitest_1.it)('POST /capture with invalid JSON should return 400', async () => {
143
+ // Send raw invalid JSON
144
+ const res = await new Promise((resolve, reject) => {
145
+ const req = http.request({
146
+ hostname: '127.0.0.1',
147
+ port: actualPort,
148
+ path: '/capture',
149
+ method: 'POST',
150
+ headers: { 'Content-Type': 'application/json' },
151
+ }, (r) => {
152
+ const chunks = [];
153
+ r.on('data', (chunk) => chunks.push(chunk));
154
+ r.on('end', () => {
155
+ const raw = Buffer.concat(chunks).toString('utf-8');
156
+ resolve({ status: r.statusCode, body: JSON.parse(raw) });
157
+ });
158
+ });
159
+ req.on('error', reject);
160
+ req.write('not valid json{{{');
161
+ req.end();
162
+ });
163
+ (0, vitest_1.expect)(res.status).toBe(400);
164
+ (0, vitest_1.expect)(res.body.success).toBe(false);
165
+ (0, vitest_1.expect)(res.body.error).toContain('Invalid JSON');
166
+ });
167
+ (0, vitest_1.it)('POST /capture response should include CORS headers', async () => {
168
+ const res = await request(actualPort, 'POST', '/capture', makeValidCaptureBody());
169
+ (0, vitest_1.expect)(res.headers['access-control-allow-origin']).toBe('*');
170
+ });
171
+ (0, vitest_1.it)('unknown route should return 404', async () => {
172
+ const res = await request(actualPort, 'GET', '/unknown');
173
+ (0, vitest_1.expect)(res.status).toBe(404);
174
+ });
175
+ (0, vitest_1.it)('should bind to localhost (127.0.0.1)', async () => {
176
+ const addr = server.server.address();
177
+ (0, vitest_1.expect)(addr.address).toBe('127.0.0.1');
178
+ });
179
+ });
180
+ //# sourceMappingURL=http-server.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-server.test.js","sourceRoot":"","sources":["../../src/__tests__/http-server.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=mcp-tools.property.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-tools.property.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/mcp-tools.property.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ /**
7
+ * 属性 9: MCP 工具数据一致性
8
+ * Feature: chrome-agent-bridge, Property 9: MCP 工具数据一致性
9
+ *
10
+ * For any DataStore state, data returned by get_selected_element,
11
+ * get_element_screenshot, and get_element_styles MCP tools must match
12
+ * the corresponding records in the DataStore.
13
+ *
14
+ * Validates: Requirements 6.2, 6.3, 6.4
15
+ */
16
+ const vitest_1 = require("vitest");
17
+ const fast_check_1 = __importDefault(require("fast-check"));
18
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
19
+ const data_store_1 = require("../data-store");
20
+ const mcp_tools_1 = require("../mcp-tools");
21
+ // --- Arbitraries ---
22
+ const cssRuleInfoArb = fast_check_1.default.record({
23
+ selector: fast_check_1.default.string({ minLength: 1 }),
24
+ properties: fast_check_1.default.dictionary(fast_check_1.default.string({ minLength: 1 }), fast_check_1.default.string()),
25
+ mediaQuery: fast_check_1.default.option(fast_check_1.default.string({ minLength: 1 }), { nil: null }),
26
+ source: fast_check_1.default.string({ minLength: 1 }),
27
+ });
28
+ const capturedElementDataArb = fast_check_1.default.record({
29
+ id: fast_check_1.default.uuid(),
30
+ timestamp: fast_check_1.default.nat(),
31
+ url: fast_check_1.default.webUrl(),
32
+ title: fast_check_1.default.string({ minLength: 1 }),
33
+ element: fast_check_1.default.record({
34
+ tagName: fast_check_1.default.constantFrom('div', 'span', 'p', 'section', 'article', 'main', 'header', 'footer'),
35
+ html: fast_check_1.default.string({ minLength: 1 }),
36
+ text: fast_check_1.default.string(),
37
+ classes: fast_check_1.default.array(fast_check_1.default.string({ minLength: 1 })),
38
+ id: fast_check_1.default.option(fast_check_1.default.string({ minLength: 1 }), { nil: null }),
39
+ attributes: fast_check_1.default.dictionary(fast_check_1.default.string({ minLength: 1 }), fast_check_1.default.string()),
40
+ domPath: fast_check_1.default.string({ minLength: 1 }),
41
+ }),
42
+ styles: fast_check_1.default.record({
43
+ computed: fast_check_1.default.dictionary(fast_check_1.default.string({ minLength: 1 }), fast_check_1.default.string()),
44
+ matched: fast_check_1.default.array(cssRuleInfoArb),
45
+ }),
46
+ screenshot: fast_check_1.default.option(fast_check_1.default.base64String(), { nil: null }),
47
+ });
48
+ /**
49
+ * Access the internal _registeredTools map on McpServer and invoke a tool handler.
50
+ * Tools with inputSchema are called as handler(args, extra).
51
+ * Tools without inputSchema are called as handler(extra).
52
+ */
53
+ async function callTool(mcpServer, toolName, args = {}) {
54
+ const tools = mcpServer._registeredTools;
55
+ const tool = tools[toolName];
56
+ if (!tool)
57
+ throw new Error(`Tool "${toolName}" not registered`);
58
+ // Provide a minimal extra object (tools don't use it in our implementation)
59
+ const extra = {};
60
+ if (tool.inputSchema) {
61
+ return await tool.handler(args, extra);
62
+ }
63
+ return await tool.handler(extra);
64
+ }
65
+ // --- Tests ---
66
+ (0, vitest_1.describe)('Property 9: MCP tool data consistency', () => {
67
+ /**
68
+ * Requirement 6.2: get_selected_element returns full CapturedElementData
69
+ * matching what is stored in DataStore, both via getLatest and getById.
70
+ */
71
+ (0, vitest_1.it)('get_selected_element returns data consistent with DataStore (by id)', async () => {
72
+ await fast_check_1.default.assert(fast_check_1.default.asyncProperty(capturedElementDataArb, async (data) => {
73
+ const dataStore = new data_store_1.DataStore();
74
+ const mcpServer = new mcp_js_1.McpServer({ name: 'test', version: '0.0.0' });
75
+ (0, mcp_tools_1.registerTools)(mcpServer, dataStore);
76
+ const id = dataStore.store(data);
77
+ const stored = dataStore.getById(id);
78
+ const result = await callTool(mcpServer, 'get_selected_element', { id });
79
+ // First content block is text JSON (without screenshot)
80
+ (0, vitest_1.expect)(result.content[0].type).toBe('text');
81
+ const { screenshot: _s, ...expectedRest } = stored;
82
+ const parsed = JSON.parse(result.content[0].text);
83
+ (0, vitest_1.expect)(parsed).toEqual(expectedRest);
84
+ // If screenshot exists, second block is image
85
+ if (stored.screenshot) {
86
+ (0, vitest_1.expect)(result.content).toHaveLength(2);
87
+ (0, vitest_1.expect)(result.content[1].type).toBe('image');
88
+ (0, vitest_1.expect)(result.content[1].data).toBe(stored.screenshot);
89
+ (0, vitest_1.expect)(result.content[1].mimeType).toBe('image/jpeg');
90
+ }
91
+ else {
92
+ (0, vitest_1.expect)(result.content).toHaveLength(1);
93
+ }
94
+ }), { numRuns: 100 });
95
+ });
96
+ (0, vitest_1.it)('get_selected_element via getLatest matches last stored record', async () => {
97
+ await fast_check_1.default.assert(fast_check_1.default.asyncProperty(fast_check_1.default.array(capturedElementDataArb, { minLength: 1, maxLength: 10 }), async (items) => {
98
+ const dataStore = new data_store_1.DataStore();
99
+ const mcpServer = new mcp_js_1.McpServer({ name: 'test', version: '0.0.0' });
100
+ (0, mcp_tools_1.registerTools)(mcpServer, dataStore);
101
+ let lastId = '';
102
+ for (const item of items) {
103
+ lastId = dataStore.store(item);
104
+ }
105
+ const stored = dataStore.getById(lastId);
106
+ // Call without id → should use getLatest
107
+ const result = await callTool(mcpServer, 'get_selected_element', {});
108
+ const { screenshot: _s, ...expectedRest } = stored;
109
+ const parsed = JSON.parse(result.content[0].text);
110
+ (0, vitest_1.expect)(parsed).toEqual(expectedRest);
111
+ }), { numRuns: 100 });
112
+ });
113
+ /**
114
+ * Requirement 6.3: get_element_screenshot returns screenshot matching DataStore.
115
+ */
116
+ (0, vitest_1.it)('get_element_screenshot returns screenshot consistent with DataStore', async () => {
117
+ await fast_check_1.default.assert(fast_check_1.default.asyncProperty(capturedElementDataArb, async (data) => {
118
+ const dataStore = new data_store_1.DataStore();
119
+ const mcpServer = new mcp_js_1.McpServer({ name: 'test', version: '0.0.0' });
120
+ (0, mcp_tools_1.registerTools)(mcpServer, dataStore);
121
+ const id = dataStore.store(data);
122
+ const stored = dataStore.getById(id);
123
+ const result = await callTool(mcpServer, 'get_element_screenshot', { id });
124
+ (0, vitest_1.expect)(result.content).toHaveLength(1);
125
+ if (stored.screenshot) {
126
+ // Should return image content with matching data
127
+ (0, vitest_1.expect)(result.content[0].type).toBe('image');
128
+ (0, vitest_1.expect)(result.content[0].data).toBe(stored.screenshot);
129
+ (0, vitest_1.expect)(result.content[0].mimeType).toBe('image/jpeg');
130
+ }
131
+ else {
132
+ // No screenshot → text message
133
+ (0, vitest_1.expect)(result.content[0].type).toBe('text');
134
+ (0, vitest_1.expect)(result.content[0].text).toBe('该元素没有截图数据');
135
+ }
136
+ }), { numRuns: 100 });
137
+ });
138
+ /**
139
+ * Requirement 6.4: get_element_styles returns styles matching DataStore.
140
+ */
141
+ (0, vitest_1.it)('get_element_styles returns styles consistent with DataStore', async () => {
142
+ await fast_check_1.default.assert(fast_check_1.default.asyncProperty(capturedElementDataArb, async (data) => {
143
+ const dataStore = new data_store_1.DataStore();
144
+ const mcpServer = new mcp_js_1.McpServer({ name: 'test', version: '0.0.0' });
145
+ (0, mcp_tools_1.registerTools)(mcpServer, dataStore);
146
+ const id = dataStore.store(data);
147
+ const stored = dataStore.getById(id);
148
+ const result = await callTool(mcpServer, 'get_element_styles', { id });
149
+ (0, vitest_1.expect)(result.content).toHaveLength(1);
150
+ (0, vitest_1.expect)(result.content[0].type).toBe('text');
151
+ const parsed = JSON.parse(result.content[0].text);
152
+ (0, vitest_1.expect)(parsed).toEqual(stored.styles);
153
+ }), { numRuns: 100 });
154
+ });
155
+ /**
156
+ * Combined: for any random DataStore state, all tools return consistent data.
157
+ */
158
+ (0, vitest_1.it)('all tools return data consistent with DataStore for random state', async () => {
159
+ await fast_check_1.default.assert(fast_check_1.default.asyncProperty(fast_check_1.default.array(capturedElementDataArb, { minLength: 1, maxLength: 15 }), fast_check_1.default.nat(), async (items, pickIndex) => {
160
+ const dataStore = new data_store_1.DataStore();
161
+ const mcpServer = new mcp_js_1.McpServer({ name: 'test', version: '0.0.0' });
162
+ (0, mcp_tools_1.registerTools)(mcpServer, dataStore);
163
+ const ids = [];
164
+ for (const item of items) {
165
+ ids.push(dataStore.store(item));
166
+ }
167
+ // Pick a random stored element that still exists (capacity ≤ 20)
168
+ const validIds = ids.filter((id) => dataStore.getById(id) !== null);
169
+ const targetId = validIds[pickIndex % validIds.length];
170
+ const stored = dataStore.getById(targetId);
171
+ // get_selected_element (text block excludes screenshot)
172
+ const elemResult = await callTool(mcpServer, 'get_selected_element', { id: targetId });
173
+ const { screenshot: _s, ...expectedRest } = stored;
174
+ (0, vitest_1.expect)(JSON.parse(elemResult.content[0].text)).toEqual(expectedRest);
175
+ // get_element_styles
176
+ const stylesResult = await callTool(mcpServer, 'get_element_styles', { id: targetId });
177
+ (0, vitest_1.expect)(JSON.parse(stylesResult.content[0].text)).toEqual(stored.styles);
178
+ // get_element_screenshot
179
+ const ssResult = await callTool(mcpServer, 'get_element_screenshot', { id: targetId });
180
+ if (stored.screenshot) {
181
+ (0, vitest_1.expect)(ssResult.content[0].data).toBe(stored.screenshot);
182
+ }
183
+ else {
184
+ (0, vitest_1.expect)(ssResult.content[0].text).toBe('该元素没有截图数据');
185
+ }
186
+ }), { numRuns: 100 });
187
+ });
188
+ });
189
+ //# sourceMappingURL=mcp-tools.property.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-tools.property.test.js","sourceRoot":"","sources":["../../src/__tests__/mcp-tools.property.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=mcp-tools.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-tools.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/mcp-tools.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * MCP Tools Unit Tests
5
+ * Validates: Requirements 6.6
6
+ *
7
+ * Tests no-data returns prompt message, non-existent ID returns error message.
8
+ * We test the DataStore behavior that the MCP tools rely on.
9
+ */
10
+ const vitest_1 = require("vitest");
11
+ const data_store_1 = require("../data-store");
12
+ const NO_DATA_MSG = '当前无已采集的元素数据,请先在浏览器中选择元素';
13
+ function notFoundMsg(id) {
14
+ return `未找到 ID 为 ${id} 的元素数据`;
15
+ }
16
+ (0, vitest_1.describe)('MCP Tools - no data scenarios', () => {
17
+ (0, vitest_1.it)('should return null for getLatest when no data (get_selected_element)', () => {
18
+ const store = new data_store_1.DataStore();
19
+ const data = store.getLatest();
20
+ (0, vitest_1.expect)(data).toBeNull();
21
+ // MCP tool would return NO_DATA_MSG
22
+ const message = data ? JSON.stringify(data) : NO_DATA_MSG;
23
+ (0, vitest_1.expect)(message).toBe(NO_DATA_MSG);
24
+ });
25
+ (0, vitest_1.it)('should return null for getById with non-existent ID (get_selected_element)', () => {
26
+ const store = new data_store_1.DataStore();
27
+ const id = 'non-existent-id';
28
+ const data = store.getById(id);
29
+ (0, vitest_1.expect)(data).toBeNull();
30
+ // MCP tool would return notFoundMsg
31
+ const message = data ? JSON.stringify(data) : notFoundMsg(id);
32
+ (0, vitest_1.expect)(message).toBe(notFoundMsg(id));
33
+ });
34
+ (0, vitest_1.it)('should return empty list when no data (list_captured_elements)', () => {
35
+ const store = new data_store_1.DataStore();
36
+ const summaries = store.list();
37
+ (0, vitest_1.expect)(summaries).toEqual([]);
38
+ // MCP tool would return NO_DATA_MSG for empty list
39
+ const message = summaries.length === 0 ? NO_DATA_MSG : JSON.stringify(summaries);
40
+ (0, vitest_1.expect)(message).toBe(NO_DATA_MSG);
41
+ });
42
+ (0, vitest_1.it)('should return null screenshot for non-existent ID (get_element_screenshot)', () => {
43
+ const store = new data_store_1.DataStore();
44
+ const data = store.getById('missing-id');
45
+ (0, vitest_1.expect)(data).toBeNull();
46
+ });
47
+ (0, vitest_1.it)('should return null styles for non-existent ID (get_element_styles)', () => {
48
+ const store = new data_store_1.DataStore();
49
+ const data = store.getById('missing-id');
50
+ (0, vitest_1.expect)(data).toBeNull();
51
+ });
52
+ });
53
+ //# sourceMappingURL=mcp-tools.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-tools.test.js","sourceRoot":"","sources":["../../src/__tests__/mcp-tools.test.ts"],"names":[],"mappings":";;AAAA;;;;;;GAMG;AACH,mCAA8C;AAC9C,8CAA0C;AAE1C,MAAM,WAAW,GAAG,yBAAyB,CAAC;AAE9C,SAAS,WAAW,CAAC,EAAU;IAC7B,OAAO,YAAY,EAAE,QAAQ,CAAC;AAChC,CAAC;AAED,IAAA,iBAAQ,EAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,IAAA,WAAE,EAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,KAAK,GAAG,IAAI,sBAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;QAC/B,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;QACxB,oCAAoC;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;QAC1D,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,4EAA4E,EAAE,GAAG,EAAE;QACpF,MAAM,KAAK,GAAG,IAAI,sBAAS,EAAE,CAAC;QAC9B,MAAM,EAAE,GAAG,iBAAiB,CAAC;QAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC/B,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;QACxB,oCAAoC;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAC9D,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,KAAK,GAAG,IAAI,sBAAS,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC/B,IAAA,eAAM,EAAC,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC9B,mDAAmD;QACnD,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACjF,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,4EAA4E,EAAE,GAAG,EAAE;QACpF,MAAM,KAAK,GAAG,IAAI,sBAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACzC,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,MAAM,KAAK,GAAG,IAAI,sBAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACzC,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/validator.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const validator_1 = require("../validator");
5
+ function makeValidData() {
6
+ return {
7
+ id: 'test-id',
8
+ timestamp: Date.now(),
9
+ url: 'https://example.com',
10
+ title: 'Example',
11
+ element: {
12
+ tagName: 'div',
13
+ html: '<div>hello</div>',
14
+ text: 'hello',
15
+ classes: ['test'],
16
+ id: null,
17
+ attributes: {},
18
+ domPath: 'body > div',
19
+ },
20
+ styles: {
21
+ computed: { color: 'red' },
22
+ matched: [],
23
+ },
24
+ screenshot: null,
25
+ };
26
+ }
27
+ (0, vitest_1.describe)('validateCapturedElementData', () => {
28
+ (0, vitest_1.it)('should accept valid data', () => {
29
+ const result = (0, validator_1.validateCapturedElementData)(makeValidData());
30
+ (0, vitest_1.expect)(result.valid).toBe(true);
31
+ (0, vitest_1.expect)(result.errors).toHaveLength(0);
32
+ });
33
+ (0, vitest_1.it)('should reject null', () => {
34
+ const result = (0, validator_1.validateCapturedElementData)(null);
35
+ (0, vitest_1.expect)(result.valid).toBe(false);
36
+ (0, vitest_1.expect)(result.errors).toContain('Data must be a non-null object');
37
+ });
38
+ (0, vitest_1.it)('should reject non-object types', () => {
39
+ (0, vitest_1.expect)((0, validator_1.validateCapturedElementData)('string').valid).toBe(false);
40
+ (0, vitest_1.expect)((0, validator_1.validateCapturedElementData)(42).valid).toBe(false);
41
+ (0, vitest_1.expect)((0, validator_1.validateCapturedElementData)(true).valid).toBe(false);
42
+ (0, vitest_1.expect)((0, validator_1.validateCapturedElementData)(undefined).valid).toBe(false);
43
+ });
44
+ (0, vitest_1.it)('should reject arrays', () => {
45
+ const result = (0, validator_1.validateCapturedElementData)([]);
46
+ (0, vitest_1.expect)(result.valid).toBe(false);
47
+ });
48
+ (0, vitest_1.it)('should reject missing url', () => {
49
+ const data = makeValidData();
50
+ delete data.url;
51
+ const result = (0, validator_1.validateCapturedElementData)(data);
52
+ (0, vitest_1.expect)(result.valid).toBe(false);
53
+ (0, vitest_1.expect)(result.errors.some(e => e.includes('url'))).toBe(true);
54
+ });
55
+ (0, vitest_1.it)('should reject missing title', () => {
56
+ const data = makeValidData();
57
+ delete data.title;
58
+ const result = (0, validator_1.validateCapturedElementData)(data);
59
+ (0, vitest_1.expect)(result.valid).toBe(false);
60
+ (0, vitest_1.expect)(result.errors.some(e => e.includes('title'))).toBe(true);
61
+ });
62
+ (0, vitest_1.it)('should reject missing element', () => {
63
+ const data = makeValidData();
64
+ delete data.element;
65
+ const result = (0, validator_1.validateCapturedElementData)(data);
66
+ (0, vitest_1.expect)(result.valid).toBe(false);
67
+ (0, vitest_1.expect)(result.errors.some(e => e.includes('element'))).toBe(true);
68
+ });
69
+ (0, vitest_1.it)('should reject invalid element.tagName', () => {
70
+ const data = makeValidData();
71
+ data.element.tagName = 123;
72
+ const result = (0, validator_1.validateCapturedElementData)(data);
73
+ (0, vitest_1.expect)(result.valid).toBe(false);
74
+ (0, vitest_1.expect)(result.errors.some(e => e.includes('element.tagName'))).toBe(true);
75
+ });
76
+ (0, vitest_1.it)('should reject invalid element.classes (not array)', () => {
77
+ const data = makeValidData();
78
+ data.element.classes = 'not-array';
79
+ const result = (0, validator_1.validateCapturedElementData)(data);
80
+ (0, vitest_1.expect)(result.valid).toBe(false);
81
+ (0, vitest_1.expect)(result.errors.some(e => e.includes('element.classes'))).toBe(true);
82
+ });
83
+ (0, vitest_1.it)('should reject element.classes with non-string items', () => {
84
+ const data = makeValidData();
85
+ data.element.classes = [1, 2];
86
+ const result = (0, validator_1.validateCapturedElementData)(data);
87
+ (0, vitest_1.expect)(result.valid).toBe(false);
88
+ (0, vitest_1.expect)(result.errors.some(e => e.includes('element.classes'))).toBe(true);
89
+ });
90
+ (0, vitest_1.it)('should reject missing styles', () => {
91
+ const data = makeValidData();
92
+ delete data.styles;
93
+ const result = (0, validator_1.validateCapturedElementData)(data);
94
+ (0, vitest_1.expect)(result.valid).toBe(false);
95
+ (0, vitest_1.expect)(result.errors.some(e => e.includes('styles'))).toBe(true);
96
+ });
97
+ (0, vitest_1.it)('should reject invalid styles.computed', () => {
98
+ const data = makeValidData();
99
+ data.styles.computed = 'not-object';
100
+ const result = (0, validator_1.validateCapturedElementData)(data);
101
+ (0, vitest_1.expect)(result.valid).toBe(false);
102
+ (0, vitest_1.expect)(result.errors.some(e => e.includes('styles.computed'))).toBe(true);
103
+ });
104
+ (0, vitest_1.it)('should reject invalid styles.matched (not array)', () => {
105
+ const data = makeValidData();
106
+ data.styles.matched = 'not-array';
107
+ const result = (0, validator_1.validateCapturedElementData)(data);
108
+ (0, vitest_1.expect)(result.valid).toBe(false);
109
+ (0, vitest_1.expect)(result.errors.some(e => e.includes('styles.matched'))).toBe(true);
110
+ });
111
+ (0, vitest_1.it)('should accept screenshot as string', () => {
112
+ const data = makeValidData();
113
+ data.screenshot = 'data:image/png;base64,abc';
114
+ const result = (0, validator_1.validateCapturedElementData)(data);
115
+ (0, vitest_1.expect)(result.valid).toBe(true);
116
+ });
117
+ (0, vitest_1.it)('should reject screenshot as number', () => {
118
+ const data = makeValidData();
119
+ data.screenshot = 123;
120
+ const result = (0, validator_1.validateCapturedElementData)(data);
121
+ (0, vitest_1.expect)(result.valid).toBe(false);
122
+ (0, vitest_1.expect)(result.errors.some(e => e.includes('screenshot'))).toBe(true);
123
+ });
124
+ (0, vitest_1.it)('should accept element.id as string', () => {
125
+ const data = makeValidData();
126
+ data.element.id = 'my-id';
127
+ const result = (0, validator_1.validateCapturedElementData)(data);
128
+ (0, vitest_1.expect)(result.valid).toBe(true);
129
+ });
130
+ (0, vitest_1.it)('should reject element.id as number', () => {
131
+ const data = makeValidData();
132
+ data.element.id = 42;
133
+ const result = (0, validator_1.validateCapturedElementData)(data);
134
+ (0, vitest_1.expect)(result.valid).toBe(false);
135
+ (0, vitest_1.expect)(result.errors.some(e => e.includes('element.id'))).toBe(true);
136
+ });
137
+ (0, vitest_1.it)('should collect multiple errors', () => {
138
+ const result = (0, validator_1.validateCapturedElementData)({});
139
+ (0, vitest_1.expect)(result.valid).toBe(false);
140
+ (0, vitest_1.expect)(result.errors.length).toBeGreaterThan(1);
141
+ });
142
+ });
143
+ //# sourceMappingURL=validator.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.test.js","sourceRoot":"","sources":["../../src/__tests__/validator.test.ts"],"names":[],"mappings":"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"}