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
19 changes: 19 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,22 @@ jobs:
- name: Run Python tests
run: |
for suite in tests/python/*/run.sh; do "$suite"; done

javascript-tests:
name: JavaScript Tests
runs-on: ubuntu-latest
needs: shellcheck

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Prepare test environment
run: |
chmod +x javascript/*.sh
chmod +x tests/lib/*.bash
find tests/javascript -name "*.sh" -exec chmod +x {} +

- name: Run JavaScript tests
run: |
for suite in tests/javascript/*/run.sh; do "$suite"; done
27 changes: 27 additions & 0 deletions javascript/check_eslint_all.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash
# ------------------------------------------------------------------------------
# Runs ESLint with --fix on the entire project (app/, components/, lib/, types/).
# No file arguments required — always checks all configured directories.
# Exits 1 if ESLint fails to fix issues, 0 on success.
# ------------------------------------------------------------------------------

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"

cd "$PROJECT_ROOT"

# Directories to check
LINT_DIRS=("app/" "components/" "lib/" "types/")

echo "=== ESLint (full project) ==="

echo "Fixing ESLint issues..."
if ! npx eslint "${LINT_DIRS[@]}" --fix; then
echo "ERROR: Failed to fix ESLint issues"
exit 1
fi
echo "ESLint issues fixed!"

exit 0
44 changes: 44 additions & 0 deletions javascript/check_prettier.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash
# ------------------------------------------------------------------------------
# Runs Prettier --write on staged TypeScript files.
# Receives files to check as arguments: ./check_prettier.sh file1.ts file2.ts
# Exits 1 if Prettier fails, 0 on success. Skips if no .ts files provided.
# ------------------------------------------------------------------------------

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"

cd "$PROJECT_ROOT"

# Parse arguments
FILES=()

# Filter only .ts files
RELEVANT_FILES=()
for file in "${FILES[@]}"; do
if [[ "$file" == *.ts ]]; then
if [ -f "$file" ]; then
RELEVANT_FILES+=("$file")
fi
fi
done

# Skip if no relevant files
if [ ${#RELEVANT_FILES[@]} -eq 0 ]; then
echo "=== Code Style Check ==="
echo "No TypeScript files to check, skipping..."
exit 0
fi

echo "=== Code Style Check (${#RELEVANT_FILES[@]} files) ==="

echo "Fixing code style issues..."
if ! npx prettier --write "${RELEVANT_FILES[@]}"; then
echo "ERROR: Failed to fix code style"
exit 1
fi
echo "Code style fixed!"

exit 0
22 changes: 22 additions & 0 deletions javascript/check_prettier_all.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash
# ------------------------------------------------------------------------------
# Runs Prettier --write on all TypeScript files in the project.
# No file arguments required — uses glob patterns for app/, components/, lib/, etc.
# Exits 1 if Prettier fails, 0 on success.
# ------------------------------------------------------------------------------

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"

cd "$PROJECT_ROOT"

echo "Fixing code style issues..."
if ! npx prettier --write "app/**/*.{ts,tsx}" "components/**/*.{ts,tsx}" "lib/**/*.ts" "services/**/*.ts" "types/**/*.ts"; then
echo "ERROR: Failed to fix code style"
exit 1
fi
echo "Code style fixed!"

exit 0
89 changes: 89 additions & 0 deletions javascript/check_test_coverage.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!/bin/bash
# ------------------------------------------------------------------------------
# Runs vitest with optional --watch and --coverage flags for specified files.
# Receives files as arguments: ./check_test_coverage.sh file1.ts [--watch] [--coverage]
# Exits 1 if tests fail, 0 on success. Runs full suite when no files provided.
# ------------------------------------------------------------------------------

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"

cd "$PROJECT_ROOT"

# Parse arguments
WATCH=false
COVERAGE=false
FILES=()

for arg in "$@"; do
case $arg in
--watch)
WATCH=true
;;
--coverage)
COVERAGE=true
;;
*)
FILES+=("$arg")
;;
esac
done

# Filter only test files or source files that have tests
RELEVANT_FILES=()
for file in "${FILES[@]}"; do
if [[ "$file" == *.ts ]]; then
if [ -f "$file" ]; then
RELEVANT_FILES+=("$file")
fi
fi
done

