Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test-smokes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ jobs:
echo ">>> ./run-tests.sh ${file}"
# Run tests without -e so we don't exit on first failure
set +e
shopt -s globstar && ./run-tests.sh "$file"
./run-tests.sh "$file"
status=$?
set -e
echo "::endgroup::"
Expand Down
3 changes: 3 additions & 0 deletions dev-docs/feature-format-matrix/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ qmd-files/**/*.html
qmd-files/**/*.pdf
qmd-files/**/*.md
qmd-files/**/*.mdx
qmd-files/**/*.typ

/.quarto/

**/*.quarto_ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- '#{set text\(font: \("Georgia", "serif"\)\); table\('
- '#{set text\(font: \("Libertinus Serif", "serif"\)\); table\('
- []
---

```{=html}
<table style="font-family: Georgia, serif;">
<table style="font-family: 'Libertinus Serif', serif;">
<tr><td>A</td><td>B</td></tr>
</table>
```
Expand Down
76 changes: 76 additions & 0 deletions tests/run-tests-multiple-file-args.test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/env bash
# Regression test for run-tests.sh collapsing multiple .test.ts file
# arguments into a single glued argv token.
#
# tests/README.md documents passing several .ts files at once, e.g.:
# ./run-tests.sh smoke/extensions/extension-render-doc.test.ts smoke/smoke-all.test.ts
#
# run-tests.sh built TESTS_TO_RUN by looping `for file in "$*"; do`, which
# joins all positional args into one string before iterating, so the loop
# only ever runs once. That single glued string used to reach deno unquoted,
# where bash's own word-splitting happened to reconstruct separate args -
# but that's incidental, not something quoting the resulting array should be
# allowed to depend on. This test runs the real run-tests.sh with two file
# arguments and confirms each survives as its own deno argv token.
set -uo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." >/dev/null 2>&1 && pwd)"

TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT

fail() {
echo "FAIL: $1"
exit 1
}

# --- Isolated fake repo skeleton, just enough for run-tests.sh to run ---
mkdir -p "$TMP/tests"
mkdir -p "$TMP/package/scripts/common"
mkdir -p "$TMP/package/dist/bin/tools/stub"
mkdir -p "$TMP/src/resources"

# Strip CR in case this checkout has core.autocrlf=true (Windows dev boxes);
# CI checkouts on Linux/macOS never have CRLF here, this is a local-copy
# normalization only, not part of the fix under test.
tr -d '\r' < "$REPO_ROOT/tests/run-tests.sh" > "$TMP/tests/run-tests.sh"
tr -d '\r' < "$REPO_ROOT/package/scripts/common/utils.sh" > "$TMP/package/scripts/common/utils.sh"
chmod +x "$TMP/tests/run-tests.sh"

RECORD_FILE="$TMP/recorded-argv.txt"
cat > "$TMP/package/dist/bin/tools/stub/deno" <<'EOF'
#!/usr/bin/env bash
printf '%s\n' "$@" > "$RECORD_FILE"
exit 0
EOF
chmod +x "$TMP/package/dist/bin/tools/stub/deno"

# --- Invoke the real script with two separate .test.ts file arguments ---
(
cd "$TMP/tests" || exit 1
export QUARTO_TESTS_NO_CONFIG=true
export QUARTO_TESTS_FORCE_NO_VENV=true
export DENO_DIR=stub
export RECORD_FILE
./run-tests.sh "foo.test.ts" "bar.test.ts"
)

[ -f "$RECORD_FILE" ] || fail "deno stub was never invoked - run-tests.sh did not reach the final deno call"

mapfile -t recorded < "$RECORD_FILE"

found_foo=0
found_bar=0
found_glued=0
for tok in "${recorded[@]}"; do
[ "$tok" = "foo.test.ts" ] && found_foo=1
[ "$tok" = "bar.test.ts" ] && found_bar=1
[ "$tok" = "foo.test.ts bar.test.ts" ] && found_glued=1
done

[ "$found_glued" -eq 0 ] || fail "foo.test.ts and bar.test.ts were glued into a single argv token - multiple file arguments were collapsed"
[ "$found_foo" -eq 1 ] || fail "foo.test.ts missing from deno argv (got: ${recorded[*]})"
[ "$found_bar" -eq 1 ] || fail "bar.test.ts missing from deno argv (got: ${recorded[*]})"

echo "PASS: multiple .test.ts file arguments reached deno as separate argv tokens"
95 changes: 95 additions & 0 deletions tests/run-tests-recursive-glob.test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#!/usr/bin/env bash
# Regression test for run-tests.sh silently truncating recursive ** glob
# buckets on Linux/macOS (quarto-cli-jho3).
#
# Runs the real run-tests.sh against a nested qmd fixture, with the deno
# binary swapped for a recorder stub (via the DENO_DIR override run-tests.sh
# already supports), and checks that a file nested two directories deep
# under a `**` bucket still reaches the resolved test-file set. The
# assertion re-expands any still-glob-shaped token itself (mirroring what
# smoke-all.test.ts's expandGlobSync does), so it passes regardless of
# whether the fix quotes the pattern through to deno or expands it in bash.
set -uo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." >/dev/null 2>&1 && pwd)"

TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT

fail() {
echo "FAIL: $1"
exit 1
}

# --- Isolated fake repo skeleton, just enough for run-tests.sh to run ---
mkdir -p "$TMP/tests"
mkdir -p "$TMP/package/scripts/common"
mkdir -p "$TMP/package/dist/bin/tools/stub"
mkdir -p "$TMP/src/resources"

# Strip CR in case this checkout has core.autocrlf=true (Windows dev boxes);
# CI checkouts on Linux/macOS never have CRLF here, this is a local-copy
# normalization only, not part of the fix under test.
tr -d '\r' < "$REPO_ROOT/tests/run-tests.sh" > "$TMP/tests/run-tests.sh"
tr -d '\r' < "$REPO_ROOT/package/scripts/common/utils.sh" > "$TMP/package/scripts/common/utils.sh"
chmod +x "$TMP/tests/run-tests.sh"

RECORD_FILE="$TMP/recorded-argv.txt"
cat > "$TMP/package/dist/bin/tools/stub/deno" <<'EOF'
#!/usr/bin/env bash
printf '%s\n' "$@" > "$RECORD_FILE"
exit 0
EOF
chmod +x "$TMP/package/dist/bin/tools/stub/deno"

# --- Nested fixture: one .qmd at depth 1, one at depth 2 under qmd-files/ ---
mkdir -p "$TMP/qmd-files/a/b"
: > "$TMP/qmd-files/a/one.qmd"
: > "$TMP/qmd-files/a/b/two.qmd"

# --- Invoke the real script exactly as test-smokes.yml's bucket runner does ---
(
cd "$TMP/tests" || exit 1
export QUARTO_TESTS_NO_CONFIG=true
export QUARTO_TESTS_FORCE_NO_VENV=true
export DENO_DIR=stub
export RECORD_FILE
./run-tests.sh "../qmd-files/**/*.qmd"
)

