@freshworks/shiftleft-tools 1.1.8
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/README.md +351 -0
- package/bin/shiftleft.js +95 -0
- package/package.json +57 -0
- package/src/commands/doctor.js +208 -0
- package/src/commands/init-postman.js +298 -0
- package/src/commands/init-rules.js +78 -0
- package/src/commands/link.js +172 -0
- package/src/commands/protect.js +61 -0
- package/src/commands/run-tests.js +182 -0
- package/src/commands/setup-pipeline.js +209 -0
- package/src/commands/update.js +203 -0
- package/src/index.js +4 -0
- package/src/utils/copy-tree.js +98 -0
- package/src/utils/gitignore.js +26 -0
- package/src/utils/logger.js +9 -0
- package/src/utils/manifest.js +145 -0
- package/src/utils/stack.js +80 -0
- package/src/utils/template.js +135 -0
- package/templates/AGENTS.md +109 -0
- package/templates/CLAUDE.md +3 -0
- package/templates/jenkins/Jenkinsfile-java.groovy +432 -0
- package/templates/jenkins/Jenkinsfile-node.groovy +450 -0
- package/templates/postman/.husky/pre-commit +19 -0
- package/templates/postman/.prettierrc.json +5 -0
- package/templates/postman/README.md.ejs +147 -0
- package/templates/postman/collections/01-core.json.ejs +91 -0
- package/templates/postman/config/local.json.ejs +12 -0
- package/templates/postman/config/staging.json.ejs +26 -0
- package/templates/postman/environments/local.postman_environment.json.ejs +31 -0
- package/templates/postman/environments/staging.postman_environment.json.ejs +31 -0
- package/templates/postman/gitignore +16 -0
- package/templates/postman/npmrc +31 -0
- package/templates/postman/package.json.ejs +66 -0
- package/templates/postman/run-all-shim.sh +16 -0
- package/templates/postman/scripts/auth/generate-jwt.sh +113 -0
- package/templates/postman/scripts/auth/get-issuer-secret.sh +140 -0
- package/templates/postman/scripts/infra/start-mocks.sh +138 -0
- package/templates/postman/scripts/infra/stop-mocks.sh +43 -0
- package/templates/postman/scripts/lib/api_coverage.py +1122 -0
- package/templates/postman/scripts/lib/cleanup-reports.sh +101 -0
- package/templates/postman/scripts/lib/cleanup-stryker.sh +44 -0
- package/templates/postman/scripts/lib/report_combined.py +527 -0
- package/templates/postman/scripts/lib/report_consolidated.py +363 -0
- package/templates/postman/scripts/lib/report_generator.py +121 -0
- package/templates/postman/scripts/lib/report_migration.py +156 -0
- package/templates/postman/scripts/lib/report_mutation.py +110 -0
- package/templates/postman/scripts/lib/report_unit.py +353 -0
- package/templates/postman/scripts/lib/report_utils.py +973 -0
- package/templates/postman/scripts/report-generators/generate-consolidated-report.sh +445 -0
- package/templates/postman/scripts/report-generators/java-api-coverage-matrix.sh +257 -0
- package/templates/postman/scripts/report-generators/mutation-report.sh +672 -0
- package/templates/postman/scripts/report-generators/node-api-coverage-matrix.sh +167 -0
- package/templates/postman/scripts/report-generators/stage-report-artifacts.sh +27 -0
- package/templates/postman/scripts/run-all.sh +452 -0
- package/templates/postman/scripts/runners/run-mutation-tests.sh +113 -0
- package/templates/postman/scripts/runners/run-tests-local.sh +936 -0
- package/templates/postman/scripts/runners/run-tests-staging.sh +741 -0
- package/templates/postman-node/README.md.ejs +26 -0
- package/templates/postman-node/collections/crud/01-bootstrap.json.ejs +34 -0
- package/templates/postman-node/config/local.json.ejs +46 -0
- package/templates/postman-node/config/staging.json.ejs +31 -0
- package/templates/postman-node/local.test.env.ejs +3 -0
- package/templates/postman-node/mocks/external.js +14 -0
- package/templates/postman-node/package.json.ejs +39 -0
- package/templates/postman-node/requirements.txt +1 -0
- package/templates/postman-node/scripts/database/cleanup-mysql.sh +12 -0
- package/templates/postman-node/scripts/database/run-migrations.js +29 -0
- package/templates/postman-node/scripts/database/start-mysql.sh +34 -0
- package/templates/postman-node/scripts/database/wait-for-mysql.sh +36 -0
- package/templates/postman-node/scripts/lib/api_coverage_node.py +1137 -0
- package/templates/postman-node/scripts/lib/fetch-jwt.sh +86 -0
- package/templates/postman-node/scripts/lib/run-newman.sh +104 -0
- package/templates/postman-node/scripts/lib/setup-database.sh +55 -0
- package/templates/postman-node/scripts/lib/start-app.sh +48 -0
- package/templates/postman-node/scripts/lib/utils.sh +114 -0
- package/templates/postman-node/scripts/report-generators/stage-report-artifacts.sh +26 -0
- package/templates/postman-node/scripts/run-all.sh +303 -0
- package/templates/postman-node/scripts/runners/run-tests.sh +123 -0
- package/templates/postman-node/scripts/setup-mocks.js.ejs +29 -0
- package/templates/postman-node/stryker.config.js.ejs +51 -0
- package/templates/rules/local-test-setup.mdc +420 -0
- package/templates/rules/testing-node.mdc +66 -0
- package/templates/rules/testing.mdc +248 -0
- package/templates/skills/_shared/postman-standards.md +380 -0
- package/templates/skills/enhance-test-pipeline/SKILL-java.md +483 -0
- package/templates/skills/enhance-test-pipeline/SKILL-node.md +431 -0
- package/templates/skills/enhance-test-pipeline/SKILL.md +9 -0
- package/templates/skills/review-test-suite/SKILL-java.md +137 -0
- package/templates/skills/review-test-suite/SKILL-node.md +78 -0
- package/templates/skills/review-test-suite/SKILL.md +9 -0
- package/templates/skills/run-test-suite/SKILL-java.md +186 -0
- package/templates/skills/run-test-suite/SKILL-node.md +191 -0
- package/templates/skills/run-test-suite/SKILL.md +9 -0
- package/templates/skills/setup-api-tests/SKILL-java.md +1094 -0
- package/templates/skills/setup-api-tests/SKILL-node.md +141 -0
- package/templates/skills/setup-api-tests/SKILL.md +9 -0
- package/templates/skills/setup-mutation-tests/SKILL-java.md +303 -0
- package/templates/skills/setup-mutation-tests/SKILL-node.md +408 -0
- package/templates/skills/setup-mutation-tests/SKILL.md +9 -0
- package/templates/skills/setup-test-pipeline/SKILL-java.md +454 -0
- package/templates/skills/setup-test-pipeline/SKILL-node.md +318 -0
- package/templates/skills/setup-test-pipeline/SKILL.md +9 -0
- package/templates/skills/write-api-tests/SKILL-java.md +115 -0
- package/templates/skills/write-api-tests/SKILL-node.md +83 -0
- package/templates/skills/write-api-tests/SKILL.md +9 -0
- package/templates/stryker.config.js +50 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Unified Test & Quality Report Runner (freshapps_api_node)
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# ./run-all.sh [OPTIONS]
|
|
7
|
+
#
|
|
8
|
+
# Options:
|
|
9
|
+
# --env {local|staging} Target environment for Postman tests (default: local)
|
|
10
|
+
# --skip-unit Skip unit tests (use existing results)
|
|
11
|
+
# --skip-mutation Skip mutation tests (use existing results)
|
|
12
|
+
# --skip-postman Skip Postman API tests (use existing results)
|
|
13
|
+
# --skip-coverage Skip API coverage matrix (use existing results)
|
|
14
|
+
# --skip-report Skip quality report generation
|
|
15
|
+
# --no-delay Skip delays between phases
|
|
16
|
+
# -h, --help Show this help message
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
GREEN='\033[0;32m'
|
|
21
|
+
RED='\033[0;31m'
|
|
22
|
+
YELLOW='\033[1;33m'
|
|
23
|
+
BLUE='\033[0;34m'
|
|
24
|
+
CYAN='\033[0;36m'
|
|
25
|
+
BOLD='\033[1m'
|
|
26
|
+
NC='\033[0m'
|
|
27
|
+
|
|
28
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
29
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
30
|
+
POSTMAN_DIR="$(dirname "$SCRIPT_DIR")"
|
|
31
|
+
# shellcheck source=lib/cleanup-stryker.sh
|
|
32
|
+
source "$SCRIPT_DIR/lib/cleanup-stryker.sh"
|
|
33
|
+
REPORTS_DIR="$POSTMAN_DIR/reports"
|
|
34
|
+
TIMESTAMP=$(date +"%Y%m%d-%H%M%S")
|
|
35
|
+
|
|
36
|
+
POSTMAN_ENV="${POSTMAN_ENV:-local}"
|
|
37
|
+
SKIP_UNIT=false
|
|
38
|
+
SKIP_MUTATION=false
|
|
39
|
+
SKIP_POSTMAN=false
|
|
40
|
+
SKIP_COVERAGE=false
|
|
41
|
+
SKIP_REPORT=false
|
|
42
|
+
SKIP_DELAY=false
|
|
43
|
+
|
|
44
|
+
UNIT_OK=false
|
|
45
|
+
MUTATION_OK=false
|
|
46
|
+
POSTMAN_OK=false
|
|
47
|
+
COVERAGE_OK=false
|
|
48
|
+
POSTMAN_RESULT=0
|
|
49
|
+
|
|
50
|
+
while [[ $# -gt 0 ]]; do
|
|
51
|
+
case $1 in
|
|
52
|
+
-h|--help) head -18 "$0" | tail -14; exit 0 ;;
|
|
53
|
+
--env) POSTMAN_ENV="$2"; shift 2 ;;
|
|
54
|
+
--skip-unit) SKIP_UNIT=true; shift ;;
|
|
55
|
+
--skip-mutation) SKIP_MUTATION=true; shift ;;
|
|
56
|
+
--skip-postman) SKIP_POSTMAN=true; shift ;;
|
|
57
|
+
--skip-coverage) SKIP_COVERAGE=true; shift ;;
|
|
58
|
+
--skip-report) SKIP_REPORT=true; shift ;;
|
|
59
|
+
--no-delay) SKIP_DELAY=true; shift ;;
|
|
60
|
+
*) echo -e "${RED}Unknown option: $1${NC}"; exit 1 ;;
|
|
61
|
+
esac
|
|
62
|
+
done
|
|
63
|
+
|
|
64
|
+
if [[ ! "$POSTMAN_ENV" =~ ^(local|staging)$ ]]; then
|
|
65
|
+
echo -e "${RED}Invalid environment: $POSTMAN_ENV${NC}"
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
cleanup() {
|
|
70
|
+
local pid_file="$POSTMAN_DIR/.app.pid"
|
|
71
|
+
if [ -f "$pid_file" ]; then
|
|
72
|
+
APP_PID=$(cat "$pid_file" 2>/dev/null || echo "")
|
|
73
|
+
if [ -n "$APP_PID" ] && ps -p "$APP_PID" > /dev/null 2>&1; then
|
|
74
|
+
echo -e "${YELLOW}Stopping application (PID $APP_PID)...${NC}"
|
|
75
|
+
kill "$APP_PID" 2>/dev/null || true
|
|
76
|
+
sleep 2
|
|
77
|
+
ps -p "$APP_PID" > /dev/null 2>&1 && kill -9 "$APP_PID" 2>/dev/null || true
|
|
78
|
+
fi
|
|
79
|
+
rm -f "$pid_file"
|
|
80
|
+
fi
|
|
81
|
+
cleanup_stryker "$PROJECT_ROOT"
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
trap cleanup EXIT
|
|
85
|
+
|
|
86
|
+
mkdir -p "$REPORTS_DIR"
|
|
87
|
+
|
|
88
|
+
echo -e "${YELLOW}Cleaning up old reports...${NC}"
|
|
89
|
+
_keep_latest() {
|
|
90
|
+
local pattern="$1" keep="${2:-3}"
|
|
91
|
+
# shellcheck disable=SC2012
|
|
92
|
+
ls -t $pattern 2>/dev/null | tail -n +$((keep + 1)) | xargs rm -f 2>/dev/null || true
|
|
93
|
+
}
|
|
94
|
+
_keep_latest "$REPORTS_DIR/quality-report-*.html" 3
|
|
95
|
+
if [ "$SKIP_POSTMAN" = false ]; then
|
|
96
|
+
# Remove only THIS environment's stale per-collection Newman HTML reports
|
|
97
|
+
# (they are about to be regenerated). Scoping the delete to the current env
|
|
98
|
+
# leaves the other env's reports — and the "View Details" links of its kept
|
|
99
|
+
# consolidated report — intact.
|
|
100
|
+
find "$REPORTS_DIR" -maxdepth 1 -name "test-${POSTMAN_ENV}-*.html" \
|
|
101
|
+
-delete 2>/dev/null || true
|
|
102
|
+
fi
|
|
103
|
+
if [ "$SKIP_POSTMAN" = false ]; then
|
|
104
|
+
_keep_latest "$REPORTS_DIR/consolidated-*.html" 3
|
|
105
|
+
_keep_latest "$REPORTS_DIR/consolidated-*.json" 3
|
|
106
|
+
rm -rf "$REPORTS_DIR"/json 2>/dev/null || true
|
|
107
|
+
fi
|
|
108
|
+
if [ "$SKIP_COVERAGE" = false ]; then
|
|
109
|
+
_keep_latest "$REPORTS_DIR/api-coverage-matrix-*.html" 3
|
|
110
|
+
_keep_latest "$REPORTS_DIR/api-coverage-matrix-*.json" 3
|
|
111
|
+
fi
|
|
112
|
+
echo -e "${GREEN}Old reports cleaned${NC}"
|
|
113
|
+
|
|
114
|
+
echo -e "${YELLOW}Cleaning up stale Stryker processes and temp files...${NC}"
|
|
115
|
+
cleanup_stryker "$PROJECT_ROOT"
|
|
116
|
+
echo -e "${GREEN}Stryker cleanup done${NC}"
|
|
117
|
+
echo ""
|
|
118
|
+
|
|
119
|
+
[ -t 1 ] && clear || true
|
|
120
|
+
echo -e "${BOLD}${BLUE}UNIFIED TEST & QUALITY REPORT RUNNER${NC}"
|
|
121
|
+
echo ""
|
|
122
|
+
if [ "$SKIP_DELAY" = "false" ]; then
|
|
123
|
+
echo -e "${YELLOW}Starting in 2 seconds... (Ctrl+C to cancel)${NC}"
|
|
124
|
+
sleep 2
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
MOCHA_XML="$PROJECT_ROOT/coverage/unit-tests/test-results.xml"
|
|
128
|
+
LCOV="$PROJECT_ROOT/coverage/unit-tests/lcov.info"
|
|
129
|
+
STRYKER_JSON="$PROJECT_ROOT/coverage/mutation/mutation-report.json"
|
|
130
|
+
|
|
131
|
+
# Phase 1: Unit tests
|
|
132
|
+
echo ""
|
|
133
|
+
echo -e "${CYAN}Phase 1: Unit Tests + nyc Coverage${NC}"
|
|
134
|
+
if [ "$SKIP_UNIT" = false ]; then
|
|
135
|
+
cd "$PROJECT_ROOT"
|
|
136
|
+
if yarn --ignore-engines unit-tests; then
|
|
137
|
+
echo -e "${GREEN}Unit tests completed${NC}"
|
|
138
|
+
else
|
|
139
|
+
echo -e "${RED}Unit tests had failures (continuing)${NC}"
|
|
140
|
+
fi
|
|
141
|
+
UNIT_OK=true
|
|
142
|
+
else
|
|
143
|
+
echo -e "${YELLOW}Skipping unit tests${NC}"
|
|
144
|
+
[ -f "$MOCHA_XML" ] || [ -f "$LCOV" ] && UNIT_OK=true
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
# Phase 2: Mutation — fast mode (changed files vs origin/master); Jenkins uses mutation-tests:full
|
|
148
|
+
echo ""
|
|
149
|
+
echo -e "${CYAN}Phase 2: Stryker Mutation Testing (changed files vs origin/master)${NC}"
|
|
150
|
+
if [ "$SKIP_MUTATION" = false ]; then
|
|
151
|
+
if [ "$SKIP_UNIT" = true ] && [ ! -d "$PROJECT_ROOT/.nyc_output" ]; then
|
|
152
|
+
echo -e "${YELLOW}Warning: .nyc_output missing; perTest coverage may fail. Run unit tests first.${NC}"
|
|
153
|
+
fi
|
|
154
|
+
cd "$PROJECT_ROOT"
|
|
155
|
+
if yarn --ignore-engines mutation-tests; then
|
|
156
|
+
MUTATION_OK=true
|
|
157
|
+
echo -e "${GREEN}Mutation tests completed${NC}"
|
|
158
|
+
else
|
|
159
|
+
echo -e "${RED}Mutation tests failed (continuing)${NC}"
|
|
160
|
+
fi
|
|
161
|
+
else
|
|
162
|
+
echo -e "${YELLOW}Skipping mutation tests${NC}"
|
|
163
|
+
[ -f "$STRYKER_JSON" ] && MUTATION_OK=true
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
# Phase 3: Postman
|
|
167
|
+
echo ""
|
|
168
|
+
echo -e "${CYAN}Phase 3: Postman API Tests ($POSTMAN_ENV)${NC}"
|
|
169
|
+
POSTMAN_PASSED=0
|
|
170
|
+
POSTMAN_FAILED=0
|
|
171
|
+
CONSOLIDATED_JSON=""
|
|
172
|
+
|
|
173
|
+
if [ "$SKIP_POSTMAN" = false ]; then
|
|
174
|
+
set +e
|
|
175
|
+
"$SCRIPT_DIR/runners/run-tests.sh" "$POSTMAN_ENV"
|
|
176
|
+
POSTMAN_RESULT=$?
|
|
177
|
+
set -e
|
|
178
|
+
CONSOLIDATED_JSON=$(ls -t "$REPORTS_DIR"/consolidated-*.json 2>/dev/null | head -1 || true)
|
|
179
|
+
if [ -n "$CONSOLIDATED_JSON" ] && [ -f "$CONSOLIDATED_JSON" ]; then
|
|
180
|
+
POSTMAN_PASSED=$(jq '.summary.collections.passed // 0' "$CONSOLIDATED_JSON" 2>/dev/null || echo "0")
|
|
181
|
+
POSTMAN_FAILED=$(jq '.summary.collections.failed // 0' "$CONSOLIDATED_JSON" 2>/dev/null || echo "0")
|
|
182
|
+
POSTMAN_OK=true
|
|
183
|
+
fi
|
|
184
|
+
else
|
|
185
|
+
echo -e "${YELLOW}Skipping Postman tests${NC}"
|
|
186
|
+
CONSOLIDATED_JSON=$(ls -t "$REPORTS_DIR"/consolidated-*.json 2>/dev/null | head -1 || true)
|
|
187
|
+
[ -n "$CONSOLIDATED_JSON" ] && POSTMAN_OK=true
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
# Phase 4: API coverage
|
|
191
|
+
echo ""
|
|
192
|
+
echo -e "${CYAN}Phase 4: API Coverage Matrix${NC}"
|
|
193
|
+
API_COVERAGE_JSON=""
|
|
194
|
+
if [ "$SKIP_COVERAGE" = false ]; then
|
|
195
|
+
if "$SCRIPT_DIR/report-generators/node-api-coverage-matrix.sh" "$PROJECT_ROOT/src/controllers" "$POSTMAN_DIR"; then
|
|
196
|
+
COVERAGE_OK=true
|
|
197
|
+
echo -e "${GREEN}API coverage matrix generated${NC}"
|
|
198
|
+
else
|
|
199
|
+
echo -e "${RED}API coverage matrix failed${NC}"
|
|
200
|
+
fi
|
|
201
|
+
else
|
|
202
|
+
echo -e "${YELLOW}Skipping API coverage matrix${NC}"
|
|
203
|
+
ls "$REPORTS_DIR"/api-coverage-matrix-*.json 1>/dev/null 2>&1 && COVERAGE_OK=true
|
|
204
|
+
fi
|
|
205
|
+
|
|
206
|
+
COVERAGE_JSON_FILE=$(ls -t "$REPORTS_DIR"/api-coverage-matrix-*.json 2>/dev/null | head -1 || true)
|
|
207
|
+
if [ -n "$COVERAGE_JSON_FILE" ] && [ -f "$COVERAGE_JSON_FILE" ]; then
|
|
208
|
+
API_COVERAGE_JSON=$(cat "$COVERAGE_JSON_FILE")
|
|
209
|
+
fi
|
|
210
|
+
|
|
211
|
+
# Phase 5: Combined report
|
|
212
|
+
echo ""
|
|
213
|
+
echo -e "${CYAN}Phase 5: Combined Quality Report${NC}"
|
|
214
|
+
|
|
215
|
+
# Install Python dependencies if needed (defusedxml for XXE protection)
|
|
216
|
+
if [ "$SKIP_REPORT" = false ] || [ "$SKIP_COVERAGE" = false ]; then
|
|
217
|
+
echo -e "${YELLOW}Installing Python dependencies...${NC}"
|
|
218
|
+
if [ -f "$PROJECT_ROOT/requirements.txt" ]; then
|
|
219
|
+
python3 -m pip install --upgrade pip >/dev/null 2>&1
|
|
220
|
+
python3 -m pip install -r "$PROJECT_ROOT/requirements.txt" >/dev/null 2>&1 || {
|
|
221
|
+
echo -e "${RED}Failed to install Python dependencies${NC}"
|
|
222
|
+
exit 1
|
|
223
|
+
}
|
|
224
|
+
echo -e "${GREEN}Python dependencies installed${NC}"
|
|
225
|
+
fi
|
|
226
|
+
fi
|
|
227
|
+
|
|
228
|
+
if [ "$SKIP_REPORT" = false ]; then
|
|
229
|
+
POSTMAN_TOTAL_ASSERTIONS=0
|
|
230
|
+
POSTMAN_PASSED_ASSERTIONS=0
|
|
231
|
+
POSTMAN_FAILED_ASSERTIONS=0
|
|
232
|
+
POSTMAN_TOTAL_REQUESTS=0
|
|
233
|
+
POSTMAN_DURATION="0"
|
|
234
|
+
|
|
235
|
+
CONSOLIDATED_JSON="${CONSOLIDATED_JSON:-$(ls -t "$REPORTS_DIR"/consolidated-*.json 2>/dev/null | head -1 || true)}"
|
|
236
|
+
if [ -n "$CONSOLIDATED_JSON" ] && [ -f "$CONSOLIDATED_JSON" ]; then
|
|
237
|
+
POSTMAN_TOTAL_ASSERTIONS=$(jq '.summary.assertions.total // 0' "$CONSOLIDATED_JSON" 2>/dev/null || echo "0")
|
|
238
|
+
POSTMAN_FAILED_ASSERTIONS=$(jq '.summary.assertions.failed // 0' "$CONSOLIDATED_JSON" 2>/dev/null || echo "0")
|
|
239
|
+
POSTMAN_TOTAL_REQUESTS=$(jq '.summary.requests.total // 0' "$CONSOLIDATED_JSON" 2>/dev/null || echo "0")
|
|
240
|
+
POSTMAN_TOTAL_DURATION=$(jq '.summary.duration_ms // 0' "$CONSOLIDATED_JSON" 2>/dev/null || echo "0")
|
|
241
|
+
POSTMAN_PASSED_ASSERTIONS=$((POSTMAN_TOTAL_ASSERTIONS - POSTMAN_FAILED_ASSERTIONS))
|
|
242
|
+
POSTMAN_DURATION=$(echo "scale=2; $POSTMAN_TOTAL_DURATION / 1000" | bc 2>/dev/null || echo "0")
|
|
243
|
+
fi
|
|
244
|
+
|
|
245
|
+
COMBINED_OUTPUT="$REPORTS_DIR/quality-report-$TIMESTAMP.html"
|
|
246
|
+
|
|
247
|
+
"$SCRIPT_DIR/report-generators/stage-report-artifacts.sh" "$PROJECT_ROOT" "$REPORTS_DIR"
|
|
248
|
+
|
|
249
|
+
REPORT_ARGS=(combined "$COMBINED_OUTPUT" --logo "API Service")
|
|
250
|
+
|
|
251
|
+
[ -f "$MOCHA_XML" ] && REPORT_ARGS+=(--mocha-xml "$MOCHA_XML")
|
|
252
|
+
[ -f "$LCOV" ] && REPORT_ARGS+=(--lcov "$LCOV")
|
|
253
|
+
[ -f "$STRYKER_JSON" ] && REPORT_ARGS+=(--stryker-json "$STRYKER_JSON")
|
|
254
|
+
|
|
255
|
+
REPORT_ARGS+=(--postman-assertions-total "$POSTMAN_TOTAL_ASSERTIONS")
|
|
256
|
+
REPORT_ARGS+=(--postman-assertions-passed "$POSTMAN_PASSED_ASSERTIONS")
|
|
257
|
+
REPORT_ARGS+=(--postman-assertions-failed "$POSTMAN_FAILED_ASSERTIONS")
|
|
258
|
+
REPORT_ARGS+=(--postman-requests "$POSTMAN_TOTAL_REQUESTS")
|
|
259
|
+
REPORT_ARGS+=(--postman-duration "$POSTMAN_DURATION")
|
|
260
|
+
REPORT_ARGS+=(--postman-collections-passed "$POSTMAN_PASSED")
|
|
261
|
+
REPORT_ARGS+=(--postman-collections-failed "$POSTMAN_FAILED")
|
|
262
|
+
|
|
263
|
+
TEMP_COVERAGE=""
|
|
264
|
+
if [ -n "$API_COVERAGE_JSON" ]; then
|
|
265
|
+
TEMP_COVERAGE="/tmp/api-coverage-data-$$.json"
|
|
266
|
+
# Ensure temp file is cleaned up on exit
|
|
267
|
+
trap 'rm -f "$TEMP_COVERAGE" 2>/dev/null || true' EXIT
|
|
268
|
+
echo "$API_COVERAGE_JSON" > "$TEMP_COVERAGE"
|
|
269
|
+
REPORT_ARGS+=(--api-coverage-file "$TEMP_COVERAGE")
|
|
270
|
+
fi
|
|
271
|
+
|
|
272
|
+
API_COVERAGE_HTML=$(ls -t "$REPORTS_DIR"/api-coverage-matrix-*.html 2>/dev/null | head -1 || true)
|
|
273
|
+
[ -n "$API_COVERAGE_HTML" ] && REPORT_ARGS+=(--api-coverage-html "$API_COVERAGE_HTML")
|
|
274
|
+
|
|
275
|
+
# Always (re)generate the consolidated HTML for THIS run's timestamp so the
|
|
276
|
+
# combined report never links to a stale consolidated whose per-collection
|
|
277
|
+
# detail files have been cleaned up. Fall back to the newest only if this run
|
|
278
|
+
# produced no consolidated JSON to render.
|
|
279
|
+
POSTMAN_CONSOLIDATED_HTML="$REPORTS_DIR/consolidated-${POSTMAN_ENV}-${TIMESTAMP}.html"
|
|
280
|
+
CONSOLIDATED_JSON_THIS_RUN="$REPORTS_DIR/consolidated-${POSTMAN_ENV}-${TIMESTAMP}.json"
|
|
281
|
+
if [ ! -f "$POSTMAN_CONSOLIDATED_HTML" ] && [ -f "$CONSOLIDATED_JSON_THIS_RUN" ]; then
|
|
282
|
+
"$SCRIPT_DIR/report-generators/generate-consolidated-report.sh" "$POSTMAN_ENV" "$TIMESTAMP" "$REPORTS_DIR" "$POSTMAN_PASSED" "$POSTMAN_FAILED" 0 >/dev/null 2>&1 || true
|
|
283
|
+
fi
|
|
284
|
+
if [ ! -f "$POSTMAN_CONSOLIDATED_HTML" ]; then
|
|
285
|
+
POSTMAN_CONSOLIDATED_HTML=$(ls -t "$REPORTS_DIR"/consolidated-*.html 2>/dev/null | head -1 || true)
|
|
286
|
+
fi
|
|
287
|
+
[ -n "$POSTMAN_CONSOLIDATED_HTML" ] && [ -f "$POSTMAN_CONSOLIDATED_HTML" ] && REPORT_ARGS+=(--postman-consolidated-html "$POSTMAN_CONSOLIDATED_HTML")
|
|
288
|
+
|
|
289
|
+
python3 "$SCRIPT_DIR/lib/report_generator.py" "${REPORT_ARGS[@]}"
|
|
290
|
+
[ -n "$TEMP_COVERAGE" ] && rm -f "$TEMP_COVERAGE"
|
|
291
|
+
|
|
292
|
+
if [ -f "$COMBINED_OUTPUT" ]; then
|
|
293
|
+
echo -e "${GREEN}Combined report: $COMBINED_OUTPUT${NC}"
|
|
294
|
+
[[ "$OSTYPE" == darwin* ]] && open "$COMBINED_OUTPUT" 2>/dev/null || true
|
|
295
|
+
else
|
|
296
|
+
echo -e "${RED}Failed to generate combined report${NC}"
|
|
297
|
+
exit 1
|
|
298
|
+
fi
|
|
299
|
+
else
|
|
300
|
+
echo -e "${YELLOW}Skipping report generation${NC}"
|
|
301
|
+
fi
|
|
302
|
+
|
|
303
|
+
exit $POSTMAN_RESULT
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# =============================================================================
|
|
3
|
+
# Unified Test Runner - Config-Driven
|
|
4
|
+
# =============================================================================
|
|
5
|
+
# Runs integration tests for any environment (local, dev, staging)
|
|
6
|
+
# Configuration determines what gets set up and how authentication works
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# ./run-tests.sh [environment]
|
|
10
|
+
#
|
|
11
|
+
# Examples:
|
|
12
|
+
# ./run-tests.sh local # Local with Podman MySQL
|
|
13
|
+
# ./run-tests.sh dev # Dev with AWS auth
|
|
14
|
+
# ./run-tests.sh staging # Staging with AWS auth
|
|
15
|
+
#
|
|
16
|
+
# Environment Variables (optional overrides):
|
|
17
|
+
# AWS_PROFILE=profile # Override AWS profile from config
|
|
18
|
+
# =============================================================================
|
|
19
|
+
|
|
20
|
+
set -euo pipefail
|
|
21
|
+
|
|
22
|
+
RUNNERS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
23
|
+
SCRIPT_DIR="$(cd "$RUNNERS_DIR/.." && pwd)"
|
|
24
|
+
POSTMAN_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
25
|
+
PROJECT_ROOT="$(cd "$POSTMAN_DIR/.." && pwd)"
|
|
26
|
+
|
|
27
|
+
# Source utilities
|
|
28
|
+
source "$SCRIPT_DIR/lib/utils.sh"
|
|
29
|
+
|
|
30
|
+
# Parse arguments
|
|
31
|
+
ENVIRONMENT="${1:-local}"
|
|
32
|
+
CONFIG_FILE="$POSTMAN_DIR/config/${ENVIRONMENT}.json"
|
|
33
|
+
|
|
34
|
+
# Validate environment
|
|
35
|
+
if [ ! -f "$CONFIG_FILE" ]; then
|
|
36
|
+
error "Configuration not found: $CONFIG_FILE"
|
|
37
|
+
echo ""
|
|
38
|
+
echo "Available environments:"
|
|
39
|
+
ls -1 "$POSTMAN_DIR/config"/*.json 2>/dev/null | xargs -n1 basename | sed 's/.json$//' | sed 's/^/ - /' || echo " (none found)"
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
log_header "Freshapps API Integration Tests"
|
|
44
|
+
log_info "Environment: ${ENVIRONMENT}"
|
|
45
|
+
log_info "Config: $(basename $CONFIG_FILE)"
|
|
46
|
+
echo ""
|
|
47
|
+
|
|
48
|
+
# Load configuration
|
|
49
|
+
API_URL=$(jq -r '.api_url' "$CONFIG_FILE")
|
|
50
|
+
AUTH_TYPE=$(jq -r '.auth.type' "$CONFIG_FILE")
|
|
51
|
+
|
|
52
|
+
# Setup flags (with env var overrides)
|
|
53
|
+
SETUP_DB=$(jq -r '.setup.database.enabled' "$CONFIG_FILE")
|
|
54
|
+
if [ "${SKIP_DB:-}" = "true" ]; then
|
|
55
|
+
SETUP_DB="false"
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
SETUP_APP=$(jq -r '.setup.app.enabled' "$CONFIG_FILE")
|
|
59
|
+
if [ "${SKIP_APP:-}" = "true" ]; then
|
|
60
|
+
SETUP_APP="false"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
SETUP_MIGRATIONS=$(jq -r '.setup.migrations.enabled' "$CONFIG_FILE")
|
|
64
|
+
|
|
65
|
+
CLEANUP_ENABLED="true"
|
|
66
|
+
if [ "${SKIP_CLEANUP:-}" = "true" ]; then
|
|
67
|
+
CLEANUP_ENABLED="false"
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
log_info "API URL: ${API_URL}"
|
|
71
|
+
log_info "Auth Type: ${AUTH_TYPE}"
|
|
72
|
+
log_info "Setup Database: ${SETUP_DB}"
|
|
73
|
+
log_info "Setup App: ${SETUP_APP}"
|
|
74
|
+
echo ""
|
|
75
|
+
|
|
76
|
+
# Trap cleanup
|
|
77
|
+
trap cleanup EXIT
|
|
78
|
+
|
|
79
|
+
# Step 1: Database Setup
|
|
80
|
+
if [ "$SETUP_DB" = "true" ]; then
|
|
81
|
+
log_step "1" "Setting up database"
|
|
82
|
+
source "$SCRIPT_DIR/lib/setup-database.sh"
|
|
83
|
+
setup_database "$CONFIG_FILE"
|
|
84
|
+
echo ""
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# Step 2: Run Migrations
|
|
88
|
+
if [ "$SETUP_MIGRATIONS" = "true" ]; then
|
|
89
|
+
log_step "2" "Running migrations"
|
|
90
|
+
source "$SCRIPT_DIR/lib/setup-database.sh"
|
|
91
|
+
run_migrations "$CONFIG_FILE"
|
|
92
|
+
echo ""
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
# Step 3: Start Application
|
|
96
|
+
if [ "$SETUP_APP" = "true" ]; then
|
|
97
|
+
log_step "3" "Starting application"
|
|
98
|
+
source "$SCRIPT_DIR/lib/start-app.sh"
|
|
99
|
+
start_application "$CONFIG_FILE"
|
|
100
|
+
echo ""
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
# Step 4: Generate JWT Token
|
|
104
|
+
log_step "4" "Generating authentication token"
|
|
105
|
+
source "$SCRIPT_DIR/lib/fetch-jwt.sh"
|
|
106
|
+
JWT_TOKEN=$(fetch_jwt "$CONFIG_FILE")
|
|
107
|
+
log_success "Token generated"
|
|
108
|
+
echo ""
|
|
109
|
+
|
|
110
|
+
# Step 5: Update Environment File
|
|
111
|
+
log_step "5" "Updating Postman environment"
|
|
112
|
+
update_postman_environment "$ENVIRONMENT" "$JWT_TOKEN" "$API_URL" "$CONFIG_FILE"
|
|
113
|
+
echo ""
|
|
114
|
+
|
|
115
|
+
# Step 6: Run Tests
|
|
116
|
+
log_step "6" "Running Newman tests"
|
|
117
|
+
source "$SCRIPT_DIR/lib/run-newman.sh"
|
|
118
|
+
run_newman_tests "$ENVIRONMENT"
|
|
119
|
+
echo ""
|
|
120
|
+
|
|
121
|
+
# Cleanup handled by trap
|
|
122
|
+
echo ""
|
|
123
|
+
log_header "Tests Completed Successfully!"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* nock mock orchestrator for <%= serviceName %> integration tests.
|
|
5
|
+
* Load from your app entry when NODE_ENV=integration-tests:
|
|
6
|
+
*
|
|
7
|
+
* if (process.env.NODE_ENV === 'integration-tests') {
|
|
8
|
+
* require('../postman/scripts/setup-mocks').setupMocks();
|
|
9
|
+
* }
|
|
10
|
+
*/
|
|
11
|
+
const nock = require('nock');
|
|
12
|
+
const { setupExternalMocks } = require('../mocks/external');
|
|
13
|
+
|
|
14
|
+
function setupMocks() {
|
|
15
|
+
nock.disableNetConnect();
|
|
16
|
+
nock.enableNetConnect(/(localhost|127\.0\.0\.1)/);
|
|
17
|
+
|
|
18
|
+
setupExternalMocks(nock);
|
|
19
|
+
|
|
20
|
+
// Add service-specific mocks in postman/mocks/ and require them here.
|
|
21
|
+
console.log('[setup-mocks] External HTTP mocks enabled');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function teardownMocks() {
|
|
25
|
+
nock.cleanAll();
|
|
26
|
+
nock.enableNetConnect();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = { setupMocks, teardownMocks };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Stryker mutation testing for <%= serviceName %>.
|
|
5
|
+
* Customize mutate paths after inspecting your src/ layout.
|
|
6
|
+
* Exclude external-service wrappers (HTTP clients, AWS SDK, etc.).
|
|
7
|
+
*/
|
|
8
|
+
module.exports = {
|
|
9
|
+
packageManager: 'yarn',
|
|
10
|
+
testRunner: 'mocha',
|
|
11
|
+
reporters: ['html', 'json', 'clear-text', 'progress'],
|
|
12
|
+
htmlReporter: {
|
|
13
|
+
fileName: 'coverage/mutation/index.html',
|
|
14
|
+
},
|
|
15
|
+
jsonReporter: {
|
|
16
|
+
fileName: 'coverage/mutation/mutation-report.json',
|
|
17
|
+
},
|
|
18
|
+
// IMPORTANT: List only business-logic folders — never `src/**/*.js` (Stryker will run for hours).
|
|
19
|
+
// Run `/setup-mutation-tests` to audit src/ and set paths file-by-file.
|
|
20
|
+
mutate: [
|
|
21
|
+
'src/actions/**/*.js',
|
|
22
|
+
'src/services/**/*.js',
|
|
23
|
+
'src/serializers/**/*.js',
|
|
24
|
+
'src/middlewares/**/*.js',
|
|
25
|
+
'!src/**/index.js',
|
|
26
|
+
'!src/**/app.js',
|
|
27
|
+
'!src/controllers/**',
|
|
28
|
+
'!src/routes/**',
|
|
29
|
+
'!src/config/**',
|
|
30
|
+
'!src/constants/**',
|
|
31
|
+
'!src/migrations/**',
|
|
32
|
+
'!src/seeders/**',
|
|
33
|
+
'!src/models/**',
|
|
34
|
+
],
|
|
35
|
+
coverageAnalysis: 'perTest',
|
|
36
|
+
concurrency: 4,
|
|
37
|
+
incremental: true,
|
|
38
|
+
incrementalFile: 'coverage/mutation/stryker-incremental.json',
|
|
39
|
+
ignorePatterns: ['postman/**', 'coverage/**', 'node_modules/**'],
|
|
40
|
+
mochaOpts: {
|
|
41
|
+
files: 'test/unit/**/*.test.js',
|
|
42
|
+
require: ['test/unit/setup.js'],
|
|
43
|
+
timeout: 10000,
|
|
44
|
+
},
|
|
45
|
+
thresholds: {
|
|
46
|
+
high: 80,
|
|
47
|
+
low: 60,
|
|
48
|
+
break: 0,
|
|
49
|
+
},
|
|
50
|
+
tempDirName: 'coverage/mutation/.stryker-tmp',
|
|
51
|
+
};
|