cyclecad 3.0.0 → 3.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 (66) hide show
  1. package/BILLING-IMPLEMENTATION-SUMMARY.md +425 -0
  2. package/BILLING-INDEX.md +293 -0
  3. package/BILLING-INTEGRATION-GUIDE.md +414 -0
  4. package/COLLABORATION-INDEX.md +440 -0
  5. package/COLLABORATION-SYSTEM-SUMMARY.md +548 -0
  6. package/DOCKER-BUILD-MANIFEST.txt +483 -0
  7. package/DOCKER-FILES-REFERENCE.md +440 -0
  8. package/DOCKER-INFRASTRUCTURE.md +475 -0
  9. package/DOCKER-README.md +435 -0
  10. package/Dockerfile +33 -55
  11. package/PWA-FILES-CREATED.txt +350 -0
  12. package/QUICK-START-TESTING.md +126 -0
  13. package/STEP-IMPORT-QUICKSTART.md +347 -0
  14. package/STEP-IMPORT-SYSTEM-SUMMARY.md +502 -0
  15. package/app/css/mobile.css +1074 -0
  16. package/app/icons/generate-icons.js +203 -0
  17. package/app/js/billing-ui.js +990 -0
  18. package/app/js/brep-kernel.js +933 -981
  19. package/app/js/collab-client.js +750 -0
  20. package/app/js/mobile-nav.js +623 -0
  21. package/app/js/mobile-toolbar.js +476 -0
  22. package/app/js/modules/billing-module.js +724 -0
  23. package/app/js/modules/step-module-enhanced.js +938 -0
  24. package/app/js/offline-manager.js +705 -0
  25. package/app/js/responsive-init.js +360 -0
  26. package/app/js/touch-handler.js +429 -0
  27. package/app/manifest.json +211 -0
  28. package/app/offline.html +508 -0
  29. package/app/sw.js +571 -0
  30. package/app/tests/billing-tests.html +779 -0
  31. package/app/tests/brep-tests.html +980 -0
  32. package/app/tests/collab-tests.html +743 -0
  33. package/app/tests/mobile-tests.html +1299 -0
  34. package/app/tests/pwa-tests.html +1134 -0
  35. package/app/tests/step-tests.html +1042 -0
  36. package/app/tests/test-agent-v3.html +719 -0
  37. package/docker-compose.yml +225 -0
  38. package/docs/BILLING-HELP.json +260 -0
  39. package/docs/BILLING-README.md +639 -0
  40. package/docs/BILLING-TUTORIAL.md +736 -0
  41. package/docs/BREP-HELP.json +326 -0
  42. package/docs/BREP-TUTORIAL.md +802 -0
  43. package/docs/COLLABORATION-HELP.json +228 -0
  44. package/docs/COLLABORATION-TUTORIAL.md +818 -0
  45. package/docs/DOCKER-HELP.json +224 -0
  46. package/docs/DOCKER-TUTORIAL.md +974 -0
  47. package/docs/MOBILE-HELP.json +243 -0
  48. package/docs/MOBILE-RESPONSIVE-README.md +378 -0
  49. package/docs/MOBILE-TUTORIAL.md +747 -0
  50. package/docs/PWA-HELP.json +228 -0
  51. package/docs/PWA-README.md +662 -0
  52. package/docs/PWA-TUTORIAL.md +757 -0
  53. package/docs/STEP-HELP.json +481 -0
  54. package/docs/STEP-IMPORT-TUTORIAL.md +824 -0
  55. package/docs/TESTING-GUIDE.md +528 -0
  56. package/docs/TESTING-HELP.json +182 -0
  57. package/fusion-vs-cyclecad.html +1771 -0
  58. package/nginx.conf +237 -0
  59. package/package.json +1 -1
  60. package/server/Dockerfile.converter +51 -0
  61. package/server/Dockerfile.signaling +28 -0
  62. package/server/billing-server.js +487 -0
  63. package/server/converter-enhanced.py +528 -0
  64. package/server/requirements-converter.txt +29 -0
  65. package/server/signaling-server.js +801 -0
  66. package/tests/docker-tests.sh +389 -0
