@nahisaho/yata-ui 1.7.0 → 1.7.5
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/package.json
CHANGED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* YATA UI Integration Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests the UI Server and data transformation integration
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
* @see REQ-YI-WEB-001 - Web-based Visualization
|
|
8
|
+
* @see REQ-YI-WEB-002 - Interactive Graph Editing
|
|
9
|
+
* @see REQ-YI-WEB-003 - Real-time Updates
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
13
|
+
import { YataUIServer, createYataUIServer, DEFAULT_UI_CONFIG } from '../index.js';
|
|
14
|
+
import type { GraphData, GraphNode, GraphEdge } from '../index.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Mock YataLocal-like data source for testing
|
|
18
|
+
*/
|
|
19
|
+
class MockYataLocal {
|
|
20
|
+
private entities: Array<{ id: string; type: string; name: string; namespace: string }> = [];
|
|
21
|
+
private relationships: Array<{ id: string; sourceId: string; targetId: string; type: string }> = [];
|
|
22
|
+
|
|
23
|
+
async addEntity(entity: { type: string; name: string; namespace: string }) {
|
|
24
|
+
const id = `E-${this.entities.length + 1}`;
|
|
25
|
+
this.entities.push({ id, ...entity });
|
|
26
|
+
return { id };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async addRelationship(rel: { sourceId: string; targetId: string; type: string }) {
|
|
30
|
+
const id = `R-${this.relationships.length + 1}`;
|
|
31
|
+
this.relationships.push({ id, ...rel });
|
|
32
|
+
return { id };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async getAllEntities() {
|
|
36
|
+
return this.entities;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async getAllRelationships() {
|
|
40
|
+
return this.relationships;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
toGraphData(): GraphData {
|
|
44
|
+
return {
|
|
45
|
+
nodes: this.entities.map(e => ({
|
|
46
|
+
id: e.id,
|
|
47
|
+
label: e.name,
|
|
48
|
+
type: e.type,
|
|
49
|
+
namespace: e.namespace,
|
|
50
|
+
})),
|
|
51
|
+
edges: this.relationships.map(r => ({
|
|
52
|
+
id: r.id,
|
|
53
|
+
source: r.sourceId,
|
|
54
|
+
target: r.targetId,
|
|
55
|
+
type: r.type,
|
|
56
|
+
})),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
describe('YATA UI Integration', () => {
|
|
62
|
+
let server: YataUIServer;
|
|
63
|
+
let mockYata: MockYataLocal;
|
|
64
|
+
|
|
65
|
+
beforeEach(async () => {
|
|
66
|
+
mockYata = new MockYataLocal();
|
|
67
|
+
|
|
68
|
+
// Seed test data
|
|
69
|
+
const user = await mockYata.addEntity({
|
|
70
|
+
type: 'class',
|
|
71
|
+
name: 'User',
|
|
72
|
+
namespace: 'domain.entities',
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const userRepo = await mockYata.addEntity({
|
|
76
|
+
type: 'interface',
|
|
77
|
+
name: 'UserRepository',
|
|
78
|
+
namespace: 'domain.repositories',
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const userService = await mockYata.addEntity({
|
|
82
|
+
type: 'class',
|
|
83
|
+
name: 'UserService',
|
|
84
|
+
namespace: 'application.services',
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
await mockYata.addRelationship({
|
|
88
|
+
sourceId: userService.id,
|
|
89
|
+
targetId: userRepo.id,
|
|
90
|
+
type: 'depends_on',
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
await mockYata.addRelationship({
|
|
94
|
+
sourceId: userRepo.id,
|
|
95
|
+
targetId: user.id,
|
|
96
|
+
type: 'manages',
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Create server
|
|
100
|
+
server = new YataUIServer({
|
|
101
|
+
port: 0, // Random port
|
|
102
|
+
enableRealtime: true,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
server.setDataProvider(async () => mockYata.toGraphData());
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
afterEach(async () => {
|
|
109
|
+
if (server.isRunning()) {
|
|
110
|
+
await server.stop();
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe('Server Lifecycle', () => {
|
|
115
|
+
it('should start and stop server', async () => {
|
|
116
|
+
expect(server.isRunning()).toBe(false);
|
|
117
|
+
|
|
118
|
+
await server.start();
|
|
119
|
+
expect(server.isRunning()).toBe(true);
|
|
120
|
+
|
|
121
|
+
await server.stop();
|
|
122
|
+
expect(server.isRunning()).toBe(false);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should return URL', () => {
|
|
126
|
+
const url = server.getUrl();
|
|
127
|
+
expect(url).toMatch(/^http:\/\/localhost:\d+$/);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe('Data Provider Integration', () => {
|
|
132
|
+
it('should accept data provider function', () => {
|
|
133
|
+
const mockProvider = async (): Promise<GraphData> => ({
|
|
134
|
+
nodes: [{ id: '1', label: 'Test', type: 'entity' }],
|
|
135
|
+
edges: [],
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Should not throw
|
|
139
|
+
server.setDataProvider(mockProvider);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should update data provider dynamically', async () => {
|
|
143
|
+
// Add more entities
|
|
144
|
+
await mockYata.addEntity({
|
|
145
|
+
type: 'class',
|
|
146
|
+
name: 'Order',
|
|
147
|
+
namespace: 'domain.entities',
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const graphData = mockYata.toGraphData();
|
|
151
|
+
expect(graphData.nodes.length).toBe(4);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
describe('Real-time Updates', () => {
|
|
156
|
+
it('should broadcast updates to connected clients', () => {
|
|
157
|
+
// Broadcast an update - should not throw
|
|
158
|
+
server.broadcastUpdate('entity:created', {
|
|
159
|
+
id: 'E-NEW',
|
|
160
|
+
type: 'class',
|
|
161
|
+
name: 'NewEntity',
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
expect(true).toBe(true);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('should broadcast to namespaced clients', () => {
|
|
168
|
+
server.broadcastUpdate('entity:updated', {
|
|
169
|
+
id: 'E-1',
|
|
170
|
+
changes: { name: 'UpdatedUser' },
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Verify no error thrown
|
|
174
|
+
expect(server.isRunning()).toBe(false); // Not started yet
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe('YataUIServer Factory', () => {
|
|
180
|
+
it('should create server with factory function', () => {
|
|
181
|
+
const server = createYataUIServer({ port: 0 });
|
|
182
|
+
expect(server).toBeInstanceOf(YataUIServer);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('should apply default configuration', () => {
|
|
186
|
+
expect(DEFAULT_UI_CONFIG.port).toBe(3000);
|
|
187
|
+
expect(DEFAULT_UI_CONFIG.host).toBe('localhost');
|
|
188
|
+
expect(DEFAULT_UI_CONFIG.cors).toBe(true);
|
|
189
|
+
expect(DEFAULT_UI_CONFIG.enableRealtime).toBe(true);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
describe('GraphData Transformation', () => {
|
|
194
|
+
it('should transform entities to nodes correctly', async () => {
|
|
195
|
+
const mockYata = new MockYataLocal();
|
|
196
|
+
await mockYata.addEntity({ type: 'class', name: 'Test', namespace: 'ns' });
|
|
197
|
+
|
|
198
|
+
const graphData = mockYata.toGraphData();
|
|
199
|
+
|
|
200
|
+
expect(graphData.nodes[0]).toMatchObject({
|
|
201
|
+
label: 'Test',
|
|
202
|
+
type: 'class',
|
|
203
|
+
namespace: 'ns',
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('should transform relationships to edges correctly', async () => {
|
|
208
|
+
const mockYata = new MockYataLocal();
|
|
209
|
+
const e1 = await mockYata.addEntity({ type: 'class', name: 'A', namespace: 'ns' });
|
|
210
|
+
const e2 = await mockYata.addEntity({ type: 'class', name: 'B', namespace: 'ns' });
|
|
211
|
+
await mockYata.addRelationship({
|
|
212
|
+
sourceId: e1.id,
|
|
213
|
+
targetId: e2.id,
|
|
214
|
+
type: 'uses',
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
const graphData = mockYata.toGraphData();
|
|
218
|
+
|
|
219
|
+
expect(graphData.edges[0]).toMatchObject({
|
|
220
|
+
source: e1.id,
|
|
221
|
+
target: e2.id,
|
|
222
|
+
type: 'uses',
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('should handle empty data', () => {
|
|
227
|
+
const mockYata = new MockYataLocal();
|
|
228
|
+
const graphData = mockYata.toGraphData();
|
|
229
|
+
|
|
230
|
+
expect(graphData.nodes).toEqual([]);
|
|
231
|
+
expect(graphData.edges).toEqual([]);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('should handle multiple nodes and edges', async () => {
|
|
235
|
+
const mockYata = new MockYataLocal();
|
|
236
|
+
|
|
237
|
+
// Add multiple entities
|
|
238
|
+
for (let i = 0; i < 5; i++) {
|
|
239
|
+
await mockYata.addEntity({ type: 'class', name: `Class${i}`, namespace: 'ns' });
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const graphData = mockYata.toGraphData();
|
|
243
|
+
expect(graphData.nodes.length).toBe(5);
|
|
244
|
+
});
|
|
245
|
+
});
|