# Determine test command
if [ ${#RELEVANT_FILES[@]} -eq 0 ]; then
echo "=== Tests (full suite) ==="

if [ "$WATCH" = true ]; then
echo "Running tests in watch mode..."
npx vitest
elif [ "$COVERAGE" = true ]; then
echo "Running tests with coverage..."
if ! npx vitest run --coverage; then
echo "ERROR: Tests failed"
exit 1
fi
echo "Tests passed with coverage!"
else
echo "Running tests..."
if ! npx vitest run; then
echo "ERROR: Tests failed"
exit 1
fi
echo "Tests passed!"
fi
else
echo "=== Tests (related to ${#RELEVANT_FILES[@]} changed files) ==="

if [ "$WATCH" = true ]; then
echo "Running related tests in watch mode..."
npx vitest --related "${RELEVANT_FILES[@]}"
elif [ "$COVERAGE" = true ]; then
echo "Running related tests with coverage..."
if ! npx vitest run --related "${RELEVANT_FILES[@]}" --coverage; then
echo "ERROR: Tests failed"
exit 1
fi
echo "Tests passed with coverage!"
else
echo "Running related tests..."
if ! npx vitest run --related "${RELEVANT_FILES[@]}"; then
echo "ERROR: Tests failed"
exit 1
fi
echo "Tests passed!"
fi
fi

exit 0
77 changes: 77 additions & 0 deletions javascript/check_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/bin/bash
# ------------------------------------------------------------------------------
# Runs vitest for changed TypeScript files or from git staged files.
# Receives files as arguments: ./check_tests.sh file1.ts file2.ts
# Exits 1 if tests fail, 0 on success. Skips files matching SKIP_PATTERNS.
# ------------------------------------------------------------------------------

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"

cd "$PROJECT_ROOT"

# Patterns to skip
SKIP_PATTERNS=("tests/" ".test.ts" ".config.ts" ".config.mjs" "types/" ".d.ts" "layout.tsx" "page.tsx" "loading.tsx" "error.tsx" "globals.css" "providers/" "components/ui/" "prisma/")

should_skip() {
local file="$1"
for pattern in "${SKIP_PATTERNS[@]}"; do
[[ "$file" == *"$pattern"* ]] && return 0
done
return 1
}

# Get test path: source.ts -> tests/source.test.ts
get_test_path() {
local file="$1"
local base="${file%.ts}"
base="${base%.tsx}"
echo "tests/${base}.test.ts"
}

# Get files to check
FILES=()
if [ $# -eq 0 ]; then
while IFS= read -r line; do
[[ "$line" == *.ts || "$line" == *.tsx ]] && FILES+=("$line")
done < <(git diff --cached --name-only --diff-filter=ACM 2>/dev/null || true)
[ ${#FILES[@]} -eq 0 ] && echo "No staged TypeScript files" && exit 0
else
for arg in "$@"; do
[[ "$arg" == *.ts || "$arg" == *.tsx ]] && FILES+=("$arg")
done
fi

# Collect tests to run
TESTS_TO_RUN=()

for file in "${FILES[@]}"; do
[ ! -f "$file" ] && continue

# If it's already a test file, add it directly
if [[ "$file" == *.test.ts ]]; then
[ -f "$file" ] && TESTS_TO_RUN+=("$file")
continue
fi

should_skip "$file" && continue

test_path=$(get_test_path "$file")
[ -f "$test_path" ] && TESTS_TO_RUN+=("$test_path")
done

# Remove duplicates
mapfile -t TESTS_TO_RUN < <(printf '%s\n' "${TESTS_TO_RUN[@]}" | sort -u)

if [ ${#TESTS_TO_RUN[@]} -eq 0 ]; then
echo "No tests to run for changed files"
exit 0
fi

echo "=== Running tests for changed files ==="
echo "Tests: ${TESTS_TO_RUN[*]}"
echo ""

npx vitest run "${TESTS_TO_RUN[@]}"
18 changes: 18 additions & 0 deletions javascript/check_tests_all.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash
# ------------------------------------------------------------------------------
# Runs the full vitest test suite for the project.
# No file arguments required — runs all tests via `npx vitest run`.
# Exits 1 if tests fail, 0 on success.
# ------------------------------------------------------------------------------

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"

cd "$PROJECT_ROOT"

echo "=== Running tests ==="
echo ""

npx vitest run
78 changes: 78 additions & 0 deletions javascript/check_tests_exist.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/bin/bash
# ------------------------------------------------------------------------------
# Checks that each staged TypeScript source file has a corresponding test file.
# Receives files as arguments or reads from git staged files if none provided.
# Exits 1 if any source file is missing its tests/...test.ts counterpart.
# ------------------------------------------------------------------------------

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"

cd "$PROJECT_ROOT"

# Patterns to skip (no tests required)
SKIP_PATTERNS=("tests/" ".test.ts" ".config.ts" ".config.mjs" "types/" ".d.ts" "layout.tsx" "page.tsx" "loading.tsx" "error.tsx" "globals.css" "providers/" "components/ui/" "prisma/")

should_skip() {
local file="$1"
for pattern in "${SKIP_PATTERNS[@]}"; do
[[ "$file" == *"$pattern"* ]] && return 0
done
return 1
}

# Get test path: source.ts -> tests/source.test.ts
get_test_path() {
local file="$1"
local base="${file%.ts}"
base="${base%.tsx}"
echo "tests/${base}.test.ts"
}

# Get files to check
FILES=()
if [ $# -eq 0 ]; then
while IFS= read -r line; do
[[ "$line" == *.ts || "$line" == *.tsx ]] && FILES+=("$line")
done < <(git diff --cached --name-only --diff-filter=ACM 2>/dev/null || true)
[ ${#FILES[@]} -eq 0 ] && echo "No staged TypeScript files" && exit 0
else
for arg in "$@"; do
[[ "$arg" == *.ts || "$arg" == *.tsx ]] && FILES+=("$arg")
done
fi

echo "=== Test Coverage Check ==="
echo ""

missing=()
found=()
skipped=()

for file in "${FILES[@]}"; do
[ ! -f "$file" ] && continue
should_skip "$file" && { skipped+=("$file"); continue; }

test_path=$(get_test_path "$file")

if [ -f "$test_path" ]; then
found+=("$file")
else
missing+=("$file → $test_path")
fi
done

[ ${#found[@]} -gt 0 ] && echo -e "Has tests:" && printf ' %s\n' "${found[@]}" && echo ""
[ ${#skipped[@]} -gt 0 ] && echo -e "Skipped:" && printf ' %s\n' "${skipped[@]}" && echo ""

if [ ${#missing[@]} -gt 0 ]; then
echo -e "Missing tests:"
printf ' %s\n' "${missing[@]}"
echo ""
echo -e "ERROR: ${#missing[@]} file(s) missing tests"
exit 1
fi

echo -e "All files have tests!"
Loading