Skip to content

Commit b6bcc8e

Browse files
committed
Merge branch 'tests-revamp'
2 parents cab65b1 + d7a9db9 commit b6bcc8e

File tree

7 files changed

+283
-46
lines changed

7 files changed

+283
-46
lines changed

.github/workflows/tests.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ name: tests
22
on:
33
pull_request:
44
push:
5-
branches: [ main ]
65

76
schedule:
87
- cron: '00 07 * * *'

kickstart/common/web/themes/custom/.gitkeep

Whitespace-only changes.

tests/required_addons.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Required addons that should be installed after Aljibe Assistant run
2+
# Format: addon short name # comment explaining why it is required (DO NOT use single quotes "'")
3+
4+
adminer # Adminer database management tool
5+
aljibe # Main add-on
6+
aljibe-assistant # Aljibe Assistant for guided setup and configuration
7+
backstopjs # BackstopJS visual regression testing tool
8+
mkdocs # MkDocs documentation
9+
newman # Newman Postman collection runner
10+
pa11y # Pa11y accessibility testing tool
11+
selenium # Selenium for Behat testing
12+
unlighthouse # Unlightouse accessibility and performance testing tool

tests/required_files.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Required files after Aljibe installation
2+
# Format: file_path # comment explaining why it is required (DO NOT use single quotes "'")
3+
4+
grumphp.yml # GrumPHP configuration for code quality checks on git commits
5+
phpstan.neon # PHPStan static analysis configuration
6+
phpunit.xml # PHPUnit testing framework configuration
7+
composer.json # Composer dependency management and project metadata
8+
composer.lock # Composer lock file for consistent dependency versions
9+
drush/drush.yml # Drush configuration file for command-line Drupal management

tests/required_folders.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Required folders after Aljibe installation
2+
# Format: folder_path # comment explaining why it is required (DO NOT use single quotes "'")
3+
4+
backups # Storage for manual backups
5+
config # Drupal configuration files
6+
config/default # Default Drupal configuration sync directory
7+
config/envs # Environment-specific configuration overrides
8+
config/envs/local # Local environment configuration overrides
9+
drush # Drush commands and configuration
10+
drush/Commands # Custom Drush commands
11+
drush/sites # Drush site aliases
12+
patches # Composer patches for dependencies
13+
private-files # Drupal private files placed out of docroot
14+
recipes # Drupal recipes specific for this project
15+
scripts # Projects scripts and automation tools
16+
tests # Automated tests
17+
web # Drupal web root (docroot)
18+
web/core # Drupal core files
19+
web/modules/custom # Custom Drupal modules
20+
web/themes/custom # Custom Drupal themes
21+
web/sites/default # Default Drupal site files

tests/required_symlinks.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Required symlinks after Aljibe installation
2+
# Format: symlink_path # comment explaining why it is required (DO NOT use single quotes "'")
3+
4+
docroot # Symlink to Drupal web root for compatibility with tools and setups that expect docroot
5+
public_html # Symlink to Drupal web root for hosting environments

tests/test.bats

Lines changed: 236 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,271 @@
11
#!/bin/bash
22

3+
4+
# Standard DDEV add-on setup code taken from official DDEV add-ons.
35
setup() {
46
set -eu -o pipefail
5-
export DIR="$( cd "$( dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )/.."
6-
export TESTDIR=~/tmp/test-addon-aljibe
7-
mkdir -p "$TESTDIR"
8-
export PROJNAME=test-addon-aljibe
9-
export DDEV_NON_INTERACTIVE=true
10-
ddev delete -Oy "$PROJNAME" >/dev/null 2>&1 || true
11-
cd "$TESTDIR"
12-
ddev config --project-name="$PROJNAME"
13-
ddev start -y >/dev/null
7+
export GITHUB_REPO=Metadrop/ddev-aljibe
8+
TEST_BREW_PREFIX="$(brew --prefix 2>/dev/null || true)"
9+
export BATS_LIB_PATH="${BATS_LIB_PATH}:${TEST_BREW_PREFIX}/lib:/usr/lib/bats"
10+
bats_load_library bats-assert
11+
bats_load_library bats-file
12+
bats_load_library bats-support
13+
14+
# shellcheck disable=SC2155
15+
export DIR="$(cd "$(dirname "${BATS_TEST_FILENAME}")/.." >/dev/null 2>&1 && pwd)"
16+
# shellcheck disable=SC2155
17+
export PROJNAME="test-$(basename "${GITHUB_REPO}")"
18+
19+
mkdir -p ~/tmp
20+
# shellcheck disable=SC2155
21+
export TESTDIR=$(mktemp -d ~/tmp/${PROJNAME}.XXXXXX)
22+
export DDEV_NONINTERACTIVE=true
23+
export DDEV_NO_INSTRUMENTATION=true
24+
ddev delete -Oy "${PROJNAME}" >/dev/null 2>&1 || true
25+
26+
cd "${TESTDIR}"
27+
run ddev config --project-name="${PROJNAME}" --project-tld=ddev.site
28+
assert_success
29+
run ddev start -y
30+
assert_success
1431
}
1532

