Skip to content

Add Handlebars.js behavioral spec, coverage tests, and net10 dev environment#616

Merged
rexm merged 10 commits into
masterfrom
spec-coverage-tests
Jun 19, 2026
Merged

Add Handlebars.js behavioral spec, coverage tests, and net10 dev environment#616
rexm merged 10 commits into
masterfrom
spec-coverage-tests

Conversation

@rexm

@rexm rexm commented Jun 19, 2026

Copy link
Copy Markdown
Member

Summary

  • HandlebarsSpec.md — exhaustive behavioral specification derived from the canonical Handlebars.js spec files (spec/*.js), the Mustache spec, official docs, and source analysis. 32 sections covering every feature of the templating language. Includes a new Known Implementation Gaps section documenting 5 confirmed behavioral differences from Handlebars.js, each with root cause and backward-compatibility risk rating.

  • HandlebarsSpecCoverageTests.cs — ~100 test methods across 22 behavioral categories covering areas not exercised by the existing suite (HTML encoding edge cases, whitespace control, #each data variables, block params, subexpressions, partials, decorators, helper interactions, etc.). Uses the existing HandlebarsEnvGenerator pattern so every test runs across 5 IHandlebars configurations.

  • Dev environment update — bumped Handlebars.Test and Handlebars.Benchmark from EOL netcoreapp3.1/net6 targets to net10.0; updated Microsoft.NET.Test.Sdk and BenchmarkDotNet to current versions.

Documented implementation gaps (tests assert current behavior as regressions)

Gap Spec says Current behavior Fix risk
Default HTML encoder omits ' ` = Encode all 7 special chars HtmlEncoderLegacy (default) skips 3; HtmlEncoder (opt-in) is correct HIGH
{{log}} not registered No output, calls logger HandlebarsRuntimeException at render time LOW
false renders as "False" "false" (lowercase) .NET bool.ToString()"False" MEDIUM
Whitespace control on comments {{~! x ~}} strips whitespace Inline: no strip; block: parse error LOW
{{^}} bare caret as else {{#x}}a{{^}}b{{/x}} like {{else}} Resolves to context.ToString(); use {{else}} LOW

Test plan

  • dotnet test — 1746/1746 passing (all pre-existing tests plus new coverage tests)
  • No library code was changed — all gaps are documented with regression tests only

rexm and others added 9 commits June 18, 2026 20:11
…ronment to net10

- Add HandlebarsSpec.md: exhaustive Handlebars.js behavioral specification derived
  from the JS spec files, documentation, and the Mustache spec (32 sections, 200+
  behaviors, and a new Known Implementation Gaps section documenting 5 confirmed
  deviations from the canonical spec with root causes and compat risk ratings)

- Add HandlebarsSpecCoverageTests.cs: ~100 test methods across 22 behavioral categories
  covering areas not exercised by the existing suite. 1746/1746 tests pass.
  Gap tests assert current (non-spec-compliant) behavior as documented regressions so
  that any future changes in those areas are detected immediately.

- Update test and benchmark projects to target net10.0; drop EOL frameworks
  (netcoreapp3.1, net6, net452, net46, net461); bump BenchmarkDotNet and
  Microsoft.NET.Test.Sdk to current versions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- actions/checkout v2/master → v4
- actions/setup-dotnet v1 → v4; SDK versions 2.1.x/3.1.x/6.0.x → 6.0.x/10.0.x
  (2.1.x and 3.1.x are EOL and no longer available; 10.0.x needed for net10 test target)
- actions/cache v1 → v4
- actions/upload-artifact v2 → v4 (v2 was shut off by GitHub, causing benchmark job to fail)
- actions/setup-java v4 already current; left unchanged
- Fix deprecated ::set-output syntax → $GITHUB_OUTPUT in benchmark job
- sonar.login → sonar.token (sonar.login deprecated in recent SonarScanner versions)
- Remove stale nuget cache-clearing workaround (setup-dotnet/issues/155 is long fixed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
BenchmarkDotNet auto-detects all installed runtimes on the runner; ubuntu-latest
has .NET Core 3.1 pre-installed, causing it to generate a netcoreapp3.1 subprocess
project that is incompatible with the benchmark project's net10.0 target (NU1201).
Pinning to -f net10.0 constrains BenchmarkDotNet to the single supported TFM.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Program.cs was explicitly forcing BenchmarkDotNet to use the .NET Core 3.1
toolchain (CsProjCoreToolchain.NetCoreApp31), which broke once the benchmark
project moved to net10.0. Dropping the explicit toolchain lets BenchmarkDotNet
use the current process runtime (net10.0 via dotnet run -f net10.0 in CI).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
windows-2019 runners have stalled at queue on two consecutive runs tonight
(24+ min each vs 2-13s historical baseline). Switching to windows-latest
(Server 2022) which was used in prior successful runs on this repo.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SonarCloud quality gate failing on security hotspot S7637 — third-party
GitHub Actions referenced by floating tags rather than commit SHAs, which
allows supply-chain attacks if a tag is moved.

Pin:
  Happypig375/github-action-benchmark@v1.8.2 → @e7cb068
  release-drafter/release-drafter@v5         → @09c613e

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t> key param empty on Linux/Windows)

On Linux and Windows, the 'key' block param was not bound when iterating
Dictionary<string, int> in #each. Switch to Dictionary<string, object>
(consistent with existing DictionaryEnumeratorWithBlockParams) and rename
block params to itemVal/itemKey to avoid any ambiguity with built-in names.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
S6702: SONAR_TOKEN was hardcoded in plain text in both workflow files.
Move to ${{ secrets.SONAR_TOKEN }} and reference via $env:SONAR_TOKEN
in the PowerShell run blocks.

S7630: pull_request.yml used github.event.pull_request.head.ref directly
in a run block, enabling script injection from external actors. Bind the
PR context expressions to env vars (PR_KEY, PR_BRANCH, PR_BASE) and
reference them as $env:* in the PowerShell command.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rexm rexm requested a review from oformaniuk June 19, 2026 02:31
@rexm

rexm commented Jun 19, 2026

Copy link
Copy Markdown
Member Author

@oformaniuk we're back baby

windows-2019 runners were stalling (same issue seen previously in pull_request.yml).
windows-latest uses the current stable runner pool and picks up in seconds.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@rexm rexm merged commit 839dcde into master Jun 19, 2026
7 checks passed
@rexm rexm deleted the spec-coverage-tests branch June 19, 2026 03:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants