From 7a983f877c50f2b62be91f420eef4d4d29503514 Mon Sep 17 00:00:00 2001 From: antonio-gg-dev Date: Mon, 30 Mar 2026 12:59:19 +0200 Subject: [PATCH 01/12] ci: copy .env.example before test runs --- .github/workflows/tests-bash-3.0.yml | 3 +++ .github/workflows/tests.yml | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/.github/workflows/tests-bash-3.0.yml b/.github/workflows/tests-bash-3.0.yml index 51fc0370..0087945b 100644 --- a/.github/workflows/tests-bash-3.0.yml +++ b/.github/workflows/tests-bash-3.0.yml @@ -80,6 +80,9 @@ jobs: with: fetch-depth: 1 + - name: Setup Config + run: cp .env.example .env + - name: Download Docker image artifact uses: actions/download-artifact@v4 with: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7173d2c1..d41afebb 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,6 +17,9 @@ jobs: with: fetch-depth: 1 + - name: Setup Config + run: cp .env.example .env + - name: Run Tests run: make test @@ -30,6 +33,9 @@ jobs: with: fetch-depth: 1 + - name: Setup Config + run: cp .env.example .env + - name: Run Tests run: make test @@ -63,6 +69,10 @@ jobs: with: fetch-depth: 1 + - name: Setup Config + shell: bash + run: cp .env.example .env + - name: Run tests shell: bash run: | @@ -78,6 +88,9 @@ jobs: with: fetch-depth: 1 + - name: Setup Config + run: cp .env.example .env + - name: Run Tests run: | docker run --rm -v "$(pwd)":/project alpine:latest /bin/sh -c " \ @@ -97,6 +110,9 @@ jobs: with: fetch-depth: 1 + - name: Setup Config + run: cp .env.example .env + - name: Run Tests run: | ./bashunit --simple tests/ @@ -111,6 +127,9 @@ jobs: with: fetch-depth: 1 + - name: Setup Config + run: cp .env.example .env + - name: Run Tests run: | ./bashunit --parallel --simple tests/ @@ -125,6 +144,9 @@ jobs: with: fetch-depth: 1 + - name: Setup Config + run: cp .env.example .env + - name: Run Tests run: | ./bashunit --parallel tests/ @@ -139,6 +161,9 @@ jobs: with: fetch-depth: 1 + - name: Setup Config + run: cp .env.example .env + - name: Run Tests with strict mode run: | ./bashunit --parallel --simple --strict tests/ From c58aff2f4539600fc2a6bfea32fe0bd07f98ebef Mon Sep 17 00:00:00 2001 From: antonio-gg-dev Date: Mon, 30 Mar 2026 13:00:43 +0200 Subject: [PATCH 02/12] fix: correct .env.example coverage threshold entry --- .env.example | 60 ++++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/.env.example b/.env.example index d57324f1..f3682d1b 100644 --- a/.env.example +++ b/.env.example @@ -7,54 +7,54 @@ #─────────────────────────────────────────────────────────────────────────────── # Test Discovery #─────────────────────────────────────────────────────────────────────────────── -BASHUNIT_DEFAULT_PATH= # Default: tests -BASHUNIT_BOOTSTRAP= # Default: tests/bootstrap.sh -BASHUNIT_BOOTSTRAP_ARGS= # Arguments passed to bootstrap script +BASHUNIT_DEFAULT_PATH= # Default: tests +BASHUNIT_BOOTSTRAP= # Default: tests/bootstrap.sh +BASHUNIT_BOOTSTRAP_ARGS= # Arguments passed to bootstrap script #─────────────────────────────────────────────────────────────────────────────── # Output Display #─────────────────────────────────────────────────────────────────────────────── -BASHUNIT_SHOW_HEADER= # Default: true -BASHUNIT_HEADER_ASCII_ART= # Default: false -BASHUNIT_SIMPLE_OUTPUT= # Default: false (use dots instead of test names) -BASHUNIT_VERBOSE= # Default: false (show environment variables) -BASHUNIT_NO_OUTPUT= # Default: false (suppress all output) -BASHUNIT_SHOW_EXECUTION_TIME= # Default: true -BASHUNIT_SHOW_SKIPPED= # Default: false (show skipped test details) -BASHUNIT_SHOW_INCOMPLETE= # Default: false (show incomplete test details) -BASHUNIT_FAILURES_ONLY= # Default: false (only show failures) -BASHUNIT_NO_COLOR= # Default: false (disable colors) +BASHUNIT_SHOW_HEADER= # Default: true +BASHUNIT_HEADER_ASCII_ART= # Default: false +BASHUNIT_SIMPLE_OUTPUT= # Default: false (use dots instead of test names) +BASHUNIT_VERBOSE= # Default: false (show environment variables) +BASHUNIT_NO_OUTPUT= # Default: false (suppress all output) +BASHUNIT_SHOW_EXECUTION_TIME= # Default: true +BASHUNIT_SHOW_SKIPPED= # Default: false (show skipped test details) +BASHUNIT_SHOW_INCOMPLETE= # Default: false (show incomplete test details) +BASHUNIT_FAILURES_ONLY= # Default: false (only show failures) +BASHUNIT_NO_COLOR= # Default: false (disable colors) #─────────────────────────────────────────────────────────────────────────────── # Test Execution #─────────────────────────────────────────────────────────────────────────────── -BASHUNIT_PARALLEL_RUN= # Default: false -BASHUNIT_STOP_ON_FAILURE= # Default: false (stop suite on first failure) +BASHUNIT_PARALLEL_RUN= # Default: false +BASHUNIT_STOP_ON_FAILURE= # Default: false (stop suite on first failure) BASHUNIT_STOP_ON_ASSERTION_FAILURE= # Default: true (stop test on first assertion fail) -BASHUNIT_STRICT_MODE= # Default: false (enable set -euo pipefail) -BASHUNIT_LOGIN_SHELL= # Default: false (source login shell profiles) +BASHUNIT_STRICT_MODE= # Default: false (enable set -euo pipefail) +BASHUNIT_LOGIN_SHELL= # Default: false (source login shell profiles) #─────────────────────────────────────────────────────────────────────────────── # Reports #─────────────────────────────────────────────────────────────────────────────── -BASHUNIT_LOG_JUNIT= # JUnit XML report path (e.g., report.xml) -BASHUNIT_REPORT_HTML= # HTML test report path (e.g., report.html) +BASHUNIT_LOG_JUNIT= # JUnit XML report path (e.g., report.xml) +BASHUNIT_REPORT_HTML= # HTML test report path (e.g., report.html) #─────────────────────────────────────────────────────────────────────────────── # Code Coverage #─────────────────────────────────────────────────────────────────────────────── -BASHUNIT_COVERAGE= # Default: false -BASHUNIT_COVERAGE_PATHS= # Default: src/ (comma-separated paths to track) -BASHUNIT_COVERAGE_EXCLUDE= # Default: tests/*,vendor/*,*_test.sh,*Test.sh -BASHUNIT_COVERAGE_REPORT= # Default: coverage/lcov.info -BASHUNIT_COVERAGE_REPORT_HTML= # HTML coverage report directory (e.g., coverage/html) -BASHUNIT_COVERAGE_MIN= # Minimum coverage % (fails if below) -BASHUNIT_COVERAGE_THRESHOLD_LOW= # Default: 50 (red below this) -BASHUNIT_COVERAGE_THRESHOLD_HIGH=# Default: 80 (green above this) +BASHUNIT_COVERAGE= # Default: false +BASHUNIT_COVERAGE_PATHS= # Default: src/ (comma-separated paths to track) +BASHUNIT_COVERAGE_EXCLUDE= # Default: tests/*,vendor/*,*_test.sh,*Test.sh +BASHUNIT_COVERAGE_REPORT= # Default: coverage/lcov.info +BASHUNIT_COVERAGE_REPORT_HTML= # HTML coverage report directory (e.g., coverage/html) +BASHUNIT_COVERAGE_MIN= # Minimum coverage % (fails if below) +BASHUNIT_COVERAGE_THRESHOLD_LOW= # Default: 50 (red below this) +BASHUNIT_COVERAGE_THRESHOLD_HIGH= # Default: 80 (green above this) #─────────────────────────────────────────────────────────────────────────────── # Advanced / Debug #─────────────────────────────────────────────────────────────────────────────── -BASHUNIT_DEV_LOG= # Developer log file path -BASHUNIT_BENCH_MODE= # Default: false (benchmark mode) -BASHUNIT_INTERNAL_LOG= # Default: false (internal debug logging) +BASHUNIT_DEV_LOG= # Developer log file path +BASHUNIT_BENCH_MODE= # Default: false (benchmark mode) +BASHUNIT_INTERNAL_LOG= # Default: false (internal debug logging) From 118030a37de90746cdff60452aa6cda65f179796 Mon Sep 17 00:00:00 2001 From: antonio-gg-dev Date: Mon, 30 Mar 2026 13:15:32 +0200 Subject: [PATCH 03/12] docs: update changelog for env example CI fix --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ff9f45b..111be382 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Fixed - Fix spying on `echo` or `printf` causing bashunit to hang due to infinite recursion (#607) +- Fix invalid `.env.example` coverage threshold entry and copy `.env.example` to `.env` in CI test workflows so configuration parse errors are caught during automated test runs ## [0.34.1](https://github.com/TypedDevs/bashunit/compare/0.34.0...0.34.1) - 2026-03-20 From 314c79fe46ed5dd89f0e4d4a6913354abc807cc9 Mon Sep 17 00:00:00 2001 From: antonio-gg-dev Date: Mon, 30 Mar 2026 13:36:09 +0200 Subject: [PATCH 04/12] fix: support comma decimal separator in shell clock --- CHANGELOG.md | 1 + src/clock.sh | 7 +++++-- tests/unit/clock_test.sh | 6 ++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 111be382..0b2f5927 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Fixed - Fix spying on `echo` or `printf` causing bashunit to hang due to infinite recursion (#607) - Fix invalid `.env.example` coverage threshold entry and copy `.env.example` to `.env` in CI test workflows so configuration parse errors are caught during automated test runs +- Fix `clock::now` shell-time parsing when `EPOCHREALTIME` uses a comma decimal separator ## [0.34.1](https://github.com/TypedDevs/bashunit/compare/0.34.0...0.34.1) - 2026-03-20 diff --git a/src/clock.sh b/src/clock.sh index 3a3b9281..51641a71 100644 --- a/src/clock.sh +++ b/src/clock.sh @@ -113,8 +113,11 @@ EOF shell) # shellcheck disable=SC2155 local shell_time="$(bashunit::clock::shell_time)" - local seconds="${shell_time%%.*}" - local microseconds="${shell_time#*.}" + local seconds="${shell_time%%[.,]*}" + local microseconds="${shell_time#*[.,]}" + if [ "$seconds" = "$shell_time" ]; then + microseconds="" + fi # Pad to 6 digits and strip leading zeros for arithmetic microseconds="${microseconds}000000" microseconds="${microseconds:0:6}" diff --git a/tests/unit/clock_test.sh b/tests/unit/clock_test.sh index 39f52c70..86f5befb 100644 --- a/tests/unit/clock_test.sh +++ b/tests/unit/clock_test.sh @@ -124,6 +124,12 @@ function test_now_prefers_shell_time_over_perl() { assert_same "1234567890000" "$(bashunit::clock::now)" } +function test_now_handles_shell_time_with_comma_decimal_separator() { + bashunit::mock bashunit::clock::shell_time <<<"1234,567890" + + assert_same "1234567890000" "$(bashunit::clock::now)" +} + function test_now_prefers_python_over_node() { bashunit::mock bashunit::clock::shell_time mock_non_existing_fn bashunit::mock date mock_non_existing_fn From 985798c0bb2a83cd36aeef04dd141f9705e8beb3 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Mon, 30 Mar 2026 13:52:07 +0200 Subject: [PATCH 05/12] fix(env): add --skip-env-file to tests where .env clobbers env vars The .env file sourcing overwrites BASHUNIT_BOOTSTRAP_ARGS and BASHUNIT_NO_COLOR set by the test environment or early flag scan. --- tests/acceptance/bashunit_bootstrap_args_test.sh | 2 +- tests/acceptance/bashunit_no_color_test.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/acceptance/bashunit_bootstrap_args_test.sh b/tests/acceptance/bashunit_bootstrap_args_test.sh index 4f54dbd0..dc91a087 100644 --- a/tests/acceptance/bashunit_bootstrap_args_test.sh +++ b/tests/acceptance/bashunit_bootstrap_args_test.sh @@ -26,7 +26,7 @@ function test_bootstrap_args_via_env_variable() { # Use --env flag to set the bootstrap file (avoiding .env override), # but use BASHUNIT_BOOTSTRAP_ARGS from environment output=$(BASHUNIT_BOOTSTRAP_ARGS="hello world" \ - ./bashunit --no-parallel --simple \ + ./bashunit --no-parallel --simple --skip-env-file \ --env "tests/acceptance/fixtures/bootstrap_with_args.sh" \ tests/acceptance/fixtures/test_bootstrap_args.sh 2>&1) || true diff --git a/tests/acceptance/bashunit_no_color_test.sh b/tests/acceptance/bashunit_no_color_test.sh index 52647362..1bb7329c 100644 --- a/tests/acceptance/bashunit_no_color_test.sh +++ b/tests/acceptance/bashunit_no_color_test.sh @@ -8,7 +8,7 @@ function set_up_before_script() { function test_bashunit_no_color_flag_disables_colors() { local test_file=./tests/acceptance/fixtures/test_bashunit_when_a_test_passes.sh local output - output=$(./bashunit --no-parallel --env "$TEST_ENV_FILE" "$test_file" --no-color --simple) + output=$(./bashunit --no-parallel --skip-env-file --env "$TEST_ENV_FILE" "$test_file" --no-color --simple) # ANSI escape codes start with \x1b[ (ESC[) - should not be present assert_not_contains $'\e[' "$output" From 685f011e6e73d9a338e7dddcb7c1315c42d073f5 Mon Sep 17 00:00:00 2001 From: antonio-gg-dev Date: Mon, 30 Mar 2026 14:57:00 +0200 Subject: [PATCH 06/12] ci: add localized linux test matrix --- .github/workflows/tests.yml | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d41afebb..5900b52c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -23,6 +23,45 @@ jobs: - name: Run Tests run: make test + localized-ubuntu: + name: "Ubuntu - ${{ matrix.name }} Locale" + runs-on: ubuntu-latest + timeout-minutes: 10 + strategy: + fail-fast: false + matrix: + include: + - name: "Spanish" + lang: "es_ES.UTF-8" + tz: "Europe/Madrid" + - name: "Brazilian" + lang: "pt_BR.UTF-8" + tz: "America/Sao_Paulo" + - name: "Japanese" + lang: "ja_JP.UTF-8" + tz: "Asia/Tokyo" + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Install locales + run: | + sudo apt-get update + sudo apt-get install -y locales + sudo locale-gen "${{ matrix.lang }}" + + - name: Setup Config + run: cp .env.example .env + + - name: Run Tests + env: + LANG: ${{ matrix.lang }} + LC_ALL: ${{ matrix.lang }} + TZ: ${{ matrix.tz }} + run: make test + macos: name: "macOS - latest" runs-on: macos-latest From 71f9657cca591d463eac53711aa7835483f50474 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Mon, 30 Mar 2026 15:13:55 +0200 Subject: [PATCH 07/12] fix(assert): use UTC on both sides of Z-suffix date test The test compared local time with UTC time, which only passes when the system timezone is UTC. Fails in CET, JST, BRT locale CI jobs. --- tests/unit/assert_dates_test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/assert_dates_test.sh b/tests/unit/assert_dates_test.sh index 57f9cff5..59267afc 100644 --- a/tests/unit/assert_dates_test.sh +++ b/tests/unit/assert_dates_test.sh @@ -152,10 +152,10 @@ function test_successful_assert_date_equals_epoch_vs_space_separated() { assert_empty "$(assert_date_equals "$epoch" "2023-11-14 12:00:00")" } -# UTC Z suffix test (documents existing behavior) +# UTC Z suffix test function test_successful_assert_date_equals_with_utc_z_suffix() { - assert_empty "$(assert_date_equals "2023-11-14T12:00:00" "2023-11-14T12:00:00Z")" + assert_empty "$(assert_date_equals "2023-11-14T12:00:00Z" "2023-11-14T12:00:00Z")" } # Timezone offset tests From ee2d5aadcb83c1154a5a0c4f531f864c4cbdba26 Mon Sep 17 00:00:00 2001 From: antonio-gg-dev Date: Mon, 30 Mar 2026 14:37:54 +0200 Subject: [PATCH 08/12] test: fix UTC Z date assertion case --- tests/unit/assert_dates_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/assert_dates_test.sh b/tests/unit/assert_dates_test.sh index 59267afc..169763e8 100644 --- a/tests/unit/assert_dates_test.sh +++ b/tests/unit/assert_dates_test.sh @@ -155,7 +155,7 @@ function test_successful_assert_date_equals_epoch_vs_space_separated() { # UTC Z suffix test function test_successful_assert_date_equals_with_utc_z_suffix() { - assert_empty "$(assert_date_equals "2023-11-14T12:00:00Z" "2023-11-14T12:00:00Z")" + assert_empty "$(assert_date_equals "2023-11-14T14:00:00+0200" "2023-11-14T12:00:00Z")" } # Timezone offset tests From 0e04c19b6a753e3284683a9438fef6b483c9d7dc Mon Sep 17 00:00:00 2001 From: antonio-gg-dev Date: Mon, 30 Mar 2026 15:41:52 +0200 Subject: [PATCH 09/12] ci: probe localized shell errors in matrix --- .github/workflows/tests.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5900b52c..1ce9d971 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -34,12 +34,15 @@ jobs: - name: "Spanish" lang: "es_ES.UTF-8" tz: "Europe/Madrid" + probe_error: "orden no encontrada" - name: "Brazilian" lang: "pt_BR.UTF-8" tz: "America/Sao_Paulo" + probe_error: "" - name: "Japanese" lang: "ja_JP.UTF-8" tz: "Asia/Tokyo" + probe_error: "" steps: - name: Checkout uses: actions/checkout@v4 @@ -49,9 +52,20 @@ jobs: - name: Install locales run: | sudo apt-get update - sudo apt-get install -y locales + sudo apt-get install -y locales ${{ matrix.lang == 'es_ES.UTF-8' && 'language-pack-es-base' || '' }} sudo locale-gen "${{ matrix.lang }}" + - name: Probe localized shell error + if: ${{ matrix.probe_error != '' }} + env: + LANG: ${{ matrix.lang }} + LC_ALL: ${{ matrix.lang }} + TZ: ${{ matrix.tz }} + run: | + set -euo pipefail + bash -lc 'invalid_function_name' 2>&1 | tee /tmp/bash-locale-probe.txt || true + grep -q "${{ matrix.probe_error }}" /tmp/bash-locale-probe.txt + - name: Setup Config run: cp .env.example .env From a122c56f7f38c91498b0d55a7435c32f2cdcce17 Mon Sep 17 00:00:00 2001 From: antonio-gg-dev Date: Mon, 30 Mar 2026 15:47:50 +0200 Subject: [PATCH 10/12] ci: install locale packs in localized matrix --- .github/workflows/tests.yml | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1ce9d971..c5e95996 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -34,15 +34,15 @@ jobs: - name: "Spanish" lang: "es_ES.UTF-8" tz: "Europe/Madrid" - probe_error: "orden no encontrada" + language_pack: "language-pack-es-base" - name: "Brazilian" lang: "pt_BR.UTF-8" tz: "America/Sao_Paulo" - probe_error: "" + language_pack: "language-pack-pt-base" - name: "Japanese" lang: "ja_JP.UTF-8" tz: "Asia/Tokyo" - probe_error: "" + language_pack: "language-pack-ja-base" steps: - name: Checkout uses: actions/checkout@v4 @@ -52,20 +52,9 @@ jobs: - name: Install locales run: | sudo apt-get update - sudo apt-get install -y locales ${{ matrix.lang == 'es_ES.UTF-8' && 'language-pack-es-base' || '' }} + sudo apt-get install -y locales "${{ matrix.language_pack }}" sudo locale-gen "${{ matrix.lang }}" - - name: Probe localized shell error - if: ${{ matrix.probe_error != '' }} - env: - LANG: ${{ matrix.lang }} - LC_ALL: ${{ matrix.lang }} - TZ: ${{ matrix.tz }} - run: | - set -euo pipefail - bash -lc 'invalid_function_name' 2>&1 | tee /tmp/bash-locale-probe.txt || true - grep -q "${{ matrix.probe_error }}" /tmp/bash-locale-probe.txt - - name: Setup Config run: cp .env.example .env From 627e6b45650e59b355a798c5ae17d96829a02d2a Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Mon, 30 Mar 2026 15:50:29 +0200 Subject: [PATCH 11/12] fix(assert): handle timezone offsets in date parsing for BusyBox --- src/assert_dates.sh | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/assert_dates.sh b/src/assert_dates.sh index fa33486a..849aff9d 100644 --- a/src/assert_dates.sh +++ b/src/assert_dates.sh @@ -12,10 +12,25 @@ function bashunit::date::to_epoch() { ;; esac - # Normalize ISO 8601: replace T with space, strip Z suffix, strip tz offset + # Handle Z (UTC) suffix explicitly: BusyBox needs TZ=UTC, BSD needs +0000 + case "$input" in + *Z) + local utc_input="${input%Z}" + local utc_norm="${utc_input/T/ }" + local epoch + # GNU/BusyBox: parse in explicit UTC + epoch=$(TZ=UTC date -d "$utc_input" +%s 2>/dev/null) && { echo "$epoch"; return 0; } + epoch=$(TZ=UTC date -d "$utc_norm" +%s 2>/dev/null) && { echo "$epoch"; return 0; } + # BSD: use +0000 offset which %z understands + epoch=$(date -j -f "%Y-%m-%dT%H:%M:%S%z" "${utc_input}+0000" +%s 2>/dev/null) && { echo "$epoch"; return 0; } + echo "$input" + return 1 + ;; + esac + + # Normalize ISO 8601: replace T with space, strip tz offset local normalized="$input" normalized="${normalized/T/ }" - normalized="${normalized%Z}" # Strip timezone offset (+HHMM or -HHMM) at end for initial parsing case "$normalized" in *[+-][0-9][0-9][0-9][0-9]) @@ -30,6 +45,24 @@ function bashunit::date::to_epoch() { echo "$epoch" return 0 } + # If input has timezone offset, parse in UTC and adjust manually (BusyBox) + case "$input" in + *[+-][0-9][0-9][0-9][0-9]) + epoch=$(TZ=UTC date -d "$normalized" +%s 2>/dev/null) && { + local ilen=${#input} + local ostart=$((ilen - 5)) + local osign="${input:$ostart:1}" + local ohh="${input:$((ostart + 1)):2}" + local omm="${input:$((ostart + 3)):2}" + local osecs=$(( (10#$ohh * 3600) + (10#$omm * 60) )) + if [ "$osign" = "+" ]; then + osecs=$(( -osecs )) + fi + echo $(( epoch + osecs )) + return 0 + } + ;; + esac # Try GNU date with normalized (space-separated) input if [ "$normalized" != "$input" ]; then epoch=$(date -d "$normalized" +%s 2>/dev/null) && { From c7ffe3b32f2e0e064ef85f44faaff7e9776d7326 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Mon, 30 Mar 2026 16:40:33 +0200 Subject: [PATCH 12/12] test: use locale-independent assertions in error acceptance tests --- tests/acceptance/bashunit_execution_error_test.sh | 2 +- tests/acceptance/bashunit_setup_before_script_error_test.sh | 2 +- tests/acceptance/bashunit_setup_error_test.sh | 2 +- tests/acceptance/bashunit_teardown_after_script_error_test.sh | 2 +- tests/acceptance/bashunit_teardown_error_test.sh | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/acceptance/bashunit_execution_error_test.sh b/tests/acceptance/bashunit_execution_error_test.sh index 59eb3c48..d59687f1 100644 --- a/tests/acceptance/bashunit_execution_error_test.sh +++ b/tests/acceptance/bashunit_execution_error_test.sh @@ -25,7 +25,6 @@ function test_bashunit_when_a_execution_error() { printf "%sRunning ./tests/acceptance/fixtures/test_bashunit_when_a_execution_error.sh%s\n" \ "${color_bold}" "${color_default}" printf "%s✗ Error%s: Error\n" "${color_red}" "${color_default}" - printf " %sline 4: invalid_function_name: command not found%s\n" "${color_dim}" "${color_default}" ) local fixture_end=$( format_summary_title "Tests: " @@ -39,6 +38,7 @@ function test_bashunit_when_a_execution_error() { local actual="$(./bashunit --no-parallel --detailed --env "$TEST_ENV_FILE" "$test_file")" assert_contains "$fixture_start" "$actual" + assert_contains "invalid_function_name" "$actual" assert_contains "$fixture_end" "$actual" assert_general_error "$(./bashunit --no-parallel --env "$TEST_ENV_FILE" "$test_file")" } diff --git a/tests/acceptance/bashunit_setup_before_script_error_test.sh b/tests/acceptance/bashunit_setup_before_script_error_test.sh index 1fa15819..b6f25071 100644 --- a/tests/acceptance/bashunit_setup_before_script_error_test.sh +++ b/tests/acceptance/bashunit_setup_before_script_error_test.sh @@ -15,7 +15,7 @@ function test_bashunit_when_set_up_before_script_errors() { local header_line="Running $fixture" local error_line="✗ Error: Set up before script" - local message_line=" $fixture: line 4: invalid_function_name: command not found" + local message_line="invalid_function_name" local tests_summary="Tests: 1 failed, 1 total" local assertions_summary="Assertions: 0 failed, 0 total" diff --git a/tests/acceptance/bashunit_setup_error_test.sh b/tests/acceptance/bashunit_setup_error_test.sh index 70d4ebf8..8f924366 100644 --- a/tests/acceptance/bashunit_setup_error_test.sh +++ b/tests/acceptance/bashunit_setup_error_test.sh @@ -15,7 +15,7 @@ function test_bashunit_when_set_up_errors() { local header_line="Running $fixture" local error_line="✗ Error: Set up" - local message_line=" $fixture: line 4: invalid_function_name: command not found" + local message_line="invalid_function_name" local tests_summary="Tests: 1 failed, 1 total" local assertions_summary="Assertions: 0 failed, 0 total" diff --git a/tests/acceptance/bashunit_teardown_after_script_error_test.sh b/tests/acceptance/bashunit_teardown_after_script_error_test.sh index 03878918..955b1633 100644 --- a/tests/acceptance/bashunit_teardown_after_script_error_test.sh +++ b/tests/acceptance/bashunit_teardown_after_script_error_test.sh @@ -15,7 +15,7 @@ function test_bashunit_when_tear_down_after_script_errors() { local header_line="Running $fixture" local error_line="✗ Error: Tear down after script" - local message_line=" $fixture: line 4: missing_cleanup_command: command not found" + local message_line="missing_cleanup_command" local tests_summary="Tests: 1 passed, 1 failed, 2 total" local assertions_summary="Assertions: 1 passed, 0 failed, 1 total" diff --git a/tests/acceptance/bashunit_teardown_error_test.sh b/tests/acceptance/bashunit_teardown_error_test.sh index d127a12e..ee65205f 100644 --- a/tests/acceptance/bashunit_teardown_error_test.sh +++ b/tests/acceptance/bashunit_teardown_error_test.sh @@ -15,7 +15,7 @@ function test_bashunit_when_tear_down_errors() { local header_line="Running $fixture" local error_line="✗ Error: Tear down" - local message_line=" $fixture: line 4: invalid_function_name: command not found" + local message_line="invalid_function_name" local tests_summary="Tests: 1 failed, 1 total" local assertions_summary="Assertions: 0 failed, 0 total"