33+
# Standard DDEV add-on tear down code taken from official DDEV add-ons.
1634
teardown() {
1735
set -eu -o pipefail
18-
cd "$TESTDIR" || { printf "unable to cd to %s\n" "$TESTDIR"; exit 1; }
19-
ddev delete -Oy "$PROJNAME" >/dev/null 2>&1
20-
[ -n "$TESTDIR" ] && rm -rf "$TESTDIR"
36+
cd ${TESTDIR} || ( printf "unable to cd to ${TESTDIR}\n" && exit 1 )
37+
ddev delete -Oy ${PROJNAME} >/dev/null 2>&1
38+
[ "${TESTDIR}" != "" ] && rm -rf ${TESTDIR}
2139
}
2240

23-
check_services() {
24-
echo "Checking services:"
25-
INSTALLED_SERVICES=$(ddev get --installed)
26-
for SERVICE in aljibe aljibe-assistant adminer backstopjs lighthouse mkdocs pa11y redis selenium unlighthouse;
27-
do
28-
if echo "$INSTALLED_SERVICES" | grep -q "$SERVICE"; then
29-
echo "Checking if $SERVICE is installed... Ok."
41+
# Generic helper function to check items from external list using a custom checker function.
42+
#
43+
# WARNING: This is an internal helper. Do not call directly. Use wrapper functions instead.
44+
#
45+
# Parameters:
46+
# $1: item_type - descriptive name (e.g., "folder", "file", "add-on")
47+
# $2: list_file - path to the file containing items to check
48+
# $3: checker_function - name of function to call to check each item
49+
# $4+ - additional arguments passed to checker function
50+
check_items_from_list() {
51+
local item_type="$1"
52+
local list_file="$2"
53+
local checker_function="$3"
54+
shift 3
55+
local checker_args=("$@")
56+
local failed=0
57+
58+
echo "Checking required ${item_type}s:"
59+
60+
# Read required items from external file
61+
while IFS='#' read -r item comment || [ -n "$item" ]; do
62+
# Skip empty lines and comments
63+
[[ -z "$item" || "$item" =~ ^[[:space:]]*# ]] && continue
64+
65+
# Trim whitespace
66+
item=$(echo "$item" | xargs)
67+
comment=$(echo "$comment" | xargs)
68+
69+
# Call the checker function with item and any additional arguments
70+
if "$checker_function" "$item" "${checker_args[@]}"; then
71+
echo "Checking if ${item_type} '${item}' exists... Ok. (${comment})"
3072
else
31-
echo "Checking if $SERVICE is installed... Not installed."
73+
echo "Checking if ${item_type} '${item}' exists... Missing. (${comment})"
74+
failed=1
3275
fi
33-
done
76+
done < "$list_file"
77+
78+
return $failed
79+
}
80+
81+
# Checker function for filesystem items (files, folders, symlinks)
82+
#
83+
# Parameters:
84+
# $1: item - the item name
85+
# $2: test_flag - "-d" for folders, "-f" for files, "-L" for symlinks
86+
check_filesystem_item() {
87+
local item="$1"
88+
local test_flag="$2"
89+
test "$test_flag" "${TESTDIR}/${item}"
90+
}
91+
92+
# Checker function for installed add-ons
93+
#
94+
# Parameters:
95+
# $1: item - the add-on name
96+
# $2: installed_services - output from ddev add-on list
97+
check_addon_item() {
98+
local item="$1"
99+
local installed_services="$2"
100+
# Add a trailing space in grep to avoid partial matches
101+
# Also, start with │ to avoid matching in other places that are not the first
102+
# column.
103+
echo "$installed_services" | grep -q "$item "
34104
}
35105

36-
check_project_browse() {
106+
# Checker function for running services
107+
#
108+
# Parameters:
109+
# $1: item - the service name
110+
# $2: running_services - output from ddev describe
111+
check_service_item() {
112+
local item="$1"
113+
local running_services="$2"
114+
# Add a trailing space in grep to avoid partial matches
115+
# Also, start with │ to avoid matching in other places that are not the first
116+
# column.
117+
echo "$running_services" | grep -q "$item "
118+
}
119+
120+
# Internal helper function to check existence of items from external list.
121+
#
122+
# WARNING: Do not call this function directly. Use check_required_folders or
123+
# check_required_files instead.
124+
#
125+
# Parameters:
126+
# $1: item_type - "folder" or "file"
127+
# $2: list_file - path to the file containing items to check
128+
# $3: test_flag - "-d" for folders, "-f" for files
129+
check_required_items() {
130+
local item_type="$1"
131+
local list_file="$2"
132+
local test_flag="$3"
133+
check_items_from_list "$item_type" "$list_file" check_filesystem_item "$test_flag"
134+
}
135+
136+
# Check a list of add-ons that should be installed.
137+
check_addons() {
138+
local INSTALLED_ADDONS
139+
INSTALLED_ADDONS=$(ddev add-on list --installed)
140+
check_items_from_list "add-on" "${DIR}/tests/required_addons.txt" check_addon_item "$INSTALLED_ADDONS"
141+
}
142+
143+
# Check a list of required folders.
144+
check_required_folders() {
145+
check_required_items "folder" "${DIR}/tests/required_folders.txt" "-d"
146+
}
147+
148+
# Check a list of required files.
149+
check_required_files() {
150+
check_required_items "file" "${DIR}/tests/required_files.txt" "-f"
151+
}
152+
153+
# Check a list of required symlinks.
154+
check_required_symlinks() {
155+
check_required_items "symlinks" "${DIR}/tests/required_symlinks.txt" "-L"
156+
}
157+
158+
# Check a list of services that should be running.
159+
check_services() {
160+
local RUNNING_SERVICES
161+
RUNNING_SERVICES=$(ddev describe)
162+
check_items_from_list "service" "${DIR}/tests/required_services.txt" check_service_item "$RUNNING_SERVICES"
163+
}
164+
165+
# Check Aljibe Assistant is installed alongside Aljibe.
166+
check_assistant_is_installed() {
167+
local failed=0
168+
169+
echo -n "Checking if Aljibe Assistant is installed..."
170+
if ddev add-on list --installed | grep -q "aljibe-assistant"; then
171+
echo " Ok."
172+
else
173+
echo " Failed."
174+
failed=1
175+
fi
176+
return "$failed"
177+
}
178+
179+
# Checks the homepage returns a 200 status code.
180+
check_project_homepage_is_browsable() {
181+
local failed=0
182+
37183
echo -n "Checking if the project is browsable..."
38-
if curl -s "https://${PROJNAME}.ddev.site" | grep -q "Welcome"; then
184+
local status_code
185+
status_code=$(curl -w "%{http_code}" -o NULL -s "https://${PROJNAME}.ddev.site")
186+
187+
if [ "$status_code" == "200" ]; then
39188
echo " Ok."
40189
else
41190
echo " Failed."
191+
failed=1
42192
fi
193+
194+
return "$failed"
43195
}
44196

197+
# Checks if the Drupal admin user is accessible via one-time login link.
198+
#
199+
# It checks page content because the status code is not valid for this check: if
200+
# the ULI URL is not valid the user is redirected to the login page with a 200
201+
# status code.
45202
check_drupal_admin_access() {
203+
local failed=0
204+
46205
echo -n "Checking if the Drupal admin is accessible..."
47-
if curl -sLb cookies "$(ddev drush uli)" | grep -q "The email address is not made public"; then
206+
207+
local login_url
208+
login_url=$(ddev drush uli 2>&1)
209+
210+
local response
211+
response=$(curl -sLb /tmp/cookies_$$ "$login_url" 2>&1)
212+
213+
# For some reason, the message saying that you have used a one-time login link
214+
# is not always present, so we check for the password change prompt instead.
215+
if echo "$response" | grep -q "To change the current user password, enter the new password in both fields."; then
48216
echo " Ok."
49217
else
50218
echo " Failed."
219+
failed=1
51220
fi
221+
222+
# Cleanup
223+
rm -f /tmp/cookies_$$
224+
225+
return "$failed"
52226
}
53227

54228
@test "install from directory" {
55229
set -eu -o pipefail
56230
cd "$TESTDIR"
57231
echo "# ddev get ${DIR} with project ${PROJNAME} in ${TESTDIR} ($(pwd))" >&3
58-
ddev get "${DIR}"
59-
ddev restart >/dev/null
60-
ddev aljibe-assistant --auto
61232

62-
check_services >&3
63-
check_project_browse >&3
64-
## Todo Make this test work
65-
# check_drupal_admin_access >&3
66-
}
233+
# Install the add-on and restart ddev to apply changes.
234+
ddev add-on get "${DIR}"
235+
assert_success
236+
ddev restart -y
237+
assert_success
67238

68-
@test "install from release" {
69-
set -eu -o pipefail
70-
cd "$TESTDIR" || { printf "unable to cd to %s\n" "$TESTDIR"; exit 1; }
71-
echo "# ddev get metadrop/ddev-aljibe with project ${PROJNAME} in ${TESTDIR} ($(pwd))" >&3
72-
ddev get metadrop/ddev-aljibe
73-
ddev restart >/dev/null
74-
ddev aljibe-assistant --auto
75-
76-
check_services >&3
77-
check_project_browse >&3
78-
## Todo Make this test work
79-
# check_drupal_admin_access >&3
80-
}
239+
# Run Assistant in automatic mode with standard profile.
240+
ddev aljibe-assistant --auto -p standard
241+
assert_success
242+
243+
# Checks on files and folders required after installation.
244+
run check_required_folders
245+
assert_success
246+
247+
run check_required_files
248+
assert_success
249+
250+
run check_required_symlinks
251+
assert_success
252+
253+
# Make sure Assistant is installed.
254+
run check_assistant_is_installed
255+
assert_success
256+
257+
# Check the required addons have installed correctly.
258+
run check_addons
259+
assert_success
260+
261+
# Check if the expected services are running.
262+
run check_services
263+
assert_success
264+
265+
# Check the project's homepage is accessible.
266+
run check_project_homepage_is_browsable
267+
assert_success
268+
269+
run check_drupal_admin_access
270+
assert_success
271+
}

0 commit comments

Comments
 (0)