Add snapshot tests for a basic Drupal project

This commit is contained in:
Oliver Davies 2023-12-15 14:09:09 +00:00
parent 58e454b2c2
commit 680b72bb64
18 changed files with 576 additions and 2 deletions

1
.gitignore vendored
View file

@ -2,6 +2,7 @@
/.direnv
/dist/*
!/dist/.keep
.ignored/
###> symfony/framework-bundle ###
/.env.local

56
run
View file

@ -28,7 +28,7 @@ function build {
# Generate the phar file.
box compile --config box.json.dist
rm -f .env.local.php
rm -f .env.local .env.local.php
tree dist/
@ -37,6 +37,7 @@ function build {
function ci:test {
nix develop --command composer install
nix develop --command ./run test:snapshots
nix develop --command phpunit
}
@ -49,10 +50,61 @@ function help {
printf "\nExtended help:\n Each task has comments for general usage\n"
}
function test {
phpunit "${@}"
}
# Create a new snapshot for a configuration based on generated files.
function test:create-snapshot {
set -o nounset
config="${1}"
config_file="tests/snapshots/configs/${config}.yaml"
output_path="tests/snapshots/output/${config}"
cat "${config_file}"
rm -fr "${output_path}"
./bin/build-configs app:generate --config-file "${config_file}" --output-dir "${output_path}"
git status "${output_path}"
}
# Generate a file and ensure it matches the expected version.
function test:snapshots {
rm -rf .ignored/snapshots
mkdir -p .ignored/snapshots
local configs=(
# TODO: add more configurations for different types and configurations.
drupal
)
for config in "${configs[@]}"; do
config_file="tests/snapshots/configs/${config}.yaml"
input_path="tests/snapshots/output/${config}"
output_path=".ignored/snapshots/output/${config}"
cat "${config_file}"
./bin/build-configs app:generate --config-file "${config_file}" --output-dir "${output_path}"
find "${input_path}" -type f -print0 | while IFS= read -r -d '' original_file; do
generated_file="$output_path/${original_file#"${input_path}"/}"
if cmp -s "${original_file}" "${generated_file}"; then
echo "Files match: ${original_file}"
else
# TODO: show the diff for all failed files. This will stop after the first failure.
echo "Files do not match: ${original_file}"
diff "${original_file}" "${generated_file}"
exit 1
fi
done
done
}
TIMEFORMAT=$'\nTask completed in %3lR'
time "${@:-help}"

View file

@ -0,0 +1,43 @@
name: drupal
language: php
type: drupal
web:
type: nginx
database:
type: mariadb
version: 10
php:
version: 8.1-fpm-bullseye
phpcs:
paths:
- web/modules/custom
standards:
- Drupal
- DrupalPractice
phpstan:
level: max
paths:
- web/modules/custom
drupal:
docroot: web
docker-compose:
services:
- database
- php
- web
dockerfile:
stages:
build:
commands:
- composer validate
- composer install
experimental:
createGitHubActionsConfiguration: true
runGitHooksBeforePush: true

View file

@ -0,0 +1,2 @@
/README.md
/.github/

View file

@ -0,0 +1,12 @@
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
export DOCKER_UID=1000
export COMPOSE_PROJECT_NAME=drupal
export COMPOSE_PROFILES=web,php,database
export DOCKER_WEB_VOLUME=.:/app
export MYSQL_DATABASE=app
export MYSQL_PASSWORD=app
export MYSQL_USER=app

View file

@ -0,0 +1,9 @@
#!/usr/bin/env bash
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
set -o errexit
export TTY="-T"
./run test:commit

View file

@ -0,0 +1,27 @@
#!/usr/bin/env bash
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
# Load the issue ID from an `.issue-id` file within the project and replace the
# `ISSUE_ID` placeholder within a Git commit message.
#
# For example, running `echo "OD-123" > .issue-id` will add `Refs: OD-123` to
# the commit message.
#
# This also works with multiple issue IDs in the same string, e.g.
# "OD-123 OD-456", or IDs on multiple lines.
set -o errexit
set -o nounset
set -o pipefail
PROJECT_DIR=$(git rev-parse --show-toplevel)
ISSUE_FILE="$PROJECT_DIR/.issue-id"
if [ -f "${ISSUE_FILE}" ]; then
ISSUE_IDS=$(cat "${ISSUE_FILE}" | tr '\n' ',' | tr ' ' ',' | sed 's/,$//' | sed 's/,/, /g')
if [ -n "${ISSUE_IDS}" ]; then
sed -i.bak "s/# Refs:/Refs: $ISSUE_IDS/" "$1"
fi
fi

View file

@ -0,0 +1,25 @@
name: CI
on:
pull_request:
push:
workflow_dispatch:
env:
COMPOSE_DOCKER_CLI_BUILD: 1
DOCKER_BUILDKIT: 1
DOCKER_UID: 1001
jobs:
build_and_test:
name: Build and test
runs-on: ubuntu-latest
steps:
- name: Checkout the code
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
- name: Build and test
run: |
./run ci:test

View file

@ -0,0 +1,42 @@
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
.editorconfig
.env
.gitattributes
vendor/
web/.csslintrc
web/.eslintignore
web/.eslintrc.json
web/.ht.router.php
web/.htaccess
web/INSTALL.txt
web/README.md
web/autoload.php
web/core/
web/example.gitignore
web/index.php
web/modules/README.txt
web/modules/contrib/
web/profiles/README.txt
web/robots.txt
web/sites/*/files/
web/sites/*/private/
web/sites/*/services*.yml
web/sites/*/settings*.php
web/sites/README.txt
web/sites/default/default.services.yml
web/sites/default/default.settings.php
web/sites/development.services.yml
web/sites/example.settings.local.php
web/sites/example.sites.php
web/sites/simpletest/
web/themes/README.txt
web/themes/contrib/
web/update.php
web/web.config
# Docker.
.env
docker-compose.override.yaml

View file

@ -0,0 +1,2 @@
ignore:
- DL3059

View file

@ -0,0 +1,64 @@
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
FROM php:8.1-fpm-bullseye AS base
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
RUN which composer && composer -V
ARG DOCKER_UID=1000
ENV DOCKER_UID="${DOCKER_UID}"
WORKDIR /app
RUN adduser --disabled-password --uid "${DOCKER_UID}" app \
&& chown app:app -R /app
USER app
ENV PATH="${PATH}:/app/bin:/app/vendor/bin"
COPY --chown=app:app composer.* ./
################################################################################
FROM base AS build
USER root
RUN apt-get update -yqq \
&& apt-get install -yqq --no-install-recommends \
git libpng-dev libjpeg-dev libzip-dev mariadb-client unzip \
&& rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man \
&& apt-get clean
RUN docker-php-ext-configure gd --with-jpeg
RUN docker-php-ext-install gd pdo_mysql zip
COPY --chown=app:app phpunit.xml* ./
USER app
RUN composer validate
RUN composer install
COPY --chown=app:app tools/docker/images/php/root /
ENTRYPOINT ["/usr/local/bin/docker-entrypoint-php"]
CMD ["php-fpm"]
################################################################################
FROM nginx:1 as web
EXPOSE 8080
WORKDIR /app
COPY tools/docker/images/web/root /

View file

@ -0,0 +1,77 @@
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
x-proxy: &default-proxy
networks:
- default
- web
labels:
- "traefik.docker.network=traefik_proxy"
- "traefik.http.routers.${COMPOSE_PROJECT_NAME}.rule=Host(
`${COMPOSE_PROJECT_NAME}.localhost`,
)"
x-app: &default-app
volumes:
- "${DOCKER_WEB_VOLUME:-./web:/app/web}"
env_file:
- .env
restart: "${DOCKER_RESTART_POLICY:-unless-stopped}"
networks:
- default
deploy:
resources:
limits:
cpus: "${DOCKER_MYSQL_CPUS:-0}"
memory: "${DOCKER_MYSQL_MEMORY:-0}"
labels:
- "traefik.enabled=false"
tty: true
services:
web:
<<: [*default-proxy, *default-app]
build:
context: .
target: web
depends_on:
- php
profiles: [web]
php:
<<: [*default-app]
build:
context: .
target: build
args:
- "DOCKER_UID=${DOCKER_UID:-1000}"
volumes:
- .:/app
depends_on:
- database
profiles: [php]
database:
image: mariadb:10
deploy:
resources:
limits:
cpus: "${DOCKER_MYSQL_CPUS:-0}"
memory: "${DOCKER_MYSQL_MEMORY:-0}"
volumes:
- db-data:/var/lib/mysql
env_file:
- .env
labels:
- "traefik.enabled=false"
environment:
MYSQL_RANDOM_ROOT_PASSWORD: true
profiles: [database]
volumes:
db-data: {}
networks:
web:
external: true
name: traefik_proxy

View file

@ -0,0 +1,32 @@
<?xml version="1.0"?>
<!-- Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs. -->
<ruleset name="drupal coding standards">
<description>PHPCS configuration file for drupal.</description>
<file>web/modules/custom</file>
<arg value="np"/>
<rule ref="DrupalPractice"/>
<rule ref="Drupal">
<exclude name="Drupal.Commenting.ClassComment.Missing"/>
<exclude name="Drupal.Commenting.DataTypeNamespace.DataTypeNamespace"/>
<exclude name="Drupal.Commenting.Deprecated"/>
<exclude name="Drupal.Commenting.DocComment.ContentAfterOpen"/>
<exclude name="Drupal.Commenting.DocComment.MissingShort"/>
<exclude name="Drupal.Commenting.FunctionComment.IncorrectParamVarName"/>
<exclude name="Drupal.Commenting.FunctionComment.IncorrectTypeHint"/>
<exclude name="Drupal.Commenting.FunctionComment.InvalidReturn"/>
<exclude name="Drupal.Commenting.FunctionComment.Missing"/>
<exclude name="Drupal.Commenting.FunctionComment.MissingParamComment"/>
<exclude name="Drupal.Commenting.FunctionComment.MissingReturnComment"/>
<exclude name="Drupal.Commenting.FunctionComment.ParamTypeSpaces"/>
<exclude name="Drupal.Commenting.FunctionComment.TypeHintMissing"/>
<exclude name="Drupal.Commenting.InlineComment.DocBlock"/>
<exclude name="Drupal.Commenting.VariableComment.Missing"/>
<exclude name="Drupal.NamingConventions.ValidFunctionName.ScopeNotCamelCaps"/>
<exclude name="DrupalPractice.Objects.StrictSchemaDisabled.StrictConfigSchema"/>
</rule>
</ruleset>

View file

@ -0,0 +1,9 @@
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
parameters:
level: max
excludePaths:
- *Test.php
- *TestBase.php
paths:
- web/modules/custom

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs. -->
<phpunit
beStrictAboutChangesToGlobalState="true"
beStrictAboutOutputDuringTests="false"
beStrictAboutTestsThatDoNotTestAnything="true"
bootstrap="web/core/tests/bootstrap.php"
cacheResult="false"
colors="true"
failOnWarning="true"
printerClass="\Drupal\Tests\Listeners\HtmlOutputPrinter"
>
<php>
<env name="BROWSERTEST_OUTPUT_BASE_URL" value=""/>
<env name="BROWSERTEST_OUTPUT_DIRECTORY" value=""/>
<env name="MINK_DRIVER_ARGS" value=''/>
<env name="MINK_DRIVER_ARGS_WEBDRIVER" value=''/>
<env name="MINK_DRIVER_CLASS" value=''/>
<env name="SIMPLETEST_BASE_URL" value="http://web"/>
<env name="SIMPLETEST_DB" value="sqlite://localhost//dev/shm/test.sqlite"/>
<ini name="error_reporting" value="32767"/>
<ini name="memory_limit" value="-1"/>
</php>
<testsuites>
<testsuite name="functional">
<directory>./web/modules/custom/**/tests/**/Functional</directory>
</testsuite>
<testsuite name="kernel">
<directory>./web/modules/custom/**/tests/**/Kernel</directory>
</testsuite>
<testsuite name="unit">
<directory>./web/modules/custom/**/tests/**/Unit</directory>
</testsuite>
</testsuites>
</phpunit>