[ -f "$RECORD_FILE" ] || fail "deno stub was never invoked - run-tests.sh did not reach the final deno call"

mapfile -t recorded < "$RECORD_FILE"

dashdash_index=-1
for i in "${!recorded[@]}"; do
if [ "${recorded[$i]}" = "--" ]; then
dashdash_index=$i
break
fi
done
[ "$dashdash_index" -ge 0 ] || fail "no isolated '--' token in deno argv (got: ${recorded[*]})"

# Resolve the file tokens after '--' into an actual file set, expanding any
# token that still looks like a glob pattern (mirrors expandGlobSync).
resolved=()
(
cd "$TMP/tests" || exit 1
shopt -s globstar nullglob
for ((i = dashdash_index + 1; i < ${#recorded[@]}; i++)); do
tok="${recorded[$i]}"
if [[ "$tok" == *"*"* ]]; then
for f in $tok; do
echo "$f"
done
else
echo "$tok"
fi
done
) > "$TMP/resolved-files.txt"

grep -q 'a/one\.qmd$' "$TMP/resolved-files.txt" || fail "depth-1 fixture file (qmd-files/a/one.qmd) missing from resolved test set"
grep -q 'a/b/two\.qmd$' "$TMP/resolved-files.txt" || fail "depth-2 fixture file (qmd-files/a/b/two.qmd) missing from resolved test set - recursive ** bucket was silently truncated"

echo "PASS: recursive ** bucket resolved both depth-1 and depth-2 fixture files"
27 changes: 16 additions & 11 deletions tests/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,19 @@ else
## Short version syntax to run smoke-all.test.ts
## Only use if different than ./run-test.sh ./smoke/smoke-all.test.ts
if [[ "$1" =~ smoke-all\.test\.ts ]]; then
TESTS_TO_RUN=$@
TESTS_TO_RUN=("$@")
else
# Check file argument
SMOKE_ALL_FILES=""
TESTS_TO_RUN=""
SMOKE_ALL_FILES=()
TESTS_TO_RUN=()
if [[ ! -z "$*" ]]; then
for file in "$*"; do
for file in "$@"; do
filename=$(basename "$file")
# smoke-all.test.ts works with .qmd, .md and .ipynb but will ignored file starting with _
if [[ $filename =~ ^[^_].*[.]qmd$ ]] || [[ $filename =~ ^[^_].*[.]ipynb$ ]] || [[ $filename =~ ^[^_].*[.]md$ ]]; then
SMOKE_ALL_FILES="${SMOKE_ALL_FILES} ${file}"
SMOKE_ALL_FILES+=("${file}")
elif [[ $file =~ .*[.]ts$ ]]; then
TESTS_TO_RUN="${TESTS_TO_RUN} ${file}"
TESTS_TO_RUN+=("${file}")
else
echo "#### WARNING"
echo "Only .ts, or .qmd, .md and .ipynb passed to smoke-all.test.ts are accepted (file starting with _ are ignored)."
Expand All @@ -151,17 +151,22 @@ else
fi
done
fi
if [ "$SMOKE_ALL_FILES" != "" ]; then
if [ "$TESTS_TO_RUN" != "" ]; then
if [ "${#SMOKE_ALL_FILES[@]}" -ne 0 ]; then
if [ "${#TESTS_TO_RUN[@]}" -ne 0 ]; then
echo "#### WARNING"
echo "When passing .qmd, .md and/or .ipynb, only ./smoke/smoke-all.test.ts will be run. Other tests files are ignored."
echo "Ignoring ${TESTS_TO_RUN}."
echo "Ignoring ${TESTS_TO_RUN[*]}."
echo "####"
fi
TESTS_TO_RUN="${SMOKE_ALL_TEST_FILE} -- ${SMOKE_ALL_FILES}"
TESTS_TO_RUN=("${SMOKE_ALL_TEST_FILE}" "--" "${SMOKE_ALL_FILES[@]}")
fi
fi
"${QUARTO_BIN_PATH}/tools/${DENO_ARCH_DIR}/deno" test ${QUARTO_DENO_OPTIONS} --check ${QUARTO_DENO_EXTRA_OPTIONS} "${QUARTO_IMPORT_MAP_ARG}" $TESTS_TO_RUN
# TESTS_TO_RUN is an array and quoted here on purpose: a bucket can be a
# literal, unexpanded ** glob pattern (e.g. from the ff-matrix CI bucket),
# and smoke-all.test.ts expands it itself via expandGlobSync. Expanding it
# here instead would depend on bash's own (non-recursive by default) glob
# semantics and could silently drop deeply nested matches.
"${QUARTO_BIN_PATH}/tools/${DENO_ARCH_DIR}/deno" test ${QUARTO_DENO_OPTIONS} --check ${QUARTO_DENO_EXTRA_OPTIONS} "${QUARTO_IMPORT_MAP_ARG}" "${TESTS_TO_RUN[@]}"
SUCCESS=$?
fi

Expand Down
Loading