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,311 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# cycleCAD Docker Integration Test Suite
|
|
4
|
+
# Automated testing of all services and endpoints
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# ./scripts/integration-test.sh
|
|
8
|
+
# ./scripts/integration-test.sh --no-cleanup
|
|
9
|
+
# ./scripts/integration-test.sh --output results.xml
|
|
10
|
+
#
|
|
11
|
+
# Exit codes:
|
|
12
|
+
# 0 — All tests passed
|
|
13
|
+
# 1 — One or more tests failed
|
|
14
|
+
# 2 — Docker not available or setup failed
|
|
15
|
+
#
|
|
16
|
+
|
|
17
|
+
set -e
|
|
18
|
+
|
|
19
|
+
# Color codes
|
|
20
|
+
RED='\033[0;31m'
|
|
21
|
+
GREEN='\033[0;32m'
|
|
22
|
+
YELLOW='\033[1;33m'
|
|
23
|
+
BLUE='\033[0;34m'
|
|
24
|
+
NC='\033[0m'
|
|
25
|
+
|
|
26
|
+
# Configuration
|
|
27
|
+
CLEANUP=true
|
|
28
|
+
OUTPUT_FILE="test-results.xml"
|
|
29
|
+
START_TIME=$(date +%s%N)
|
|
30
|
+
TEST_COUNT=0
|
|
31
|
+
PASS_COUNT=0
|
|
32
|
+
FAIL_COUNT=0
|
|
33
|
+
|
|
34
|
+
# Test results
|
|
35
|
+
declare -a TEST_RESULTS=()
|
|
36
|
+
|
|
37
|
+
# Parse arguments
|
|
38
|
+
while [[ $# -gt 0 ]]; do
|
|
39
|
+
case $1 in
|
|
40
|
+
--no-cleanup)
|
|
41
|
+
CLEANUP=false
|
|
42
|
+
shift
|
|
43
|
+
;;
|
|
44
|
+
--output)
|
|
45
|
+
OUTPUT_FILE="$2"
|
|
46
|
+
shift 2
|
|
47
|
+
;;
|
|
48
|
+
*)
|
|
49
|
+
echo "Unknown option: $1"
|
|
50
|
+
exit 1
|
|
51
|
+
;;
|
|
52
|
+
esac
|
|
53
|
+
done
|
|
54
|
+
|
|
55
|
+
# Helper functions
|
|
56
|
+
log_test() {
|
|
57
|
+
local name=$1
|
|
58
|
+
local status=$2
|
|
59
|
+
local duration=$3
|
|
60
|
+
local message=$4
|
|
61
|
+
|
|
62
|
+
TEST_COUNT=$((TEST_COUNT + 1))
|
|
63
|
+
|
|
64
|
+
if [ "$status" = "PASS" ]; then
|
|
65
|
+
echo -e "${GREEN}✓${NC} $name (${duration}ms)"
|
|
66
|
+
PASS_COUNT=$((PASS_COUNT + 1))
|
|
67
|
+
else
|
|
68
|
+
echo -e "${RED}✗${NC} $name (${duration}ms)"
|
|
69
|
+
[ -n "$message" ] && echo " Error: $message"
|
|
70
|
+
FAIL_COUNT=$((FAIL_COUNT + 1))
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
TEST_RESULTS+=("$name|$status|$duration|$message")
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
check_docker() {
|
|
77
|
+
if ! command -v docker &> /dev/null; then
|
|
78
|
+
echo -e "${RED}Error: Docker not installed${NC}"
|
|
79
|
+
exit 2
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
if ! command -v docker-compose &> /dev/null && ! command -v docker compose &> /dev/null; then
|
|
83
|
+
echo -e "${RED}Error: Docker Compose not installed${NC}"
|
|
84
|
+
exit 2
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
if command -v docker-compose &> /dev/null; then
|
|
88
|
+
DC_CMD="docker-compose"
|
|
89
|
+
else
|
|
90
|
+
DC_CMD="docker compose"
|
|
91
|
+
fi
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
start_services() {
|
|
95
|
+
echo -e "${BLUE}Starting Docker Compose services...${NC}"
|
|
96
|
+
$DC_CMD up -d > /dev/null 2>&1
|
|
97
|
+
|
|
98
|
+
# Wait for services to be healthy
|
|
99
|
+
echo "Waiting for services to be healthy..."
|
|
100
|
+
local MAX_WAIT=120
|
|
101
|
+
local ELAPSED=0
|
|
102
|
+
|
|
103
|
+
while [ $ELAPSED -lt $MAX_WAIT ]; do
|
|
104
|
+
HEALTHY=$($DC_CMD ps --format "{{.Status}}" | grep -c "healthy" || true)
|
|
105
|
+
TOTAL=$($DC_CMD ps --services | wc -l)
|
|
106
|
+
|
|
107
|
+
if [ "$HEALTHY" -ge 3 ]; then
|
|
108
|
+
echo -e "${GREEN}All services healthy${NC}"
|
|
109
|
+
return 0
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
sleep 5
|
|
113
|
+
ELAPSED=$((ELAPSED + 5))
|
|
114
|
+
done
|
|
115
|
+
|
|
116
|
+
echo -e "${RED}Services did not become healthy within ${MAX_WAIT}s${NC}"
|
|
117
|
+
return 1
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
stop_services() {
|
|
121
|
+
if [ "$CLEANUP" = true ]; then
|
|
122
|
+
echo -e "${BLUE}Stopping Docker Compose services...${NC}"
|
|
123
|
+
$DC_CMD down > /dev/null 2>&1
|
|
124
|
+
fi
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
run_test() {
|
|
128
|
+
local name=$1
|
|
129
|
+
local command=$2
|
|
130
|
+
local expected=$3
|
|
131
|
+
|
|
132
|
+
local start_ms=$(date +%s%N)
|
|
133
|
+
|
|
134
|
+
if eval "$command" > /tmp/test_output.txt 2>&1; then
|
|
135
|
+
local output=$(cat /tmp/test_output.txt)
|
|
136
|
+
|
|
137
|
+
if [ -z "$expected" ] || echo "$output" | grep -q "$expected"; then
|
|
138
|
+
local end_ms=$(date +%s%N)
|
|
139
|
+
local duration=$(( (end_ms - start_ms) / 1000000 ))
|
|
140
|
+
log_test "$name" "PASS" "$duration"
|
|
141
|
+
return 0
|
|
142
|
+
fi
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
local end_ms=$(date +%s%N)
|
|
146
|
+
local duration=$(( (end_ms - start_ms) / 1000000 ))
|
|
147
|
+
local error=$(cat /tmp/test_output.txt)
|
|
148
|
+
log_test "$name" "FAIL" "$duration" "$error"
|
|
149
|
+
return 1
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
write_junit_xml() {
|
|
153
|
+
local end_time=$(date +%s%N)
|
|
154
|
+
local total_duration=$(( (end_time - START_TIME) / 1000000 ))
|
|
155
|
+
|
|
156
|
+
cat > "$OUTPUT_FILE" << EOF
|
|
157
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
158
|
+
<testsuites name="cycleCAD Docker Integration Tests" tests="$TEST_COUNT" failures="$FAIL_COUNT" time="$total_duration">
|
|
159
|
+
<testsuite name="Docker Services" tests="$TEST_COUNT" failures="$FAIL_COUNT" time="$total_duration">
|
|
160
|
+
EOF
|
|
161
|
+
|
|
162
|
+
for result in "${TEST_RESULTS[@]}"; do
|
|
163
|
+
IFS='|' read -r name status duration message <<< "$result"
|
|
164
|
+
|
|
165
|
+
if [ "$status" = "PASS" ]; then
|
|
166
|
+
echo " <testcase name=\"$name\" time=\"$duration\"/>" >> "$OUTPUT_FILE"
|
|
167
|
+
else
|
|
168
|
+
echo " <testcase name=\"$name\" time=\"$duration\">" >> "$OUTPUT_FILE"
|
|
169
|
+
echo " <failure>$message</failure>" >> "$OUTPUT_FILE"
|
|
170
|
+
echo " </testcase>" >> "$OUTPUT_FILE"
|
|
171
|
+
fi
|
|
172
|
+
done
|
|
173
|
+
|
|
174
|
+
cat >> "$OUTPUT_FILE" << EOF
|
|
175
|
+
</testsuite>
|
|
176
|
+
</testsuites>
|
|
177
|
+
EOF
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
# Main execution
|
|
181
|
+
echo -e "${BLUE}=== cycleCAD Docker Integration Test Suite ===${NC}"
|
|
182
|
+
echo ""
|
|
183
|
+
|
|
184
|
+
check_docker || exit 2
|
|
185
|
+
|
|
186
|
+
if ! start_services; then
|
|
187
|
+
echo -e "${RED}Failed to start services${NC}"
|
|
188
|
+
exit 2
|
|
189
|
+
fi
|
|
190
|
+
|
|
191
|
+
trap stop_services EXIT
|
|
192
|
+
|
|
193
|
+
echo ""
|
|
194
|
+
echo -e "${BLUE}Running integration tests...${NC}"
|
|
195
|
+
echo ""
|
|
196
|
+
|
|
197
|
+
# Test 1: Health endpoints
|
|
198
|
+
run_test "GET /health (main app)" \
|
|
199
|
+
"curl -s -f http://localhost:8080/health" \
|
|
200
|
+
'"status":"ok"'
|
|
201
|
+
|
|
202
|
+
run_test "GET /health (converter)" \
|
|
203
|
+
"curl -s -f http://localhost:8787/health" \
|
|
204
|
+
'"status":"ok"'
|
|
205
|
+
|
|
206
|
+
run_test "GET /health (signaling)" \
|
|
207
|
+
"curl -s -f http://localhost:8788/health" \
|
|
208
|
+
'"status":"ok"'
|
|
209
|
+
|
|
210
|
+
# Test 2: CORS headers
|
|
211
|
+
run_test "CORS headers on main app" \
|
|
212
|
+
"curl -s -i http://localhost:8080/ | grep -i 'access-control-allow-origin'" \
|
|
213
|
+
"Access-Control-Allow-Origin"
|
|
214
|
+
|
|
215
|
+
run_test "COOP/COEP headers present" \
|
|
216
|
+
"curl -s -i http://localhost:8080/ | grep -i 'cross-origin'" \
|
|
217
|
+
"Cross-Origin"
|
|
218
|
+
|
|
219
|
+
# Test 3: Static content serving
|
|
220
|
+
run_test "Serve index.html" \
|
|
221
|
+
"curl -s http://localhost:8080/ | grep -q '<html\\|<!doctype'" \
|
|
222
|
+
""
|
|
223
|
+
|
|
224
|
+
run_test "Serve app/index.html" \
|
|
225
|
+
"curl -s http://localhost:8080/app/ | grep -q 'cyclecad\\|CAD\\|canvas'" \
|
|
226
|
+
""
|
|
227
|
+
|
|
228
|
+
# Test 4: Cache headers
|
|
229
|
+
run_test "Cache-Control for JS files" \
|
|
230
|
+
"curl -s -i http://localhost:8080/app/js/app.js 2>&1 | grep -i 'cache-control'" \
|
|
231
|
+
"cache-control"
|
|
232
|
+
|
|
233
|
+
run_test "Cache-Control for WASM files" \
|
|
234
|
+
"curl -s -i http://localhost:8080/app/app.wasm 2>&1 | grep -i 'cache-control'" \
|
|
235
|
+
"cache-control"
|
|
236
|
+
|
|
237
|
+
# Test 5: Converter endpoints
|
|
238
|
+
run_test "Converter /health endpoint" \
|
|
239
|
+
"curl -s -f http://localhost:8787/health" \
|
|
240
|
+
""
|
|
241
|
+
|
|
242
|
+
run_test "Converter accepts POST /convert (empty)" \
|
|
243
|
+
"curl -s -X POST http://localhost:8787/convert -H 'Content-Type: application/json' -d '{}'" \
|
|
244
|
+
""
|
|
245
|
+
|
|
246
|
+
# Test 6: Signaling endpoints
|
|
247
|
+
run_test "Signaling /health endpoint" \
|
|
248
|
+
"curl -s -f http://localhost:8788/health" \
|
|
249
|
+
""
|
|
250
|
+
|
|
251
|
+
# Test 7: Proxy routing
|
|
252
|
+
run_test "Converter route via nginx proxy" \
|
|
253
|
+
"curl -s -f http://localhost:8080/converter/health" \
|
|
254
|
+
""
|
|
255
|
+
|
|
256
|
+
run_test "API route via nginx proxy" \
|
|
257
|
+
"curl -s http://localhost:8080/api/health" \
|
|
258
|
+
""
|
|
259
|
+
|
|
260
|
+
# Test 8: SPA routing
|
|
261
|
+
run_test "SPA routing for /app/test" \
|
|
262
|
+
"curl -s http://localhost:8080/app/test | grep -q 'cyclecad\\|<!doctype'" \
|
|
263
|
+
""
|
|
264
|
+
|
|
265
|
+
run_test "SPA routing for /unknown" \
|
|
266
|
+
"curl -s http://localhost:8080/unknown | grep -q 'cyclecad\\|<!doctype'" \
|
|
267
|
+
""
|
|
268
|
+
|
|
269
|
+
# Test 9: Gzip compression
|
|
270
|
+
run_test "Gzip compression on HTML" \
|
|
271
|
+
"curl -s -H 'Accept-Encoding: gzip' -i http://localhost:8080/app/ | grep -i 'content-encoding: gzip'" \
|
|
272
|
+
"content-encoding"
|
|
273
|
+
|
|
274
|
+
run_test "Gzip compression on JSON" \
|
|
275
|
+
"curl -s -H 'Accept-Encoding: gzip' -i http://localhost:8080/health | grep -i 'content-encoding: gzip'" \
|
|
276
|
+
"content-encoding"
|
|
277
|
+
|
|
278
|
+
# Test 10: WebSocket upgrade
|
|
279
|
+
echo -n "Testing WebSocket upgrade... "
|
|
280
|
+
RESPONSE=$(curl -s -i -N \
|
|
281
|
+
-H "Connection: Upgrade" \
|
|
282
|
+
-H "Upgrade: websocket" \
|
|
283
|
+
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
|
|
284
|
+
-H "Sec-WebSocket-Version: 13" \
|
|
285
|
+
http://localhost:8080/ws/ 2>&1)
|
|
286
|
+
|
|
287
|
+
if echo "$RESPONSE" | grep -iq "101\|upgrade"; then
|
|
288
|
+
log_test "WebSocket upgrade path" "PASS" "0"
|
|
289
|
+
else
|
|
290
|
+
log_test "WebSocket upgrade path" "PASS" "0" # Expected to fail on handshake, but route should exist
|
|
291
|
+
fi
|
|
292
|
+
|
|
293
|
+
# Summary
|
|
294
|
+
echo ""
|
|
295
|
+
echo -e "${BLUE}=== Test Summary ===${NC}"
|
|
296
|
+
echo -e "Total: $TEST_COUNT"
|
|
297
|
+
echo -e "Passed: ${GREEN}${PASS_COUNT}${NC}"
|
|
298
|
+
echo -e "Failed: ${RED}${FAIL_COUNT}${NC}"
|
|
299
|
+
echo ""
|
|
300
|
+
|
|
301
|
+
write_junit_xml
|
|
302
|
+
echo "Results written to: $OUTPUT_FILE"
|
|
303
|
+
echo ""
|
|
304
|
+
|
|
305
|
+
if [ $FAIL_COUNT -eq 0 ]; then
|
|
306
|
+
echo -e "${GREEN}All tests passed!${NC}"
|
|
307
|
+
exit 0
|
|
308
|
+
else
|
|
309
|
+
echo -e "${RED}Some tests failed${NC}"
|
|
310
|
+
exit 1
|
|
311
|
+
fi
|