Skip to content

Commit 1998f79

Browse files
feat: shared site testing script and move to linkinator (#97)
* feat: shared site testing script and move to linkinator Relates-to: keymanapp/keyman.com#788 Test-bot: skip * chore: address review comments Co-authored-by: Eberhard Beilharz <ermshiperete@users.noreply.github.com> --------- Co-authored-by: Eberhard Beilharz <ermshiperete@users.noreply.github.com>
1 parent d28bb1e commit 1998f79

3 files changed

Lines changed: 153 additions & 2 deletions

File tree

.bootstrap-registry

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ KeymanHosts.php
2020
KeymanSentry.php
2121
KeymanVersion.php
2222
MarkdownHost.php
23+
tests.inc.sh

_common/docker.inc.sh

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
# Common docker functions.
1+
# shellcheck shell=bash
2+
#
3+
# Keyman is copyright (C) SIL Global. MIT License.
4+
#
5+
# Common docker functions for (generally PHP-based) containers
6+
#
7+
8+
source _common/tests.inc.sh
29

310
function get_docker_image_id() {
411
local IMAGE_NAME=$1
@@ -153,4 +160,53 @@ function start_docker_container() {
153160
fi
154161

155162
builder_echo green "Listening on http://$HOST:$PORT"
156-
}
163+
}
164+
165+
#
166+
# Test PHP site in a docker container
167+
#
168+
# Parameters:
169+
# 1: CONTAINER_DESC desc of container to test
170+
# 2: CONTAINER_PORT localhost http port for container
171+
# 3: TEST_PATH path to start link check at, under http://localhost:CONTAINER_PORT
172+
# 4..: SKIP_PATHS paths to skip crawling in link check, optional
173+
#
174+
# Builder options --no-unit-test, --no-lint, --no-link-check are honoured
175+
#
176+
function test_docker_container() {
177+
local CONTAINER_DESC="$1"
178+
local CONTAINER_PORT="$2"
179+
local TEST_PATH="$3"
180+
shift 3
181+
local SKIP_PATHS=("$@")
182+
183+
local LINK_RESULT=0
184+
echo "TIER_TEST" > tier.txt
185+
186+
# Similar pattern in ci.yml on sites
187+
188+
do_test_record_start_time
189+
190+
if ! builder_has_option --no-unit-test; then
191+
builder_echo blue "---- PHP unit tests"
192+
do_test_unit_tests "${CONTAINER_DESC}"
193+
fi
194+
195+
if ! builder_has_option --no-lint; then
196+
builder_echo blue "---- Lint PHP files"
197+
do_test_lint "${CONTAINER_DESC}"
198+
fi
199+
200+
if ! builder_has_option --no-link-check; then
201+
builder_echo blue "---- Testing links"
202+
203+
do_test_links "http://localhost:${CONTAINER_PORT}" "$TEST_PATH" "${SKIP_PATHS[@]}" || LINK_RESULT=$?
204+
builder_echo blue "Done checking links; linkinator exit code: ${LINK_RESULT}"
205+
do_test_print_link_report
206+
207+
do_test_print_container_error_logs "${CONTAINER_DESC}"
208+
fi
209+
210+
rm tier.txt
211+
return "$LINK_RESULT"
212+
}

_common/tests.inc.sh

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# shellcheck shell=bash
2+
#
3+
# Keyman is copyright (C) SIL Global. MIT License.
4+
#
5+
# Shared test functions for PHP lint, unit test, and general broken link checks
6+
#
7+
8+
# Record the start time for unit tests for later log review
9+
function do_test_record_start_time() {
10+
TEST_START_TIME=$(date -Is -u)
11+
}
12+
13+
# Run unit tests through phpunit
14+
#
15+
# Parameters
16+
# 1: CONTAINER container_desc to run on
17+
#
18+
function do_test_unit_tests() {
19+
local CONTAINER="$1"
20+
docker exec "${CONTAINER}" sh -c "vendor/bin/phpunit --testdox ${builder_extra_params[*]}"
21+
}
22+
23+
# Lint .php files for obvious errors
24+
#
25+
# Parameters
26+
# 1: CONTAINER container_desc to run on
27+
#
28+
function do_test_lint() {
29+
local CONTAINER="$1"
30+
docker exec "${CONTAINER}" sh -c "find . -name '*.php' | grep -v '/vendor/' | xargs -n 1 -d '\\n' php -l"
31+
}
32+
33+
## Check links on live local server using linkinator
34+
#
35+
# Parameters
36+
# 1: baseURL the top level URL for the site
37+
# 2: testPath path under baseURL to start testing, e.g. /
38+
# 3[,4..]: skipPaths list of paths (under baseURL) to skip crawling, optional
39+
#
40+
function do_test_links() {
41+
local baseURL="$1"
42+
local testPath="$2"
43+
shift 2
44+
local skipPaths=("$@")
45+
local skip skipParams=()
46+
47+
for skip in "${skipPaths[@]}"; do
48+
skipParams+=(--skip "^${baseURL}${skip}")
49+
done
50+
51+
npx https://github.com/keymanapp/linkinator \
52+
"${baseURL}${testPath}" \
53+
--clean-urls \
54+
--concurrency 50 \
55+
--format json \
56+
--output-filename linkinator-results.json \
57+
--skip "^(?!${baseURL})" \
58+
"${skipParams[@]}" \
59+
--recurse \
60+
--redirects verify \
61+
--retry-errors \
62+
--root-path "${baseURL}"
63+
}
64+
65+
# Print summary of results from linkinator
66+
function do_test_print_link_report() {
67+
echo ----------------------------------------------------------------------
68+
echo Link check summary
69+
echo ----------------------------------------------------------------------
70+
# Emit full JSON detail for broken links (may not be necessary)
71+
jq '.links[] | select(.state != "OK")' < linkinator-results.json
72+
echo
73+
echo
74+
# Emit a summary report
75+
jq -r '.links[] | select(.state != "OK") | "\(.state)[\(.status)]: \(.parent) --> \(.url)"' < linkinator-results.json
76+
}
77+
78+
# Scan logs recorded on container since start of tests to find any reported PHP
79+
# errors (note, depends on '[php#:xxxx]' marker string, where # = 7 for PHP7, omitted for PHP8)
80+
#
81+
# Parameters
82+
# 1: CONTAINER container_desc to run on
83+
#
84+
function do_test_print_container_error_logs() {
85+
local CONTAINER="$1"
86+
if docker container logs "${CONTAINER}" --since "${TEST_START_TIME}" 2>&1 | grep -qP '\[php7?:(error|warn|notice)\]'; then
87+
echo 'PHP reported errors or warnings:'
88+
docker container logs "${CONTAINER}" --since "${TEST_START_TIME}" 2>&1 | grep -P '\[php7?:(error|warn|notice)\]'
89+
return 1
90+
else
91+
echo 'No PHP errors found'
92+
return 0
93+
fi
94+
}

0 commit comments

Comments
 (0)