retold-data-service 2.0.18 → 2.0.20
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 +2 -2
- package/source/services/Retold-Data-Service-MeadowEndpoints.js +12 -2
- package/source/services/data-cloner/DataCloner-Command-Schema.js +4 -3
- package/source/services/data-cloner/DataCloner-Command-Sync.js +31 -4
- package/source/services/data-cloner/DataCloner-ProviderRegistry.js +1 -1
- package/source/services/data-cloner/Retold-Data-Service-DataCloner.js +47 -7
- package/source/services/data-cloner/pict-app/Pict-Application-DataCloner.js +2 -1
- package/source/services/data-cloner/pict-app/providers/Pict-Provider-DataCloner.js +102 -2
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Export.js +2 -0
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Layout.js +28 -0
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Sync.js +7 -0
- package/source/services/data-cloner/web/data-cloner.js +117 -3
- package/source/services/data-cloner/web/data-cloner.js.map +1 -1
- package/source/services/data-cloner/web/data-cloner.min.js +1 -1
- package/source/services/data-cloner/web/data-cloner.min.js.map +1 -1
- package/test/run-integration-tests.js +52 -12
- package/test/run-integration-tests.sh +221 -0
- package/test/integration-report.json +0 -311
|
@@ -166,24 +166,54 @@ function fPrintReport()
|
|
|
166
166
|
console.log(` Skipped: ${_Report.summary.skipped}`);
|
|
167
167
|
console.log('-'.repeat(72));
|
|
168
168
|
|
|
169
|
-
//
|
|
170
|
-
|
|
171
|
-
let
|
|
172
|
-
for (let i = 0; i < tmpEngines.length; i++)
|
|
169
|
+
// Build storage engine status from suite results
|
|
170
|
+
let tmpStorageEnginePrefix = 'Storage Engine: ';
|
|
171
|
+
for (let i = 0; i < _Report.suites.length; i++)
|
|
173
172
|
{
|
|
174
|
-
let
|
|
175
|
-
|
|
176
|
-
|
|
173
|
+
let tmpSuite = _Report.suites[i];
|
|
174
|
+
if (tmpSuite.name.indexOf(tmpStorageEnginePrefix) !== 0) continue;
|
|
175
|
+
|
|
176
|
+
let tmpEngineName = tmpSuite.name.substring(tmpStorageEnginePrefix.length);
|
|
177
|
+
let tmpPassCount = tmpSuite.tests.filter((t) => t.status === 'pass').length;
|
|
178
|
+
let tmpFailCount = tmpSuite.tests.filter((t) => t.status === 'fail').length;
|
|
179
|
+
let tmpSkipCount = tmpSuite.tests.filter((t) => t.status === 'skip').length;
|
|
180
|
+
|
|
181
|
+
if (tmpSkipCount === tmpSuite.tests.length)
|
|
177
182
|
{
|
|
178
|
-
|
|
183
|
+
_Report.storage_engines[tmpEngineName] = { status: 'skip', reason: 'Not configured (env vars not set)' };
|
|
179
184
|
}
|
|
180
|
-
else if (
|
|
185
|
+
else if (tmpFailCount > 0)
|
|
181
186
|
{
|
|
182
|
-
|
|
187
|
+
let tmpFirstError = tmpSuite.tests.find((t) => t.status === 'fail');
|
|
188
|
+
_Report.storage_engines[tmpEngineName] = { status: 'fail', error: tmpFirstError ? tmpFirstError.error : 'Unknown' };
|
|
183
189
|
}
|
|
184
190
|
else
|
|
185
191
|
{
|
|
186
|
-
|
|
192
|
+
_Report.storage_engines[tmpEngineName] = { status: 'pass', sync_duration_ms: tmpSuite.duration_ms, records_synced: 0, tables_synced: 0 };
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Storage engines
|
|
197
|
+
let tmpEngines = Object.keys(_Report.storage_engines);
|
|
198
|
+
if (tmpEngines.length > 0)
|
|
199
|
+
{
|
|
200
|
+
console.log('\n Storage Engines:');
|
|
201
|
+
for (let i = 0; i < tmpEngines.length; i++)
|
|
202
|
+
{
|
|
203
|
+
let tmpName = tmpEngines[i];
|
|
204
|
+
let tmpEngine = _Report.storage_engines[tmpName];
|
|
205
|
+
if (tmpEngine.status === 'pass')
|
|
206
|
+
{
|
|
207
|
+
console.log(` ${tmpName.padEnd(14)} PASS ${fFormatDuration(tmpEngine.sync_duration_ms).padStart(10)} ${tmpEngine.records_synced} records / ${tmpEngine.tables_synced} tables`);
|
|
208
|
+
}
|
|
209
|
+
else if (tmpEngine.status === 'fail')
|
|
210
|
+
{
|
|
211
|
+
console.log(` ${tmpName.padEnd(14)} FAIL ${tmpEngine.error || 'Unknown error'}`);
|
|
212
|
+
}
|
|
213
|
+
else
|
|
214
|
+
{
|
|
215
|
+
console.log(` ${tmpName.padEnd(14)} SKIP ${tmpEngine.reason || ''}`);
|
|
216
|
+
}
|
|
187
217
|
}
|
|
188
218
|
}
|
|
189
219
|
|
|
@@ -194,8 +224,18 @@ function fPrintReport()
|
|
|
194
224
|
let tmpSuite = _Report.suites[i];
|
|
195
225
|
let tmpPassCount = tmpSuite.tests.filter((t) => t.status === 'pass').length;
|
|
196
226
|
let tmpFailCount = tmpSuite.tests.filter((t) => t.status === 'fail').length;
|
|
227
|
+
let tmpSkipCount = tmpSuite.tests.filter((t) => t.status === 'skip').length;
|
|
228
|
+
|
|
229
|
+
if (tmpSkipCount === tmpSuite.tests.length && tmpSuite.tests.length > 0)
|
|
230
|
+
{
|
|
231
|
+
// All tests in this suite were skipped
|
|
232
|
+
console.log(` ~ ${tmpSuite.name.padEnd(35)} skipped`);
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
|
|
197
236
|
let tmpStatus = tmpFailCount > 0 ? 'FAIL' : 'PASS';
|
|
198
|
-
|
|
237
|
+
let tmpSkipLabel = tmpSkipCount > 0 ? ` (${tmpSkipCount} skipped)` : '';
|
|
238
|
+
console.log(` ${tmpStatus === 'FAIL' ? 'X' : '+'} ${tmpSuite.name.padEnd(35)} ${tmpPassCount}/${tmpPassCount + tmpFailCount} passed ${fFormatDuration(tmpSuite.duration_ms)}${tmpSkipLabel}`);
|
|
199
239
|
|
|
200
240
|
// Show failed tests
|
|
201
241
|
for (let j = 0; j < tmpSuite.tests.length; j++)
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ==============================================================================
|
|
3
|
+
# Data Cloner Integration Tests — All Storage Engines
|
|
4
|
+
#
|
|
5
|
+
# Starts Docker containers for MySQL, PostgreSQL, and MSSQL, creates the
|
|
6
|
+
# required test databases, then runs the full integration test suite against
|
|
7
|
+
# every engine (SQLite runs without Docker).
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
# ./test/run-integration-tests.sh # All engines
|
|
11
|
+
# ./test/run-integration-tests.sh sqlite # SQLite only (no Docker)
|
|
12
|
+
# ./test/run-integration-tests.sh mysql # MySQL only
|
|
13
|
+
# ./test/run-integration-tests.sh mysql,mssql # Specific engines
|
|
14
|
+
#
|
|
15
|
+
# Prerequisites:
|
|
16
|
+
# - Docker (and docker compose) installed and running
|
|
17
|
+
# - Node.js and npm
|
|
18
|
+
# - npm install already run in retold-data-service
|
|
19
|
+
# ==============================================================================
|
|
20
|
+
|
|
21
|
+
set -euo pipefail
|
|
22
|
+
|
|
23
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
24
|
+
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
25
|
+
HARNESS_DIR="$(cd "$PROJECT_DIR/../retold-harness" 2>/dev/null && pwd)" || true
|
|
26
|
+
|
|
27
|
+
# ---- Parse arguments ----
|
|
28
|
+
ENGINES="${1:-sqlite,mysql,postgresql,mssql}"
|
|
29
|
+
|
|
30
|
+
# ---- Credentials (match retold-harness/docker-compose.yml) ----
|
|
31
|
+
MYSQL_ROOT_PASSWORD="1234567890"
|
|
32
|
+
MYSQL_TEST_DB="retold_cloner_test"
|
|
33
|
+
|
|
34
|
+
POSTGRESQL_PASSWORD="retold1234567890"
|
|
35
|
+
POSTGRESQL_TEST_DB="retold_cloner_test"
|
|
36
|
+
|
|
37
|
+
MSSQL_SA_PASSWORD="Retold1234567890!"
|
|
38
|
+
MSSQL_TEST_DB="retold_cloner_test"
|
|
39
|
+
|
|
40
|
+
# ---- Colours ----
|
|
41
|
+
RED='\033[0;31m'
|
|
42
|
+
GREEN='\033[0;32m'
|
|
43
|
+
YELLOW='\033[1;33m'
|
|
44
|
+
CYAN='\033[0;36m'
|
|
45
|
+
NC='\033[0m' # No colour
|
|
46
|
+
|
|
47
|
+
log() { echo -e "${CYAN}[$(date +%H:%M:%S)]${NC} $*"; }
|
|
48
|
+
warn() { echo -e "${YELLOW}[$(date +%H:%M:%S)] WARNING:${NC} $*"; }
|
|
49
|
+
err() { echo -e "${RED}[$(date +%H:%M:%S)] ERROR:${NC} $*"; }
|
|
50
|
+
ok() { echo -e "${GREEN}[$(date +%H:%M:%S)] OK:${NC} $*"; }
|
|
51
|
+
|
|
52
|
+
needs_docker()
|
|
53
|
+
{
|
|
54
|
+
[[ "$ENGINES" == *mysql* ]] || [[ "$ENGINES" == *postgresql* ]] || [[ "$ENGINES" == *mssql* ]]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
# ---- Check prerequisites ----
|
|
58
|
+
if needs_docker; then
|
|
59
|
+
if ! command -v docker &>/dev/null; then
|
|
60
|
+
err "Docker is not installed. Install Docker to test non-SQLite engines."
|
|
61
|
+
err "Or run: $0 sqlite"
|
|
62
|
+
exit 1
|
|
63
|
+
fi
|
|
64
|
+
if ! docker info &>/dev/null; then
|
|
65
|
+
err "Docker daemon is not running. Start Docker first."
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
if [ -z "$HARNESS_DIR" ] || [ ! -d "$HARNESS_DIR" ]; then
|
|
71
|
+
err "retold-harness not found at $PROJECT_DIR/../retold-harness"
|
|
72
|
+
err "Make sure retold-harness is cloned as a sibling of retold-data-service."
|
|
73
|
+
exit 1
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# ---- Start Docker containers ----
|
|
77
|
+
start_containers()
|
|
78
|
+
{
|
|
79
|
+
log "Starting Docker containers..."
|
|
80
|
+
cd "$HARNESS_DIR"
|
|
81
|
+
|
|
82
|
+
local SERVICES=""
|
|
83
|
+
[[ "$ENGINES" == *mysql* ]] && SERVICES="$SERVICES mysql"
|
|
84
|
+
[[ "$ENGINES" == *postgresql* ]] && SERVICES="$SERVICES postgresql"
|
|
85
|
+
[[ "$ENGINES" == *mssql* ]] && SERVICES="$SERVICES mssql"
|
|
86
|
+
|
|
87
|
+
if [ -n "$SERVICES" ]; then
|
|
88
|
+
docker compose up -d $SERVICES
|
|
89
|
+
log "Waiting for containers to become healthy..."
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
cd "$PROJECT_DIR"
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# Wait for a container to be healthy (or timeout after N seconds)
|
|
96
|
+
wait_healthy()
|
|
97
|
+
{
|
|
98
|
+
local CONTAINER="$1"
|
|
99
|
+
local TIMEOUT="${2:-120}"
|
|
100
|
+
local ELAPSED=0
|
|
101
|
+
|
|
102
|
+
while [ $ELAPSED -lt $TIMEOUT ]; do
|
|
103
|
+
local STATUS
|
|
104
|
+
STATUS="$(docker inspect --format='{{.State.Health.Status}}' "$CONTAINER" 2>/dev/null || echo "missing")"
|
|
105
|
+
if [ "$STATUS" = "healthy" ]; then
|
|
106
|
+
return 0
|
|
107
|
+
fi
|
|
108
|
+
sleep 2
|
|
109
|
+
ELAPSED=$((ELAPSED + 2))
|
|
110
|
+
done
|
|
111
|
+
|
|
112
|
+
err "$CONTAINER did not become healthy within ${TIMEOUT}s (status: $STATUS)"
|
|
113
|
+
return 1
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
# ---- Create test databases ----
|
|
117
|
+
create_mysql_db()
|
|
118
|
+
{
|
|
119
|
+
log "Waiting for MySQL to be healthy..."
|
|
120
|
+
wait_healthy "retold-harness-mysql" 120
|
|
121
|
+
|
|
122
|
+
log "Creating MySQL database '${MYSQL_TEST_DB}'..."
|
|
123
|
+
docker exec retold-harness-mysql mysql \
|
|
124
|
+
-uroot "-p${MYSQL_ROOT_PASSWORD}" \
|
|
125
|
+
-e "CREATE DATABASE IF NOT EXISTS \`${MYSQL_TEST_DB}\`;" 2>/dev/null
|
|
126
|
+
ok "MySQL database '${MYSQL_TEST_DB}' ready"
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
create_postgresql_db()
|
|
130
|
+
{
|
|
131
|
+
log "Waiting for PostgreSQL to be healthy..."
|
|
132
|
+
wait_healthy "retold-harness-postgresql" 120
|
|
133
|
+
|
|
134
|
+
log "Creating PostgreSQL database '${POSTGRESQL_TEST_DB}'..."
|
|
135
|
+
# createdb returns 0 even if DB exists when using IF NOT EXISTS via psql
|
|
136
|
+
docker exec retold-harness-postgresql psql \
|
|
137
|
+
-U postgres \
|
|
138
|
+
-tc "SELECT 1 FROM pg_database WHERE datname = '${POSTGRESQL_TEST_DB}'" \
|
|
139
|
+
| grep -q 1 \
|
|
140
|
+
|| docker exec retold-harness-postgresql psql \
|
|
141
|
+
-U postgres \
|
|
142
|
+
-c "CREATE DATABASE ${POSTGRESQL_TEST_DB};"
|
|
143
|
+
ok "PostgreSQL database '${POSTGRESQL_TEST_DB}' ready"
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
create_mssql_db()
|
|
147
|
+
{
|
|
148
|
+
log "Waiting for MSSQL to be healthy..."
|
|
149
|
+
wait_healthy "retold-harness-mssql" 120
|
|
150
|
+
|
|
151
|
+
log "Creating MSSQL database '${MSSQL_TEST_DB}'..."
|
|
152
|
+
docker exec retold-harness-mssql /opt/mssql-tools18/bin/sqlcmd \
|
|
153
|
+
-S localhost -U sa -P "${MSSQL_SA_PASSWORD}" -C \
|
|
154
|
+
-Q "IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = '${MSSQL_TEST_DB}') CREATE DATABASE [${MSSQL_TEST_DB}];" 2>/dev/null
|
|
155
|
+
ok "MSSQL database '${MSSQL_TEST_DB}' ready"
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
# ---- Main ----
|
|
159
|
+
|
|
160
|
+
log "Engines requested: ${ENGINES}"
|
|
161
|
+
log "Project dir: ${PROJECT_DIR}"
|
|
162
|
+
log "Harness dir: ${HARNESS_DIR}"
|
|
163
|
+
echo ""
|
|
164
|
+
|
|
165
|
+
# Start Docker containers if needed
|
|
166
|
+
if needs_docker; then
|
|
167
|
+
start_containers
|
|
168
|
+
|
|
169
|
+
# Create test databases in parallel where possible
|
|
170
|
+
[[ "$ENGINES" == *mysql* ]] && create_mysql_db
|
|
171
|
+
[[ "$ENGINES" == *postgresql* ]] && create_postgresql_db
|
|
172
|
+
[[ "$ENGINES" == *mssql* ]] && create_mssql_db
|
|
173
|
+
|
|
174
|
+
echo ""
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
# ---- Set environment variables ----
|
|
178
|
+
if [[ "$ENGINES" == *mysql* ]]; then
|
|
179
|
+
export MYSQL_HOST="localhost"
|
|
180
|
+
export MYSQL_PORT="3306"
|
|
181
|
+
export MYSQL_USER="root"
|
|
182
|
+
export MYSQL_PASSWORD="${MYSQL_ROOT_PASSWORD}"
|
|
183
|
+
export MYSQL_DATABASE="${MYSQL_TEST_DB}"
|
|
184
|
+
ok "MySQL env configured (localhost:3306, db=${MYSQL_TEST_DB})"
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
if [[ "$ENGINES" == *postgresql* ]]; then
|
|
188
|
+
export POSTGRESQL_HOST="localhost"
|
|
189
|
+
export POSTGRESQL_PORT="5432"
|
|
190
|
+
export POSTGRESQL_USER="postgres"
|
|
191
|
+
export POSTGRESQL_PASSWORD="${POSTGRESQL_PASSWORD}"
|
|
192
|
+
export POSTGRESQL_DATABASE="${POSTGRESQL_TEST_DB}"
|
|
193
|
+
ok "PostgreSQL env configured (localhost:5432, db=${POSTGRESQL_TEST_DB})"
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
if [[ "$ENGINES" == *mssql* ]]; then
|
|
197
|
+
export MSSQL_HOST="localhost"
|
|
198
|
+
export MSSQL_PORT="1433"
|
|
199
|
+
export MSSQL_USER="sa"
|
|
200
|
+
export MSSQL_PASSWORD="${MSSQL_SA_PASSWORD}"
|
|
201
|
+
export MSSQL_DATABASE="${MSSQL_TEST_DB}"
|
|
202
|
+
ok "MSSQL env configured (localhost:1433, db=${MSSQL_TEST_DB})"
|
|
203
|
+
fi
|
|
204
|
+
|
|
205
|
+
echo ""
|
|
206
|
+
log "Running integration tests..."
|
|
207
|
+
echo ""
|
|
208
|
+
|
|
209
|
+
# ---- Run tests ----
|
|
210
|
+
cd "$PROJECT_DIR"
|
|
211
|
+
node test/run-integration-tests.js --skip-puppeteer --engines="${ENGINES}"
|
|
212
|
+
TEST_EXIT=$?
|
|
213
|
+
|
|
214
|
+
echo ""
|
|
215
|
+
if [ $TEST_EXIT -eq 0 ]; then
|
|
216
|
+
ok "All integration tests passed!"
|
|
217
|
+
else
|
|
218
|
+
err "Some tests failed (exit code: ${TEST_EXIT})"
|
|
219
|
+
fi
|
|
220
|
+
|
|
221
|
+
exit $TEST_EXIT
|
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"timestamp": "2026-03-08T20:33:17.745Z",
|
|
3
|
-
"duration_ms": 54218,
|
|
4
|
-
"summary": {
|
|
5
|
-
"total": 35,
|
|
6
|
-
"passed": 32,
|
|
7
|
-
"failed": 0,
|
|
8
|
-
"skipped": 3
|
|
9
|
-
},
|
|
10
|
-
"storage_engines": {},
|
|
11
|
-
"suites": [
|
|
12
|
-
{
|
|
13
|
-
"name": "Data Cloner Integration",
|
|
14
|
-
"tests": [],
|
|
15
|
-
"duration_ms": 0
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
"name": "Connection Management",
|
|
19
|
-
"tests": [
|
|
20
|
-
{
|
|
21
|
-
"name": "Should show initial connection status",
|
|
22
|
-
"status": "pass",
|
|
23
|
-
"duration_ms": 1
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"name": "Should connect SQLite via configure",
|
|
27
|
-
"status": "pass",
|
|
28
|
-
"duration_ms": 2
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"name": "Should show connected after configure",
|
|
32
|
-
"status": "pass",
|
|
33
|
-
"duration_ms": 0
|
|
34
|
-
}
|
|
35
|
-
],
|
|
36
|
-
"duration_ms": 3
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
"name": "Session Configuration",
|
|
40
|
-
"tests": [
|
|
41
|
-
{
|
|
42
|
-
"name": "Should configure session with retold-harness URL",
|
|
43
|
-
"status": "pass",
|
|
44
|
-
"duration_ms": 1
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
"name": "Should show session as configured",
|
|
48
|
-
"status": "pass",
|
|
49
|
-
"duration_ms": 9
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
"name": "Should reject session configure without ServerURL",
|
|
53
|
-
"status": "pass",
|
|
54
|
-
"duration_ms": 1
|
|
55
|
-
}
|
|
56
|
-
],
|
|
57
|
-
"duration_ms": 11
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
"name": "Schema Fetch",
|
|
61
|
-
"tests": [
|
|
62
|
-
{
|
|
63
|
-
"name": "Should reconfigure session for fresh schema fetch",
|
|
64
|
-
"status": "pass",
|
|
65
|
-
"duration_ms": 1
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
"name": "Should fetch schema from retold-harness",
|
|
69
|
-
"status": "pass",
|
|
70
|
-
"duration_ms": 2
|
|
71
|
-
}
|
|
72
|
-
],
|
|
73
|
-
"duration_ms": 3
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
"name": "Schema Deploy",
|
|
77
|
-
"tests": [
|
|
78
|
-
{
|
|
79
|
-
"name": "Should deploy all tables",
|
|
80
|
-
"status": "pass",
|
|
81
|
-
"duration_ms": 25
|
|
82
|
-
}
|
|
83
|
-
],
|
|
84
|
-
"duration_ms": 25
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
"name": "Initial Sync (SQLite)",
|
|
88
|
-
"tests": [
|
|
89
|
-
{
|
|
90
|
-
"name": "Should start initial sync with record cap",
|
|
91
|
-
"status": "pass",
|
|
92
|
-
"duration_ms": 1007
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
"name": "All tables should have completed",
|
|
96
|
-
"status": "pass",
|
|
97
|
-
"duration_ms": 1
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
"name": "Should have a valid sync report",
|
|
101
|
-
"status": "pass",
|
|
102
|
-
"duration_ms": 3
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
"name": "Report tables should have timing data",
|
|
106
|
-
"status": "pass",
|
|
107
|
-
"duration_ms": 1
|
|
108
|
-
}
|
|
109
|
-
],
|
|
110
|
-
"duration_ms": 1012
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
"name": "Data Integrity",
|
|
114
|
-
"tests": [
|
|
115
|
-
{
|
|
116
|
-
"name": "Should fetch harness reference data",
|
|
117
|
-
"status": "pass",
|
|
118
|
-
"duration_ms": 9
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
"name": "Local book count should match sync (capped)",
|
|
122
|
-
"status": "pass",
|
|
123
|
-
"duration_ms": 2
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
"name": "Local Book 1 should match harness data",
|
|
127
|
-
"status": "pass",
|
|
128
|
-
"duration_ms": 1
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
"name": "Local author count should match sync (capped)",
|
|
132
|
-
"status": "pass",
|
|
133
|
-
"duration_ms": 0
|
|
134
|
-
}
|
|
135
|
-
],
|
|
136
|
-
"duration_ms": 12
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
"name": "Pre-Count and Live Status",
|
|
140
|
-
"tests": [
|
|
141
|
-
{
|
|
142
|
-
"name": "Should run a fresh pipeline and capture pre-count data",
|
|
143
|
-
"status": "pass",
|
|
144
|
-
"duration_ms": 7885
|
|
145
|
-
}
|
|
146
|
-
],
|
|
147
|
-
"duration_ms": 7885
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
"name": "Ongoing Sync",
|
|
151
|
-
"tests": [
|
|
152
|
-
{
|
|
153
|
-
"name": "Should run ongoing sync after initial",
|
|
154
|
-
"status": "pass",
|
|
155
|
-
"duration_ms": 1019
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
"name": "Ongoing sync report should show success",
|
|
159
|
-
"status": "pass",
|
|
160
|
-
"duration_ms": 1
|
|
161
|
-
}
|
|
162
|
-
],
|
|
163
|
-
"duration_ms": 1020
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
"name": "Stop Sync",
|
|
167
|
-
"tests": [
|
|
168
|
-
{
|
|
169
|
-
"name": "Should be able to stop a sync in progress",
|
|
170
|
-
"status": "pass",
|
|
171
|
-
"duration_ms": 4063
|
|
172
|
-
}
|
|
173
|
-
],
|
|
174
|
-
"duration_ms": 4063
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
"name": "Reset",
|
|
178
|
-
"tests": [
|
|
179
|
-
{
|
|
180
|
-
"name": "Should reset the database",
|
|
181
|
-
"status": "pass",
|
|
182
|
-
"duration_ms": 2
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
"name": "Connection should still work after reset",
|
|
186
|
-
"status": "pass",
|
|
187
|
-
"duration_ms": 1
|
|
188
|
-
}
|
|
189
|
-
],
|
|
190
|
-
"duration_ms": 3
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
"name": "Storage Engine: MySQL",
|
|
194
|
-
"tests": [
|
|
195
|
-
{
|
|
196
|
-
"name": "Should sync via MySQL",
|
|
197
|
-
"status": "skip",
|
|
198
|
-
"duration_ms": 0
|
|
199
|
-
}
|
|
200
|
-
],
|
|
201
|
-
"duration_ms": 0
|
|
202
|
-
},
|
|
203
|
-
{
|
|
204
|
-
"name": "Storage Engine: PostgreSQL",
|
|
205
|
-
"tests": [
|
|
206
|
-
{
|
|
207
|
-
"name": "Should sync via PostgreSQL",
|
|
208
|
-
"status": "skip",
|
|
209
|
-
"duration_ms": 0
|
|
210
|
-
}
|
|
211
|
-
],
|
|
212
|
-
"duration_ms": 0
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
"name": "Storage Engine: MSSQL",
|
|
216
|
-
"tests": [
|
|
217
|
-
{
|
|
218
|
-
"name": "Should sync via MSSQL",
|
|
219
|
-
"status": "skip",
|
|
220
|
-
"duration_ms": 0
|
|
221
|
-
}
|
|
222
|
-
],
|
|
223
|
-
"duration_ms": 0
|
|
224
|
-
}
|
|
225
|
-
],
|
|
226
|
-
"puppeteer": {
|
|
227
|
-
"available": true,
|
|
228
|
-
"suites": [
|
|
229
|
-
{
|
|
230
|
-
"name": "Data Cloner Web UI (Puppeteer)",
|
|
231
|
-
"tests": [],
|
|
232
|
-
"duration_ms": 0
|
|
233
|
-
},
|
|
234
|
-
{
|
|
235
|
-
"name": "Web UI Load",
|
|
236
|
-
"tests": [
|
|
237
|
-
{
|
|
238
|
-
"name": "Should load the data cloner page",
|
|
239
|
-
"status": "pass",
|
|
240
|
-
"duration_ms": 734
|
|
241
|
-
},
|
|
242
|
-
{
|
|
243
|
-
"name": "Should display 7 accordion sections",
|
|
244
|
-
"status": "pass",
|
|
245
|
-
"duration_ms": 15
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
"name": "Should show live status bar",
|
|
249
|
-
"status": "pass",
|
|
250
|
-
"duration_ms": 201
|
|
251
|
-
}
|
|
252
|
-
],
|
|
253
|
-
"duration_ms": 950
|
|
254
|
-
},
|
|
255
|
-
{
|
|
256
|
-
"name": "Connection Section",
|
|
257
|
-
"tests": [
|
|
258
|
-
{
|
|
259
|
-
"name": "Should connect to SQLite via go button",
|
|
260
|
-
"status": "pass",
|
|
261
|
-
"duration_ms": 2218
|
|
262
|
-
}
|
|
263
|
-
],
|
|
264
|
-
"duration_ms": 2218
|
|
265
|
-
},
|
|
266
|
-
{
|
|
267
|
-
"name": "Session, Schema, and Deploy Flow",
|
|
268
|
-
"tests": [
|
|
269
|
-
{
|
|
270
|
-
"name": "Should configure session via UI",
|
|
271
|
-
"status": "pass",
|
|
272
|
-
"duration_ms": 3019
|
|
273
|
-
},
|
|
274
|
-
{
|
|
275
|
-
"name": "Should fetch schema via UI",
|
|
276
|
-
"status": "pass",
|
|
277
|
-
"duration_ms": 2020
|
|
278
|
-
},
|
|
279
|
-
{
|
|
280
|
-
"name": "Should deploy schema via UI",
|
|
281
|
-
"status": "pass",
|
|
282
|
-
"duration_ms": 5074
|
|
283
|
-
}
|
|
284
|
-
],
|
|
285
|
-
"duration_ms": 10113
|
|
286
|
-
},
|
|
287
|
-
{
|
|
288
|
-
"name": "Sync via Web UI",
|
|
289
|
-
"tests": [
|
|
290
|
-
{
|
|
291
|
-
"name": "Should start sync and complete successfully",
|
|
292
|
-
"status": "pass",
|
|
293
|
-
"duration_ms": 7184
|
|
294
|
-
}
|
|
295
|
-
],
|
|
296
|
-
"duration_ms": 7184
|
|
297
|
-
},
|
|
298
|
-
{
|
|
299
|
-
"name": "Live Status Display",
|
|
300
|
-
"tests": [
|
|
301
|
-
{
|
|
302
|
-
"name": "Should show progress information during sync",
|
|
303
|
-
"status": "pass",
|
|
304
|
-
"duration_ms": 16243
|
|
305
|
-
}
|
|
306
|
-
],
|
|
307
|
-
"duration_ms": 16243
|
|
308
|
-
}
|
|
309
|
-
]
|
|
310
|
-
}
|
|
311
|
-
}
|