experiments in a post-browser web
1#!/bin/bash
2# Version Compatibility End-to-End Test
3#
4# Usage: ./scripts/version-compat-e2e.sh
5#
6# This script:
7# 1. Builds the project
8# 2. Starts a local server on a random port
9# 3. Seeds test items
10# 4. Runs automated desktop <-> server version compat tests
11# 5. Optionally runs iOS simulator manual sync test
12#
13# Exit codes: 0 = all passed, 1 = failures
14
15set -e
16
17SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
18PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
19SERVER_DIR="$PROJECT_DIR/backend/server"
20
21# Use random high port to avoid conflicts
22PORT=$((3470 + RANDOM % 100))
23API_KEY="version-compat-e2e-key-$(date +%s)"
24TEMP_DIR=""
25SERVER_PID=""
26
27cleanup() {
28 echo ""
29 echo "Cleaning up..."
30 if [ -n "$SERVER_PID" ]; then
31 kill "$SERVER_PID" 2>/dev/null || true
32 fi
33 if [ -n "$MISMATCH_SERVER_PID" ]; then
34 kill "$MISMATCH_SERVER_PID" 2>/dev/null || true
35 fi
36 if [ -n "$TEMP_DIR" ] && [ -d "$TEMP_DIR" ]; then
37 rm -rf "$TEMP_DIR"
38 fi
39}
40trap cleanup EXIT
41
42echo "=========================================="
43echo " Version Compatibility E2E Test"
44echo "=========================================="
45echo ""
46
47# Step 1: Build
48echo "[1/4] Building project..."
49cd "$PROJECT_DIR"
50yarn build
51echo " Build complete."
52echo ""
53
54# Step 2: Start server
55echo "[2/4] Starting server on port $PORT..."
56TEMP_DIR=$(mktemp -d)
57export PORT API_KEY
58export DATA_DIR="$TEMP_DIR"
59
60cd "$SERVER_DIR"
61node index.js &
62SERVER_PID=$!
63cd "$PROJECT_DIR"
64
65# Wait for server
66for i in $(seq 1 30); do
67 if curl -s "http://localhost:$PORT/" > /dev/null 2>&1; then
68 break
69 fi
70 sleep 0.5
71done
72
73# Verify server is running with version info
74HEALTH=$(curl -s "http://localhost:$PORT/")
75echo " Server health: $HEALTH"
76
77DS_VERSION=$(echo "$HEALTH" | python3 -c "import sys,json; print(json.load(sys.stdin).get('datastore_version', 'missing'))" 2>/dev/null || echo "parse_error")
78PROTO_VERSION=$(echo "$HEALTH" | python3 -c "import sys,json; print(json.load(sys.stdin).get('protocol_version', 'missing'))" 2>/dev/null || echo "parse_error")
79
80echo " Datastore version: $DS_VERSION"
81echo " Protocol version: $PROTO_VERSION"
82
83if [ "$DS_VERSION" != "1" ] || [ "$PROTO_VERSION" != "1" ]; then
84 echo " ERROR: Health check missing version info!"
85 exit 1
86fi
87echo " Server version check: OK"
88echo ""
89
90# Step 3: Seed test data
91echo "[3/4] Seeding test items..."
92PROFILE_PARAM="profile=default"
93
94curl -s -X POST "http://localhost:$PORT/items?$PROFILE_PARAM" \
95 -H "Authorization: Bearer $API_KEY" \
96 -H "Content-Type: application/json" \
97 -H "X-Peek-Datastore-Version: 1" \
98 -H "X-Peek-Protocol-Version: 1" \
99 -d '{"type": "url", "content": "https://version-test-1.example.com", "tags": ["test"]}' > /dev/null
100
101curl -s -X POST "http://localhost:$PORT/items?$PROFILE_PARAM" \
102 -H "Authorization: Bearer $API_KEY" \
103 -H "Content-Type: application/json" \
104 -H "X-Peek-Datastore-Version: 1" \
105 -H "X-Peek-Protocol-Version: 1" \
106 -d '{"type": "text", "content": "Version compat test text", "tags": ["test"]}' > /dev/null
107
108curl -s -X POST "http://localhost:$PORT/items?$PROFILE_PARAM" \
109 -H "Authorization: Bearer $API_KEY" \
110 -H "Content-Type: application/json" \
111 -H "X-Peek-Datastore-Version: 1" \
112 -H "X-Peek-Protocol-Version: 1" \
113 -d '{"type": "url", "content": "https://version-test-3.example.com", "tags": ["test"]}' > /dev/null
114
115echo " Seeded 3 test items"
116echo ""
117
118# Stop main server before running automated tests (they start their own)
119kill "$SERVER_PID" 2>/dev/null || true
120SERVER_PID=""
121sleep 1
122
123# Step 4: Run automated tests
124echo "[4/4] Running automated version compat tests..."
125echo ""
126
127cd "$PROJECT_DIR"
128if node backend/tests/sync-version-compat.test.js; then
129 echo ""
130 echo " Automated tests: ALL PASSED"
131else
132 echo ""
133 echo " Automated tests: FAILED"
134 exit 1
135fi
136
137echo ""
138echo "=========================================="
139echo " All automated tests passed!"
140echo "=========================================="
141echo ""
142
143# Optional: iOS simulator manual test
144read -p "Run iOS simulator manual test? (y/N) " -n 1 -r
145echo ""
146
147if [[ $REPLY =~ ^[Yy]$ ]]; then
148 echo ""
149 echo "--- iOS Simulator Sync Test ---"
150 echo ""
151
152 # Restart server for manual testing
153 PORT=$((3470 + RANDOM % 100))
154 TEMP_DIR2=$(mktemp -d)
155 export PORT
156 export DATA_DIR="$TEMP_DIR2"
157
158 cd "$SERVER_DIR"
159 node index.js &
160 SERVER_PID=$!
161 cd "$PROJECT_DIR"
162
163 for i in $(seq 1 30); do
164 if curl -s "http://localhost:$PORT/" > /dev/null 2>&1; then
165 break
166 fi
167 sleep 0.5
168 done
169
170 # Seed items for iOS test
171 PROFILE_PARAM="profile=default"
172 for i in 1 2 3; do
173 curl -s -X POST "http://localhost:$PORT/items?$PROFILE_PARAM" \
174 -H "Authorization: Bearer $API_KEY" \
175 -H "Content-Type: application/json" \
176 -H "X-Peek-Datastore-Version: 1" \
177 -H "X-Peek-Protocol-Version: 1" \
178 -d "{\"type\": \"url\", \"content\": \"https://ios-test-$i.example.com\", \"tags\": [\"ios-test\"]}" > /dev/null
179 done
180
181 LOCAL_IP=$(ipconfig getifaddr en0 2>/dev/null || echo "localhost")
182 SERVER_URL="http://$LOCAL_IP:$PORT"
183
184 echo "┌─────────────────────────────────────────────────┐"
185 echo "│ MANUAL STEP: iOS Simulator Sync Test │"
186 echo "│ │"
187 echo "│ Server: $SERVER_URL"
188 echo "│ API Key: $API_KEY"
189 echo "│ │"
190 echo "│ 1. Build & run iOS app in simulator │"
191 echo "│ (yarn mobile:ios:build) │"
192 echo "│ 2. Configure server URL and API key │"
193 echo "│ 3. Open the app → Settings → Sync │"
194 echo "│ 4. Tap 'Pull' to sync from server │"
195 echo "│ 5. Verify 3 test items appear │"
196 echo "│ 6. Add a local item, tap 'Push' │"
197 echo "│ 7. Press ENTER here when done │"
198 echo "└─────────────────────────────────────────────────┘"
199 read -p ""
200
201 # Verify pushed item
202 ITEMS=$(curl -s "http://localhost:$PORT/items?$PROFILE_PARAM" \
203 -H "Authorization: Bearer $API_KEY")
204 ITEM_COUNT=$(echo "$ITEMS" | python3 -c "import sys,json; print(len(json.load(sys.stdin).get('items', [])))" 2>/dev/null || echo "0")
205
206 if [ "$ITEM_COUNT" -gt 3 ]; then
207 echo " iOS sync test: PASSED ($ITEM_COUNT items on server, expected > 3)"
208 else
209 echo " iOS sync test: INCONCLUSIVE ($ITEM_COUNT items on server)"
210 fi
211 echo ""
212
213 # Version mismatch test
214 echo "Restarting server with mismatched version for mismatch test..."
215 kill "$SERVER_PID" 2>/dev/null || true
216 sleep 1
217
218 # Start server — the version is compiled into version.js, so mismatch testing
219 # with iOS would require modifying the file. Skip for automated portion.
220 echo ""
221 echo "┌──────────────────────────────────────────────────┐"
222 echo "│ MANUAL STEP: Version Mismatch Test (Optional) │"
223 echo "│ │"
224 echo "│ This requires modifying server version.js to │"
225 echo "│ DATASTORE_VERSION=99 and restarting. │"
226 echo "│ Skip this if you just want to verify basic sync. │"
227 echo "│ │"
228 echo "│ Press ENTER to finish. │"
229 echo "└──────────────────────────────────────────────────┘"
230 read -p ""
231
232 # Cleanup temp dir
233 rm -rf "$TEMP_DIR2" 2>/dev/null || true
234fi
235
236echo ""
237echo "=========================================="
238echo " Version Compatibility E2E: COMPLETE"
239echo "=========================================="