129
tests/snapshots/output/drupal/run Executable file
View file

@ -0,0 +1,129 @@
#!/usr/bin/env bash
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
set -o errexit
set -o pipefail
# If we're running in CI we need to disable TTY allocation for docker compose
# commands that enable it by default, such as exec and run.
TTY="${TTY:-}"
if [[ ! -t 1 ]]; then
TTY="-T"
fi
# Run automated tests as part of the Continuous Integration (CI) pipeline.
function ci:test {
lint:dockerfile
docker compose version
docker network create traefik_proxy
cp --no-clobber .env.example .env
docker compose build --progress plain
docker compose up --detach
docker compose logs
composer install --quiet --no-progress
test --testdox
quality
}
# Run a command within the php container.
function cmd {
docker compose exec php "${@}"
}
function coding-standards {
cmd phpcs "${@}"
}
function composer {
_exec php composer "${@}"
}
function drush {
_exec php drush "${@}"
}
function git-hooks:off {
git config --unset core.hooksPath
}
function git-hooks:on {
git config core.hooksPath .githooks
}
# Display a list of all available commands.
function help {
printf "%s <task> [args]\n\nTasks:\n" "${0}"
compgen -A function | grep -v "^_" | cat -n
printf "\nExtended help:\n Each task has comments for general usage\n"
}
function lint:dockerfile {
docker container run --rm -i \
hadolint/hadolint hadolint --ignore DL3008 --ignore DL3059 -t style "${@}" - < Dockerfile
}
function quality {
coding-standards
static-analysis
}
function start {
cp -v --no-clobber .env.example .env
docker compose up -d
}
function static-analysis {
cmd phpstan --memory-limit=-1 --no-progress "${@}"
}
function stop {
docker compose down
}
function test {
_exec php phpunit --colors=always "${@}"
}
function test:commit {
test --testdox --testsuite functional
test --testdox --testsuite kernel
test --testdox --testsuite unit
quality
}
function _exec {
docker compose exec ${TTY} "${@}"
}
function _run {
local service="${1}"
local command="${2}"
docker compose run \
--entrypoint "${command}" \
--no-deps \
--rm \
${TTY} \
"${service}" "${@}"
}
# Include any local tasks.
[[ -e run.local ]] && source run.local
TIMEFORMAT=$'\nTask completed in %3lR'
time "${@:-help}"
# vim: ft=bash

View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
[[ -f composer.json && ! -d vendor ]] && composer install
eval "$@"

View file

@ -0,0 +1,4 @@
# Do not edit this file. It is automatically generated by https://www.oliverdavies.uk/build-configs.
max_vars_input = 1000
memory_limit = 128M