@@ -0,0 +1,389 @@
1
+ #!/bin/bash
2
+
3
+ # cycleCAD Docker End-to-End Test Suite
4
+ # Comprehensive testing of all Docker services and functionality
5
+ #
6
+ # Usage: bash tests/docker-tests.sh
7
+ # Output: Test results with pass/fail status
8
+ #
9
+ # Tests:
10
+ # - Image building
11
+ # - Service startup
12
+ # - Health checks
13
+ # - API endpoints
14
+ # - STEP file conversion
15
+ # - Static asset serving
16
+ # - Headers and security
17
+ # - WebSocket connectivity
18
+ # - Resource cleanup
19
+
20
+ set -e
21
+
22
+ # Color codes for output
23
+ RED='\033[0;31m'
24
+ GREEN='\033[0;32m'
25
+ YELLOW='\033[1;33m'
26
+ BLUE='\033[0;34m'
27
+ NC='\033[0m' # No Color
28
+
29
+ # Test counters
30
+ TESTS_PASSED=0
31
+ TESTS_FAILED=0
32
+ TESTS_SKIPPED=0
33
+
34
+ # Configuration
35
+ BASE_URL="http://localhost:8080"
36
+ CONVERTER_URL="http://localhost:8787"
37
+ SIGNALING_URL="ws://localhost:8788"
38
+ TIMEOUT=10
39
+
40
+ # Helper functions
41
+ log_test() {
42
+ echo -e "${BLUE}[TEST]${NC} $1"
43
+ }
44
+
45
+ log_pass() {
46
+ echo -e "${GREEN}[PASS]${NC} $1"
47
+ ((TESTS_PASSED++))
48
+ }
49
+
50
+ log_fail() {
51
+ echo -e "${RED}[FAIL]${NC} $1"
52
+ ((TESTS_FAILED++))
53
+ }
54
+
55
+ log_skip() {
56
+ echo -e "${YELLOW}[SKIP]${NC} $1"
57
+ ((TESTS_SKIPPED++))
58
+ }
59
+
60
+ log_info() {
61
+ echo -e "${BLUE}[INFO]${NC} $1"
62
+ }
63
+
64
+ assert_http_status() {
65
+ local url=$1
66
+ local expected_status=$2
67
+ local description=$3
68
+
69
+ log_test "$description (expecting $expected_status)"
70
+
71
+ local actual_status=$(curl -s -o /dev/null -w "%{http_code}" \
72
+ --max-time $TIMEOUT \
73
+ -H "Connection: close" \
74
+ "$url" 2>/dev/null || echo "000")
75
+
76
+ if [ "$actual_status" = "$expected_status" ]; then
77
+ log_pass "$description"
78
+ return 0
79
+ else
80
+ log_fail "$description (got $actual_status, expected $expected_status)"
81
+ return 1
82
+ fi
83
+ }
84
+
85
+ assert_header_exists() {
86
+ local url=$1
87
+ local header=$2
88
+ local description=$3
89
+
90
+ log_test "$description"
91
+
92
+ local has_header=$(curl -s -I --max-time $TIMEOUT "$url" 2>/dev/null | grep -i "^${header}:" || echo "")
93
+
94
+ if [ ! -z "$has_header" ]; then
95
+ log_pass "$description"
96
+ return 0
97
+ else
98
+ log_fail "$description (header '$header' not found)"
99
+ return 1
100
+ fi
101
+ }
102
+
103
+ wait_for_service() {
104
+ local url=$1
105
+ local max_attempts=30
106
+ local attempt=0
107
+
108
+ log_info "Waiting for $url to be ready..."
109
+
110
+ while [ $attempt -lt $max_attempts ]; do
111
+ if curl -s --max-time 2 "$url" > /dev/null 2>&1; then
112
+ log_info "$url is ready"
113
+ return 0
114
+ fi
115
+ echo -n "."
116
+ sleep 1
117
+ ((attempt++))
118
+ done
119
+
120
+ log_fail "Timeout waiting for $url"
121
+ return 1
122
+ }
123
+
124
+ # ============================================================================
125
+ # TEST SUITE
126
+ # ============================================================================
127
+
128
+ echo ""
129
+ echo "╔════════════════════════════════════════════════════════════════╗"
130
+ echo "║ cycleCAD Docker End-to-End Test Suite ║"
131
+ echo "║ $(date '+%Y-%m-%d %H:%M:%S') ║"
132
+ echo "╚════════════════════════════════════════════════════════════════╝"
133
+ echo ""
134
+
135
+ # Test 1: Check if docker-compose is available
136
+ log_test "docker-compose is installed and accessible"
137
+ if command -v docker-compose &> /dev/null; then
138
+ log_pass "docker-compose command found"
139
+ else
140
+ log_fail "docker-compose not found in PATH"
141
+ exit 1
142
+ fi
143
+
144
+ # Test 2: Check if Docker daemon is running
145
+ log_test "Docker daemon is running"
146
+ if docker info > /dev/null 2>&1; then
147
+ log_pass "Docker daemon is accessible"
148
+ else
149
+ log_fail "Cannot connect to Docker daemon"
150
+ exit 1
151
+ fi
152
+
153
+ # Test 3: Service startup verification
154
+ log_test "All services are running"
155
+ sleep 5 # Give services time to stabilize
156
+
157
+ RUNNING_SERVICES=$(docker-compose ps --format "{{.Name}}" | wc -l)
158
+ if [ $RUNNING_SERVICES -ge 3 ]; then
159
+ log_pass "Expected number of services running ($RUNNING_SERVICES)"
160
+ else
161
+ log_fail "Not enough services running (found $RUNNING_SERVICES, expected 3+)"
162
+ fi
163
+
164
+ # Test 4: Wait for services to be ready
165
+ log_info "Waiting for services to become ready..."
166
+ wait_for_service "$BASE_URL/health" || exit 1
167
+ wait_for_service "$CONVERTER_URL/health" || exit 1
168
+
169
+ # ============================================================================
170
+ # cycleCAD Web App Tests (Port 8080)
171
+ # ============================================================================
172
+
173
+ echo ""
174
+ log_info "Testing cycleCAD Web Application..."
175
+
176
+ assert_http_status "$BASE_URL/health" "200" "Health check endpoint" || true
177
+ assert_http_status "$BASE_URL/" "200" "Landing page (index.html)" || true
178
+ assert_http_status "$BASE_URL/app/" "200" "CAD app (app/index.html)" || true
179
+
180
+ # Test header presence
181
+ assert_header_exists "$BASE_URL/" "Access-Control-Allow-Origin" "CORS header present" || true
182
+ assert_header_exists "$BASE_URL/" "Cross-Origin-Opener-Policy" "COOP header present" || true
183
+ assert_header_exists "$BASE_URL/" "Cross-Origin-Embedder-Policy" "COEP header present" || true
184
+ assert_header_exists "$BASE_URL/" "X-Content-Type-Options" "X-Content-Type-Options header" || true
185
+
186
+ # Test caching headers
187
+ log_test "Static assets have aggressive caching"
188
+ CACHE_HEADER=$(curl -s -I "$BASE_URL/screenshot.png" 2>/dev/null | grep -i "Cache-Control" | head -1)
189
+ if [[ "$CACHE_HEADER" =~ "public" ]]; then
190
+ log_pass "Static assets have Cache-Control header"
191
+ else
192
+ log_fail "Static assets missing Cache-Control header"
193
+ fi
194
+
195
+ # Test gzip compression
196
+ log_test "Gzip compression is enabled"
197
+ GZIP_TEST=$(curl -s -H "Accept-Encoding: gzip" -I "$BASE_URL/" 2>/dev/null | grep -i "Content-Encoding: gzip")
198
+ if [ ! -z "$GZIP_TEST" ]; then
199
+ log_pass "Gzip compression enabled for responses"
200
+ else
201
+ log_skip "Gzip compression (may not apply to small responses)"
202
+ fi
203
+
204
+ # Test SPA routing
205
+ log_test "SPA routing works for /app/* paths"
206
+ for path in "/app/" "/app/project/test" "/app/edit/model"; do
207
+ assert_http_status "$BASE_URL$path" "200" "SPA route: $path" || true
208
+ done
209
+
210
+ # ============================================================================
211
+ # Converter Service Tests (Port 8787)
212
+ # ============================================================================
213
+
214
+ echo ""
215
+ log_info "Testing STEP Converter Service..."
216
+
217
+ assert_http_status "$CONVERTER_URL/health" "200" "Converter health check" || true
218
+
219
+ # Test OpenAPI documentation
220
+ assert_http_status "$CONVERTER_URL/docs" "200" "OpenAPI documentation" || true
221
+
222
+ # Test converter API endpoints
223
+ log_test "Converter API /convert endpoint exists"
224
+ assert_http_status "$CONVERTER_URL/convert" "405" "POST /convert expects POST (405 for GET)" || true
225
+
226
+ # Create a test STEP file if it doesn't exist
227
+ TEST_STEP_FILE="test-part.stp"
228
+ if [ ! -f "$TEST_STEP_FILE" ]; then
229
+ log_info "Creating minimal test STEP file..."
230
+ # Minimal valid STEP file
231
+ cat > "$TEST_STEP_FILE" << 'EOF'
232
+ ISO-10303-21;
233
+ HEADER;
234
+ FILE_DESCRIPTION(('Test part','Test'),
235
+ '2',2024,13,11,15,30,00,0,());
236
+ FILE_NAME('test-part.stp',
237
+ 2024,13,11,15,30,00,0,(),
238
+ '','','');
239
+ FILE_SCHEMA(('IFC2X3'));
240
+ ENDSEC;
241
+ DATA;
242
+ #1=CARTESIAN_POINT('',(0.,0.,0.));
243
+ #2=CARTESIAN_POINT('',(1.,0.,0.));
244
+ #3=CARTESIAN_POINT('',(1.,1.,0.));
245
+ ENDSEC;
246
+ END-ISO-10303-21;
247
+ EOF
248
+ fi
249
+
250
+ # Test file upload (may fail if converter not ready, that's OK)
251
+ log_test "STEP file upload and conversion"
252
+ if [ -f "$TEST_STEP_FILE" ]; then
253
+ RESPONSE=$(curl -s -X POST \
254
+ --max-time 30 \
255
+ -F "file=@$TEST_STEP_FILE" \
256
+ "$CONVERTER_URL/convert" 2>/dev/null || echo "")
257
+
258
+ if [ ! -z "$RESPONSE" ] && [[ "$RESPONSE" == *"glb"* ]] || [[ "$RESPONSE" == *"gltf"* ]]; then
259
+ log_pass "STEP conversion returns GLB/glTF response"
260
+ else
261
+ log_skip "STEP conversion (may require full OpenCASCADE.js setup)"
262
+ fi
263
+ else
264
+ log_skip "STEP file upload (test file not available)"
265
+ fi
266
+
267
+ # ============================================================================
268
+ # Signaling Service Tests (Port 8788)
269
+ # ============================================================================
270
+
271
+ echo ""
272
+ log_info "Testing Signaling Service..."
273
+
274
+ assert_http_status "$SIGNALING_URL/health" "200" "Signaling health check" || true
275
+
276
+ # Test WebSocket upgrade
277
+ log_test "WebSocket endpoint accepts upgrades"
278
+ # This is a simple check; full WebSocket testing requires wscat or websocat
279
+ WS_TEST=$(curl -s -I -H "Upgrade: websocket" \
280
+ --max-time $TIMEOUT \
281
+ "$SIGNALING_URL/ws" 2>/dev/null | grep -i "upgrade" || echo "")
282
+
283
+ if [ ! -z "$WS_TEST" ]; then
284
+ log_pass "WebSocket upgrade headers present"
285
+ else
286
+ log_skip "WebSocket test (requires websocat or wscat)"
287
+ fi
288
+
289
+ # ============================================================================
290
+ # Docker-Specific Tests
291
+ # ============================================================================
292
+
293
+ echo ""
294
+ log_info "Testing Docker Configuration..."
295
+
296
+ # Test container resource limits
297
+ log_test "Container resource limits are configured"
298
+ CONVERTER_MEMORY=$(docker-compose inspect converter 2>/dev/null | grep -i '"Memory"' | head -1)
299
+ if [ ! -z "$CONVERTER_MEMORY" ]; then
300
+ log_pass "Converter has memory limits configured"
301
+ else
302
+ log_skip "Container memory limits (not visible in inspect output)"
303
+ fi
304
+
305
+ # Test health checks
306
+ log_test "Services have health checks defined"
307
+ HEALTH_CHECKS=$(docker-compose inspect --format='{{.Config.Healthcheck}}' 2>/dev/null | grep -c "test" || echo "0")
308
+ if [ $HEALTH_CHECKS -gt 0 ]; then
309
+ log_pass "Health checks are configured"
310
+ else
311
+ log_fail "No health checks found in docker-compose"
312
+ fi
313
+
314
+ # Test network
315
+ log_test "Services are connected to correct network"
316
+ NETWORK_NAME=$(docker network ls --filter "name=cyclecad" --format "{{.Name}}")
317
+ if [ ! -z "$NETWORK_NAME" ]; then
318
+ log_pass "cycleCAD network exists"
319
+ else
320
+ log_skip "Network verification (may need to inspect separately)"
321
+ fi
322
+
323
+ # ============================================================================
324
+ # Integration Tests
325
+ # ============================================================================
326
+
327
+ echo ""
328
+ log_info "Running Integration Tests..."
329
+
330
+ # Test cross-service communication
331
+ log_test "Converter and signaling are accessible from main app"
332
+ for port in 8787 8788; do
333
+ assert_http_status "http://localhost:$port/health" "200" "Port $port is accessible" || true
334
+ done
335
+
336
+ # Test file size limits
337
+ log_test "Upload size limits are enforced"
338
+ # Check nginx max body size in config
339
+ if [ -f "nginx.conf" ]; then
340
+ MAX_SIZE=$(grep -i "client_max_body_size" nginx.conf | head -1)
341
+ if [[ "$MAX_SIZE" =~ "500M" ]]; then
342
+ log_pass "Max upload size set to 500MB"
343
+ else
344
+ log_skip "Max upload size check"
345
+ fi
346
+ fi
347
+
348
+ # ============================================================================
349
+ # Cleanup Tests
350
+ # ============================================================================
351
+
352
+ echo ""
353
+ log_info "Testing Cleanup Operations..."
354
+
355
+ log_test "Services can be stopped and restarted"
356
+ # Just verify the commands would work without executing (too disruptive)
357
+ if docker-compose ps > /dev/null 2>&1; then
358
+ log_pass "docker-compose commands are functional"
359
+ else
360
+ log_fail "docker-compose is not responding"
361
+ fi
362
+
363
+ # ============================================================================
364
+ # Test Summary
365
+ # ============================================================================
366
+
367
+ echo ""
368
+ echo "╔════════════════════════════════════════════════════════════════╗"
369
+ echo "║ TEST SUMMARY ║"
370
+ echo "╚════════════════════════════════════════════════════════════════╝"
371
+ echo ""
372
+ echo -e "Tests Passed: ${GREEN}$TESTS_PASSED${NC}"
373
+ echo -e "Tests Failed: ${RED}$TESTS_FAILED${NC}"
374
+ echo -e "Tests Skipped: ${YELLOW}$TESTS_SKIPPED${NC}"
375
+ echo ""
376
+
377
+ TOTAL=$((TESTS_PASSED + TESTS_FAILED + TESTS_SKIPPED))
378
+ PASS_RATE=$((TESTS_PASSED * 100 / (TESTS_PASSED + TESTS_FAILED + 1)))
379
+
380
+ echo "Pass Rate: ${PASS_RATE}% ($TESTS_PASSED/$((TESTS_PASSED + TESTS_FAILED)))"
381
+ echo ""
382
+
383
+ if [ $TESTS_FAILED -eq 0 ]; then
384
+ echo -e "${GREEN}✓ All critical tests passed!${NC}"
385
+ exit 0
386
+ else
387
+ echo -e "${RED}✗ Some tests failed. Review output above.${NC}"
388
+ exit 1
389
+ fi