cyclecad 3.2.0 → 3.4.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/DOCKER-SETUP-VERIFICATION.md +399 -0
- package/DOCKER-TESTING.md +463 -0
- package/FUSION360_MODULES.md +478 -0
- package/FUSION_MODULES_README.md +352 -0
- package/INTEGRATION_SNIPPETS.md +608 -0
- package/KILLER-FEATURES-DELIVERY.md +469 -0
- package/MODULES_SUMMARY.txt +337 -0
- package/QUICK_REFERENCE.txt +298 -0
- package/README-DOCKER-TESTING.txt +438 -0
- package/app/index.html +23 -10
- package/app/js/fusion-help.json +1808 -0
- package/app/js/help-module-v3.js +1096 -0
- package/app/js/killer-features-help.json +395 -0
- package/app/js/killer-features.js +1508 -0
- package/app/js/modules/fusion-assembly.js +842 -0
- package/app/js/modules/fusion-cam.js +785 -0
- package/app/js/modules/fusion-data.js +814 -0
- package/app/js/modules/fusion-drawing.js +844 -0
- package/app/js/modules/fusion-inspection.js +756 -0
- package/app/js/modules/fusion-render.js +774 -0
- package/app/js/modules/fusion-simulation.js +986 -0
- package/app/js/modules/fusion-sketch.js +1044 -0
- package/app/js/modules/fusion-solid.js +1095 -0
- package/app/js/modules/fusion-surface.js +949 -0
- package/app/tests/FUSION_TEST_SUITE.md +266 -0
- package/app/tests/README.md +77 -0
- package/app/tests/TESTING-CHECKLIST.md +177 -0
- package/app/tests/TEST_SUITE_SUMMARY.txt +236 -0
- package/app/tests/brep-live-test.html +848 -0
- package/app/tests/docker-integration-test.html +811 -0
- package/app/tests/fusion-all-tests.html +670 -0
- package/app/tests/fusion-assembly-tests.html +461 -0
- package/app/tests/fusion-cam-tests.html +421 -0
- package/app/tests/fusion-simulation-tests.html +421 -0
- package/app/tests/fusion-sketch-tests.html +613 -0
- package/app/tests/fusion-solid-tests.html +529 -0
- package/app/tests/index.html +453 -0
- package/app/tests/killer-features-test.html +509 -0
- package/app/tests/run-tests.html +874 -0
- package/app/tests/step-import-live-test.html +1115 -0
- package/app/tests/test-agent-v3.html +93 -696
- package/architecture-dashboard.html +1970 -0
- package/docs/API-REFERENCE.md +1423 -0
- package/docs/BREP-LIVE-TEST-GUIDE.md +453 -0
- package/docs/DEVELOPER-GUIDE-v3.md +795 -0
- package/docs/DOCKER-QUICK-TEST.md +376 -0
- package/docs/FUSION-FEATURES-GUIDE.md +2513 -0
- package/docs/FUSION-TUTORIAL.md +1203 -0
- package/docs/INFRASTRUCTURE-GUIDE-INDEX.md +327 -0
- package/docs/KEYBOARD-SHORTCUTS.md +402 -0
- package/docs/KILLER-FEATURES-INTEGRATION.md +412 -0
- package/docs/KILLER-FEATURES-SUMMARY.md +424 -0
- package/docs/KILLER-FEATURES-TUTORIAL.md +784 -0
- package/docs/KILLER-FEATURES.md +562 -0
- package/docs/QUICK-REFERENCE.md +282 -0
- package/docs/README-v3-DOCS.md +274 -0
- package/docs/TUTORIAL-v3.md +1190 -0
- package/docs/architecture-dashboard.html +1970 -0
- package/docs/architecture-v3.html +1038 -0
- package/linkedin-post-v3.md +58 -0
- package/package.json +1 -1
- package/scripts/dev-setup.sh +338 -0
- package/scripts/docker-health-check.sh +159 -0
- package/scripts/integration-test.sh +311 -0
- package/scripts/test-docker.sh +515 -0
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Killer Features Test Agent — cycleCAD</title>
|
|
7
|
+
<style>
|
|
8
|
+
* {
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
body {
|
|
15
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
16
|
+
background: #0d1117;
|
|
17
|
+
color: #c9d1d9;
|
|
18
|
+
height: 100vh;
|
|
19
|
+
display: flex;
|
|
20
|
+
overflow: hidden;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.container {
|
|
24
|
+
display: flex;
|
|
25
|
+
width: 100%;
|
|
26
|
+
height: 100%;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.app-frame {
|
|
30
|
+
flex: 1;
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
border-right: 1px solid #30363d;
|
|
34
|
+
overflow: hidden;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.app-header {
|
|
38
|
+
padding: 12px 16px;
|
|
39
|
+
background: #161b22;
|
|
40
|
+
border-bottom: 1px solid #30363d;
|
|
41
|
+
display: flex;
|
|
42
|
+
justify-content: space-between;
|
|
43
|
+
align-items: center;
|
|
44
|
+
font-size: 14px;
|
|
45
|
+
font-weight: 600;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
iframe {
|
|
49
|
+
flex: 1;
|
|
50
|
+
border: none;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.test-panel {
|
|
54
|
+
width: 380px;
|
|
55
|
+
display: flex;
|
|
56
|
+
flex-direction: column;
|
|
57
|
+
background: #0d1117;
|
|
58
|
+
border-left: 1px solid #30363d;
|
|
59
|
+
overflow: hidden;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.test-header {
|
|
63
|
+
padding: 16px;
|
|
64
|
+
background: #161b22;
|
|
65
|
+
border-bottom: 1px solid #30363d;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.test-header h2 {
|
|
69
|
+
font-size: 16px;
|
|
70
|
+
margin-bottom: 12px;
|
|
71
|
+
color: #f0883e;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.test-controls {
|
|
75
|
+
display: flex;
|
|
76
|
+
gap: 8px;
|
|
77
|
+
margin-bottom: 12px;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.btn {
|
|
81
|
+
flex: 1;
|
|
82
|
+
padding: 6px 12px;
|
|
83
|
+
background: #238636;
|
|
84
|
+
border: none;
|
|
85
|
+
color: #fff;
|
|
86
|
+
border-radius: 4px;
|
|
87
|
+
cursor: pointer;
|
|
88
|
+
font-size: 12px;
|
|
89
|
+
font-weight: 600;
|
|
90
|
+
transition: background 0.2s;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.btn:hover {
|
|
94
|
+
background: #2ea043;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.btn.secondary {
|
|
98
|
+
background: #1f6feb;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.btn.secondary:hover {
|
|
102
|
+
background: #388bfd;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.test-log {
|
|
106
|
+
flex: 1;
|
|
107
|
+
overflow-y: auto;
|
|
108
|
+
padding: 12px;
|
|
109
|
+
font-family: 'Monaco', 'Courier New', monospace;
|
|
110
|
+
font-size: 11px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.test-item {
|
|
114
|
+
margin-bottom: 8px;
|
|
115
|
+
padding: 6px 8px;
|
|
116
|
+
background: #161b22;
|
|
117
|
+
border-radius: 3px;
|
|
118
|
+
border-left: 3px solid #666;
|
|
119
|
+
line-height: 1.4;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.test-item.pass {
|
|
123
|
+
border-left-color: #238636;
|
|
124
|
+
background: rgba(35, 134, 54, 0.1);
|
|
125
|
+
color: #3fb950;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.test-item.fail {
|
|
129
|
+
border-left-color: #da3633;
|
|
130
|
+
background: rgba(218, 54, 51, 0.1);
|
|
131
|
+
color: #f85149;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.test-item.skip {
|
|
135
|
+
border-left-color: #6e40aa;
|
|
136
|
+
background: rgba(110, 64, 170, 0.1);
|
|
137
|
+
color: #d2a8ff;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.test-item.running {
|
|
141
|
+
border-left-color: #d29922;
|
|
142
|
+
background: rgba(210, 153, 34, 0.1);
|
|
143
|
+
color: #d29922;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.progress-bar {
|
|
147
|
+
height: 4px;
|
|
148
|
+
background: #30363d;
|
|
149
|
+
border-radius: 2px;
|
|
150
|
+
overflow: hidden;
|
|
151
|
+
margin-top: 8px;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.progress-fill {
|
|
155
|
+
height: 100%;
|
|
156
|
+
background: #238636;
|
|
157
|
+
width: 0%;
|
|
158
|
+
transition: width 0.3s;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.stats {
|
|
162
|
+
padding: 12px;
|
|
163
|
+
border-top: 1px solid #30363d;
|
|
164
|
+
font-size: 12px;
|
|
165
|
+
display: grid;
|
|
166
|
+
grid-template-columns: 1fr 1fr;
|
|
167
|
+
gap: 8px;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.stat {
|
|
171
|
+
background: #161b22;
|
|
172
|
+
padding: 6px 8px;
|
|
173
|
+
border-radius: 3px;
|
|
174
|
+
text-align: center;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.stat-value {
|
|
178
|
+
font-size: 16px;
|
|
179
|
+
font-weight: 600;
|
|
180
|
+
color: #58a6ff;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.stat-label {
|
|
184
|
+
font-size: 10px;
|
|
185
|
+
color: #8b949e;
|
|
186
|
+
margin-top: 2px;
|
|
187
|
+
}
|
|
188
|
+
</style>
|
|
189
|
+
</head>
|
|
190
|
+
<body>
|
|
191
|
+
<div class="container">
|
|
192
|
+
<div class="app-frame">
|
|
193
|
+
<div class="app-header">
|
|
194
|
+
<div>Killer Features Test Agent</div>
|
|
195
|
+
<div id="app-status">Ready</div>
|
|
196
|
+
</div>
|
|
197
|
+
<iframe id="app-iframe" src="../index.html"></iframe>
|
|
198
|
+
</div>
|
|
199
|
+
|
|
200
|
+
<div class="test-panel">
|
|
201
|
+
<div class="test-header">
|
|
202
|
+
<h2>Test Suite</h2>
|
|
203
|
+
<div class="test-controls">
|
|
204
|
+
<button class="btn" id="btn-run-all">Run All</button>
|
|
205
|
+
<button class="btn secondary" id="btn-run-killer">Killer Features</button>
|
|
206
|
+
</div>
|
|
207
|
+
<div class="progress-bar">
|
|
208
|
+
<div class="progress-fill" id="progress-fill"></div>
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
|
|
212
|
+
<div class="test-log" id="test-log"></div>
|
|
213
|
+
|
|
214
|
+
<div class="stats">
|
|
215
|
+
<div class="stat">
|
|
216
|
+
<div class="stat-value" id="stat-pass">0</div>
|
|
217
|
+
<div class="stat-label">Passed</div>
|
|
218
|
+
</div>
|
|
219
|
+
<div class="stat">
|
|
220
|
+
<div class="stat-value" id="stat-fail">0</div>
|
|
221
|
+
<div class="stat-label">Failed</div>
|
|
222
|
+
</div>
|
|
223
|
+
<div class="stat">
|
|
224
|
+
<div class="stat-value" id="stat-skip">0</div>
|
|
225
|
+
<div class="stat-label">Skipped</div>
|
|
226
|
+
</div>
|
|
227
|
+
<div class="stat">
|
|
228
|
+
<div class="stat-value" id="stat-total">0</div>
|
|
229
|
+
<div class="stat-label">Total</div>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
</div>
|
|
233
|
+
</div>
|
|
234
|
+
|
|
235
|
+
<script>
|
|
236
|
+
const TestAgent = {
|
|
237
|
+
iframe: null,
|
|
238
|
+
testLog: document.getElementById('test-log'),
|
|
239
|
+
stats: { pass: 0, fail: 0, skip: 0, total: 0 },
|
|
240
|
+
currentTest: 0,
|
|
241
|
+
totalTests: 0,
|
|
242
|
+
|
|
243
|
+
async init() {
|
|
244
|
+
this.iframe = document.getElementById('app-iframe');
|
|
245
|
+
this.iframe.addEventListener('load', () => {
|
|
246
|
+
document.getElementById('app-status').textContent = 'Ready';
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
document.getElementById('btn-run-all').addEventListener('click', () => this.runAll());
|
|
250
|
+
document.getElementById('btn-run-killer').addEventListener('click', () => this.runKillerFeatures());
|
|
251
|
+
},
|
|
252
|
+
|
|
253
|
+
async runKillerFeatures() {
|
|
254
|
+
this.stats = { pass: 0, fail: 0, skip: 0, total: 0 };
|
|
255
|
+
this.testLog.innerHTML = '';
|
|
256
|
+
|
|
257
|
+
const tests = [
|
|
258
|
+
{ name: 'AI Copilot - Show Panel', fn: () => this.testAICopilot() },
|
|
259
|
+
{ name: 'AI Copilot - Parse Intent (Gear)', fn: () => this.testGearIntent() },
|
|
260
|
+
{ name: 'AI Copilot - Parse Intent (Bracket)', fn: () => this.testBracketIntent() },
|
|
261
|
+
{ name: 'Physics - Toggle Simulation', fn: () => this.testPhysics() },
|
|
262
|
+
{ name: 'Physics - Gravity Application', fn: () => this.testPhysicsGravity() },
|
|
263
|
+
{ name: 'Generative Design - Show Panel', fn: () => this.testGenerative() },
|
|
264
|
+
{ name: 'Generative Design - Generate Topology', fn: () => this.testGenerativeTopology() },
|
|
265
|
+
{ name: 'Cost Estimator - Show Panel', fn: () => this.testCostEstimator() },
|
|
266
|
+
{ name: 'Cost Estimator - Calculate Costs', fn: () => this.testCostCalculation() },
|
|
267
|
+
{ name: 'Smart Snap - Detect Patterns', fn: () => this.testSmartSnap() },
|
|
268
|
+
{ name: 'Smart Snap - Bolt Circle Detection', fn: () => this.testBoltCircle() },
|
|
269
|
+
{ name: 'Version Control - Save Version', fn: () => this.testVersionControl() },
|
|
270
|
+
{ name: 'Version Control - Visual Diff', fn: () => this.testVersionDiff() },
|
|
271
|
+
{ name: 'Parameter Table - Show Panel', fn: () => this.testParameterTable() },
|
|
272
|
+
{ name: 'Parameter Table - Update Parameter', fn: () => this.testParameterUpdate() },
|
|
273
|
+
{ name: 'Parameter Table - Formula Evaluation', fn: () => this.testFormula() },
|
|
274
|
+
{ name: 'Smart Mating - Detect Mate Type', fn: () => this.testSmartMate() },
|
|
275
|
+
{ name: 'Smart Mating - Apply Mate', fn: () => this.testApplyMate() },
|
|
276
|
+
{ name: 'Manufacturing Drawings - Generate', fn: () => this.testDrawings() },
|
|
277
|
+
{ name: 'Digital Twin - Start Live Data', fn: () => this.testDigitalTwin() },
|
|
278
|
+
];
|
|
279
|
+
|
|
280
|
+
this.totalTests = tests.length;
|
|
281
|
+
|
|
282
|
+
for (const test of tests) {
|
|
283
|
+
await this.runTest(test.name, test.fn);
|
|
284
|
+
this.updateProgress();
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
this.logResult(`\n✓ Test suite completed: ${this.stats.pass}/${this.stats.total} passed`, 'info');
|
|
288
|
+
},
|
|
289
|
+
|
|
290
|
+
async runTest(name, fn) {
|
|
291
|
+
this.currentTest++;
|
|
292
|
+
this.log(name, 'running');
|
|
293
|
+
|
|
294
|
+
try {
|
|
295
|
+
const result = await Promise.race([
|
|
296
|
+
fn.call(this),
|
|
297
|
+
new Promise((_, reject) => setTimeout(() => reject('Timeout'), 5000))
|
|
298
|
+
]);
|
|
299
|
+
|
|
300
|
+
if (result !== false) {
|
|
301
|
+
this.pass(name);
|
|
302
|
+
} else {
|
|
303
|
+
this.fail(name, 'Test returned false');
|
|
304
|
+
}
|
|
305
|
+
} catch (err) {
|
|
306
|
+
this.fail(name, err.message);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
310
|
+
},
|
|
311
|
+
|
|
312
|
+
log(message, status = 'info') {
|
|
313
|
+
const item = document.createElement('div');
|
|
314
|
+
item.className = `test-item ${status}`;
|
|
315
|
+
item.textContent = `${status === 'running' ? '⏳' : '▶'} ${message}`;
|
|
316
|
+
this.testLog.appendChild(item);
|
|
317
|
+
this.testLog.scrollTop = this.testLog.scrollHeight;
|
|
318
|
+
},
|
|
319
|
+
|
|
320
|
+
pass(name) {
|
|
321
|
+
this.stats.pass++;
|
|
322
|
+
this.stats.total++;
|
|
323
|
+
const item = document.querySelector(`div[data-test="${name}"]`) || document.createElement('div');
|
|
324
|
+
item.className = 'test-item pass';
|
|
325
|
+
item.textContent = `✓ ${name}`;
|
|
326
|
+
this.testLog.appendChild(item);
|
|
327
|
+
this.updateStats();
|
|
328
|
+
},
|
|
329
|
+
|
|
330
|
+
fail(name, reason) {
|
|
331
|
+
this.stats.fail++;
|
|
332
|
+
this.stats.total++;
|
|
333
|
+
const item = document.createElement('div');
|
|
334
|
+
item.className = 'test-item fail';
|
|
335
|
+
item.textContent = `✗ ${name} — ${reason}`;
|
|
336
|
+
this.testLog.appendChild(item);
|
|
337
|
+
this.updateStats();
|
|
338
|
+
},
|
|
339
|
+
|
|
340
|
+
updateStats() {
|
|
341
|
+
document.getElementById('stat-pass').textContent = this.stats.pass;
|
|
342
|
+
document.getElementById('stat-fail').textContent = this.stats.fail;
|
|
343
|
+
document.getElementById('stat-total').textContent = this.stats.total;
|
|
344
|
+
},
|
|
345
|
+
|
|
346
|
+
updateProgress() {
|
|
347
|
+
const pct = (this.currentTest / this.totalTests) * 100;
|
|
348
|
+
document.getElementById('progress-fill').style.width = pct + '%';
|
|
349
|
+
},
|
|
350
|
+
|
|
351
|
+
// =====================================================================
|
|
352
|
+
// TEST IMPLEMENTATIONS
|
|
353
|
+
// =====================================================================
|
|
354
|
+
|
|
355
|
+
async testAICopilot() {
|
|
356
|
+
const copilot = this.getFeature('aiCopilot');
|
|
357
|
+
if (!copilot) throw new Error('AI Copilot not initialized');
|
|
358
|
+
copilot.show();
|
|
359
|
+
return document.getElementById('kf-copilot-panel') !== null;
|
|
360
|
+
},
|
|
361
|
+
|
|
362
|
+
async testGearIntent() {
|
|
363
|
+
const copilot = this.getFeature('aiCopilot');
|
|
364
|
+
const intent = copilot.parseIntent('gear with 24 teeth, module 2');
|
|
365
|
+
return intent && intent.type === 'gear' && intent.teeth === 24;
|
|
366
|
+
},
|
|
367
|
+
|
|
368
|
+
async testBracketIntent() {
|
|
369
|
+
const copilot = this.getFeature('aiCopilot');
|
|
370
|
+
const intent = copilot.parseIntent('bracket 80x40x5');
|
|
371
|
+
return intent && intent.type === 'bracket' && intent.width === 80;
|
|
372
|
+
},
|
|
373
|
+
|
|
374
|
+
async testPhysics() {
|
|
375
|
+
const physics = this.getFeature('physics');
|
|
376
|
+
physics.toggle();
|
|
377
|
+
return physics.active === true;
|
|
378
|
+
},
|
|
379
|
+
|
|
380
|
+
async testPhysicsGravity() {
|
|
381
|
+
const physics = this.getFeature('physics');
|
|
382
|
+
const gravity = physics.gravity;
|
|
383
|
+
return gravity.y === -9.81;
|
|
384
|
+
},
|
|
385
|
+
|
|
386
|
+
async testGenerative() {
|
|
387
|
+
const gen = this.getFeature('generative');
|
|
388
|
+
gen.show();
|
|
389
|
+
return document.getElementById('kf-generative-panel') !== null;
|
|
390
|
+
},
|
|
391
|
+
|
|
392
|
+
async testGenerativeTopology() {
|
|
393
|
+
const gen = this.getFeature('generative');
|
|
394
|
+
// Topology generation is async, just check initialization
|
|
395
|
+
return gen !== null;
|
|
396
|
+
},
|
|
397
|
+
|
|
398
|
+
async testCostEstimator() {
|
|
399
|
+
const cost = this.getFeature('costEstimator');
|
|
400
|
+
cost.show();
|
|
401
|
+
return document.getElementById('kf-cost-panel') !== null;
|
|
402
|
+
},
|
|
403
|
+
|
|
404
|
+
async testCostCalculation() {
|
|
405
|
+
const cost = this.getFeature('costEstimator');
|
|
406
|
+
const vol = cost.estimateVolume();
|
|
407
|
+
return vol >= 0;
|
|
408
|
+
},
|
|
409
|
+
|
|
410
|
+
async testSmartSnap() {
|
|
411
|
+
const snap = this.getFeature('smartSnap');
|
|
412
|
+
return snap && snap.snapDistance === 15;
|
|
413
|
+
},
|
|
414
|
+
|
|
415
|
+
async testBoltCircle() {
|
|
416
|
+
const snap = this.getFeature('smartSnap');
|
|
417
|
+
// Test with empty array
|
|
418
|
+
const patterns = snap.detectBoltCircles([]);
|
|
419
|
+
return Array.isArray(patterns);
|
|
420
|
+
},
|
|
421
|
+
|
|
422
|
+
async testVersionControl() {
|
|
423
|
+
const vc = this.getFeature('versionControl');
|
|
424
|
+
vc.show();
|
|
425
|
+
return document.getElementById('kf-vc-panel') !== null;
|
|
426
|
+
},
|
|
427
|
+
|
|
428
|
+
async testVersionDiff() {
|
|
429
|
+
const vc = this.getFeature('versionControl');
|
|
430
|
+
vc.saveVersion();
|
|
431
|
+
return vc.versions.length > 0;
|
|
432
|
+
},
|
|
433
|
+
|
|
434
|
+
async testParameterTable() {
|
|
435
|
+
const params = this.getFeature('parameterTable');
|
|
436
|
+
params.show();
|
|
437
|
+
return document.getElementById('kf-param-table') !== null;
|
|
438
|
+
},
|
|
439
|
+
|
|
440
|
+
async testParameterUpdate() {
|
|
441
|
+
const params = this.getFeature('parameterTable');
|
|
442
|
+
params.updateParameter('width', 150);
|
|
443
|
+
return params.parameters.width.value === 150;
|
|
444
|
+
},
|
|
445
|
+
|
|
446
|
+
async testFormula() {
|
|
447
|
+
const params = this.getFeature('parameterTable');
|
|
448
|
+
params.parameters.height.formula = '=width*2';
|
|
449
|
+
params.evaluateFormulas();
|
|
450
|
+
return params.parameters.height.value > 0;
|
|
451
|
+
},
|
|
452
|
+
|
|
453
|
+
async testSmartMate() {
|
|
454
|
+
const mate = this.getFeature('smartMate');
|
|
455
|
+
// Mock parts
|
|
456
|
+
const part = { position: new THREE.Vector3() };
|
|
457
|
+
const mateType = mate.detectMateType(part, part);
|
|
458
|
+
return ['coincident', 'concentric', 'tangent'].includes(mateType);
|
|
459
|
+
},
|
|
460
|
+
|
|
461
|
+
async testApplyMate() {
|
|
462
|
+
const mate = this.getFeature('smartMate');
|
|
463
|
+
const part1 = { position: new THREE.Vector3(0, 0, 0) };
|
|
464
|
+
const part2 = { position: new THREE.Vector3(100, 100, 100) };
|
|
465
|
+
mate.applyMate(part1, part2, 'coincident');
|
|
466
|
+
return part2.position !== null;
|
|
467
|
+
},
|
|
468
|
+
|
|
469
|
+
async testDrawings() {
|
|
470
|
+
const drawings = this.getFeature('manufacturingDrawings');
|
|
471
|
+
// Just check it's initialized
|
|
472
|
+
return drawings !== null;
|
|
473
|
+
},
|
|
474
|
+
|
|
475
|
+
async testDigitalTwin() {
|
|
476
|
+
const twin = this.getFeature('digitalTwin');
|
|
477
|
+
twin.startLiveData();
|
|
478
|
+
return twin.liveDataActive === true;
|
|
479
|
+
},
|
|
480
|
+
|
|
481
|
+
// =====================================================================
|
|
482
|
+
// HELPERS
|
|
483
|
+
// =====================================================================
|
|
484
|
+
|
|
485
|
+
getFeature(name) {
|
|
486
|
+
try {
|
|
487
|
+
const win = this.iframe.contentWindow;
|
|
488
|
+
if (win.KillerFeatures && win.KillerFeatures.features) {
|
|
489
|
+
return win.KillerFeatures.features[name];
|
|
490
|
+
}
|
|
491
|
+
} catch (e) {
|
|
492
|
+
console.error('Cannot access iframe:', e);
|
|
493
|
+
}
|
|
494
|
+
return null;
|
|
495
|
+
},
|
|
496
|
+
|
|
497
|
+
async runAll() {
|
|
498
|
+
this.testLog.innerHTML += '<div class="test-item">Running full test suite...</div>';
|
|
499
|
+
await this.runKillerFeatures();
|
|
500
|
+
},
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
// Initialize on page load
|
|
504
|
+
window.addEventListener('DOMContentLoaded', () => {
|
|
505
|
+
TestAgent.init();
|
|
506
|
+
});
|
|
507
|
+
</script>
|
|
508
|
+
</body>
|
|
509
|
+
</html>
|