Skip to content

Releases: varar-dev/varar

v0.8.0

Choose a tag to compare

@aslakhellesoy aslakhellesoy released this 07 Sep 08:32

TypeScript (npm)

  • ⚠️ Breaking: cli: Varar run is gone — oaths run through your own test runner
    varar run has been removed. Run oaths with your test runner
    instead — pnpm vitest run, and VARAR_UPDATE=1 pnpm vitest run to accept
    drift and re-record varar.lock.json. varar init scaffolds the vitest wiring
    for you. renderFailure is no longer exported from @varar/runner.
  • Added: cli: Varar init scaffolds oaths into varar/ and steps into src/varar/
  • Added: core: A failure records the failing step's span, so editors underline the step and not its whole line
  • Added: cli: Varar run --json prints the run as machine-readable results
  • Added: vitest: The reporter records varar.lock.json, so vitest no longer needs varar run
  • Added: cli: Varar init scaffolds the test-runner config, so one command leaves a runnable project
  • Fixed: Examples/typescript-vitest commits pnpm-workspace.yaml so its suite runs anywhere
  • Fixed: language: @varar/language no longer installs the TypeScript compiler
  • Fixed: cli: Varar lint checks oaths against the step definitions they bind to
  • Fixed: vitest: The vitest sample writes run records, and the reporter orders them
  • Fixed: cli: Varar run writes the run record every other port's runner writes

Python (PyPI)

  • Added: runner: Varar init scaffolds oaths into varar/ and steps into tests/varar/
  • Added: config: Parse_varar_config validates config text without a file
  • Added: Pytest and unittest write run results, so editors show Python failures
  • Fixed: runner: Varar init scaffolds the Deep Thought example, matching the TypeScript CLI
  • Fixed: runner: List run-record examples in document order

Java & Kotlin (Maven Central)

  • Added: junit: Steps entries support package wildcards — ["varar.*"] loads every step class in the package
  • Added: JUnit and Kotest write run results, so editors show JVM failures
  • Fixed: Gradle samples re-run the suite when an oath or the baseline changes

Ruby (RubyGems)

  • Added: runner: Varar init scaffolds oaths into varar/ and steps into spec/varar/ or test/varar/
  • Added: config: Parse_var_config validates config text without a file
  • Added: RSpec and Minitest write run results, so editors show Ruby failures
  • Fixed: runner: Varar init scaffolds the Deep Thought example, matching the TypeScript CLI
  • Fixed: runner: List run-record examples in document order

Rust (crates.io)

  • Added: config: Parse_var_config validates config text without a file
  • Added: Cargo test writes run results, so editors show Rust failures
  • Fixed: Skip scanning dirs that can't match
  • Fixed: runner: Stop discovery pruning subtrees that can still hold oaths
  • Fixed: runner: List run-record examples in document order

C# / .NET (NuGet)

  • Fixed: vstest: Dotnet test enforces the drift gate — a paragraph that stopped matching fails the run

Go (Go modules)

  • Added: config: ParseVarConfig validates config text without a file

VS Code extension (Marketplace & Open VSX)

  • Added: Publish the extension to the VS Code Marketplace

Specification (all ports)

  • ⚠️ Breaking: The spec concept is renamed to oath — varar.lock.json is now version 2 with an "oaths" key
    varar.lock.json is now {"version": 2, "oaths": {...}}
    delete the old lock file and re-run with the update flag (varar run --update / VARAR_UPDATE=1) to regenerate it; version-1 files no longer
    parse. Renamed APIs in every port (per-language casing): SpecBaseline →
    OathBaseline, SpecResults → OathResults, deriveSpecBaseline →
    deriveOathBaseline, findSpecs/matchSpec/planSpec →
    findOaths/matchOath/planOath. The JUnit engine's UniqueId segment type is
    now "oath" (was "spec") and the VSTest property Varar.SpecPath is now
    Varar.OathPath. The scaffolded JVM suite class is RunOathsTest, the Go
    example test is TestOaths in oaths_test.go, and the Rust example harness
    is tests/oaths.rs.
  • ⚠️ Breaking: Drop the redundant Var prefix from every identifier and key
    every Var-prefixed public identifier is renamed. Types:
    VarDoc -> Doc, VarConfig -> Config (C#: the reader is ConfigFile, the record
    ParsedConfig), VarLock -> LockFile, VarGlobs -> Globs, VarConfigException ->
    ConfigException, VarDocArtifact -> DocArtifact, VarSpec -> OathSpec. Functions
    (per-language casing): parseVarLock -> parseLockFile, stringifyVarLock ->
    stringifyLockFile, pruneVarLock -> pruneLockFile, parseVarConfig -> parseConfig,
    loadVarConfig/read_var_config/ReadVarConfig -> loadConfig/read_config/ReadConfig,
    isVarDoc -> isDoc, toVarDocArtifact -> toDocArtifact. Go value conversion:
    DecodeVarValue/EncodeVarValue -> DecodeValue/EncodeValue. The ExecutionPlan
    field varDoc/var_doc is now doc. JUnit configuration parameters var.config.root
    and var.acceptDrift are now varar.config.root and varar.acceptDrift. Run results
    move from .var/ to .varar/ — update your .gitignore. Vitest task meta varResult
    is now vararResult. Generated test names var:drift:/var:diagnostic: are now
  • ⚠️ Breaking: Rename varPath to oathPath
    @varar/language's WorkspaceMatch.varPath and
    WorkspaceDiagnostic.varPath are now oathPath, and @varar/vitest's
    DiscoverInput.varPath is now absPath.
  • Added: A failure records the failing step's span in Python, Java, Kotlin and Rust too
  • Added: Ruby, .NET and Go gain the run-result failure payload
  • Added: .NET and Go write run results — every port now feeds the language server
  • Added: The run-result wire format is pinned across all seven ports
  • Fixed: Accepting drift prunes varar.lock.json entries for oaths that no longer exist

v0.7.0

Choose a tag to compare

@aslakhellesoy aslakhellesoy released this 23 Jul 09:15

TypeScript (npm)

  • ⚠️ Breaking: Stimulus handlers are typed to return the complete next state, not a partial
    A stimulus handler's return type is now C | void instead of
    Partial<C> | void. The runtime always REPLACED state with what the handler
    returned — there was never a merge — so Partial<C> type-checked the one thing
    the semantics forbid: a return that omits a field silently dropped it while
    every later step kept the full C type. Returns that were partial now fail to
    type-check; spread the current state to keep the rest, e.g.
    (state) => ({ ...state, count: 1 }).
  • ⚠️ Breaking: var-vitest: Exported names are Varar-prefixed
    @varar/vitest's exports are renamed to match the product name:
    VarResultsReporter → VararResultsReporter, VarResultsReporterOptions →
    VararResultsReporterOptions, VarVitestPluginOptions → VararVitestPluginOptions,
    varVitestPlugin → vararVitestPlugin (the default export, so import vararPlugin from '@varar/vitest' needs no change), collectVarExamples →
    collectVararExamples, varTestBody → vararTestBody, isVarSpecId → isVararSpecId.
    The old names are gone. CollectPorts keeps its name — it carries no product
    prefix and is parallel to the same type in the other ports.
  • Added: var-cli: Varar init makes the project ESM so the scaffolded steps file loads
  • Added: var-cli: Varar run explains the two reasons Node refuses a step file
  • Fixed: Commit the generated pnpm-workspace.yaml in the synced sample
  • Fixed: Published packages report their real version in VERSION, not 0.0.0

Ruby (RubyGems)

  • Fixed: Describe the gems as Varar, not Vár

C# / .NET (NuGet)

  • Added: Ship the C# sample in varar-examples

VS Code extension (Marketplace & Open VSX)

  • Fixed: Highlight only the captured value of a step parameter, not its surrounding notation

Specification (all ports)

  • ⚠️ Breaking: Steps receive the state your factory made, never frozen or retyped
    State is no longer deep-frozen at runtime, and TypeScript
    handlers receive C instead of DeepReadonly<C>. Mutating state no longer
    throws at runtime nor fails to type-check — declare your own state type
    readonly if you want the compiler to stop you (in Java and Kotlin the
    record/data class already does). Evolution is still meant to happen by
    returning the next state; the relaxation is what lets state hold live objects
    such as a DB client or a page object, which freezing broke and a mapped
    readonly type made unassignable to its own declared type.
  • ⚠️ Breaking: Drift is accepted with VARAR_UPDATE, not VAR_UPDATE
    The environment variable that accepts drift is now
    VARAR_UPDATE in every adapter (vitest, the varar CLI, pytest, unittest,
    minitest, rspec, junit, kotest, gotest and cargotest); VAR_UPDATE is no longer
    recognized. pytest's flag is now --varar-update and the JUnit/Kotest system
    property is now varar.update. Set VARAR_UPDATE=1 (or true) where you set
    VAR_UPDATE=1 before.
  • ⚠️ Breaking: A sensor with slots that returns nothing now fails instead of silently passing
    A sensor whose expression has parameters — or a trailing data
    table or doc string — must return one value per slot. Returning
    undefined/None/null/nil previously skipped the comparison entirely and the
    example went green, so a typo in a property access turned an assertion into a
    no-op while the document went on claiming something nobody checked. It is now a
    ReturnShapeError ("a sensor with N slot(s) must return one value per slot, got
    nothing"), in every port. The same applies to a header-bound row step, which
    must return its row object.

Zero-slot sensors are unchanged: they must return nothing, and throwing is still
how they fail. Throwing remains a valid way to fail at any slot count — what is
no longer allowed is answering nothing at all when the document asked a
question. Where a greedy {word} capture made the slot awkward to echo back, the
fix is to match the punctuation in the expression ("The result is {word}.") so
the slot holds just the value being compared.

Rust drops the Asserted IntoSensor impls, which existed only to opt a slotted
sensor out of the comparison: the type system now rejects at compile time what
the other ports reject at run time.

  • ⚠️ Breaking: A doc-string mismatch is a cell mismatch
    A doc string is one cell, compared whole, so it no longer has
    an error of its own. DocStringMismatchError / DocStringDiff (and the
    isDocStringMismatchError guard) are gone from every port; a differing doc string
    now throws CellMismatchError carrying a single CellDiff whose column is
    "doc string". The run-result payload drops its doc field — a doc-string
    failure appears in cells like any other. Conformance traces lose the
    doc-string-mismatch failure kind; it is cell-mismatch now.

The message is unchanged: expected/actual stay quoted, so a doc string that
differs only by a trailing newline still shows a visible difference where a bare
cell would render none.

  • ⚠️ Breaking: An inline cell is labelled "cell N", not "arg N"
    A mismatched value captured from a paragraph is now labelled
    cell 1, cell 2, … instead of arg 1, arg 2. It shows up in the message
    (CellMismatchError: cell 1: expected £2.55 but was £2.60), in CellDiff.column,
    and in the conformance trace. "arg" named the handler's parameter; what differs
    is a cell in the document.
  • ⚠️ Breaking: An example runs until a heading, ---, or a non-matching paragraph (#65)
    Two step-only examples separated by only a blank line now run
    as a single shared-state example — separate them with a --- or a heading, and
    keep prose out of the middle of an example (a non-matching paragraph between
    steps ends the example). Additionally, Varar no longer runs Gherkin .feature
    files and the scannerPlugins config key has been removed (it is now an
    unknown-key error). Migrate .feature suites by translating them to Markdown
    specs and porting the step definitions.
  • Added: Add built-in {emph} parameter type for Markdown emphasis
  • Fixed: Sensor return errors name slots and cells consistently

v0.6.1

Choose a tag to compare

@aslakhellesoy aslakhellesoy released this 22 Jul 12:23

Java & Kotlin (Maven Central)

  • ⚠️ Breaking: Rename the JUnit TestEngine id from "var" to "varar"
    the JUnit Platform engine id is now varar. Update
    @IncludeEngines("var") to @IncludeEngines("varar"); anything else selecting the
    engine by id (EngineTestKit, --include-engine, IDE run configurations) needs
    the same change.

Rust (crates.io)

  • Added: Publish the Rust port to crates.io

v0.5.2

Choose a tag to compare

@aslakhellesoy aslakhellesoy released this 22 Jul 09:37

TypeScript (npm)

  • ⚠️ Breaking: Publish the TypeScript port under the @VarAR npm scope
    npm packages are renamed from the @oselvar scope to @VarAR.
    Update imports: @oselvar/var -> @varar/varar, @oselvar/var-vitest ->
    @varar/vitest, etc.

Python (PyPI)

  • ⚠️ Breaking: Publish the Python port under the varar distribution names
    PyPI distributions are renamed. Install varar /
    pytest-varar instead of oselvar-var / pytest-var, and import varar*
    instead of var*.

Java & Kotlin (Maven Central)

  • ⚠️ Breaking: Publish the JVM port under the dev.varar Maven coordinates
    Maven coordinates change from com.oselvar:var* to
  • ⚠️ Breaking: Steps.defineState is now Steps.state
    Java's Steps.defineState(factory) is now Steps.state(factory)
    and .NET's Steps.DefineState(factory) is now Steps.State(factory). Rename the
    call in each step file; there is no other change to the API.
  • Fixed: var-kotlin: Backtick-escape the var keyword in a Kotlin import so ktfmt passes

Ruby (RubyGems)

  • ⚠️ Breaking: Publish the Ruby port under the varar gem names
    RubyGems names change from oselvar-var* to varar*; require
    paths from 'oselvar/var...' to 'varar...'; and the module namespace from
  • ⚠️ Breaking: The state factory must be a proc, called fresh per example
    steps no longer accepts a Hash or keyword arguments as the
    initial state — pass a Proc/lambda instead, e.g. steps(count: 0) becomes
    steps(-> { { count: 0 } }). Omitting the factory entirely, for stateless step
    files, is unchanged. Passing a Hash now raises ArgumentError with the rewrite.
  • Fixed: Update minitest gemspec dependency to ~> 6.0 and regenerate lockfile
  • Fixed: Update minitest to ~> 6.0 in examples/ruby-minitest Gemfile

Go (Go modules)

  • Added: Run your Markdown specs as Go tests with go get github.com/varar-dev/varar/go
  • Fixed: Keep conformance fixtures out of the published module

VS Code extension (Marketplace & Open VSX)

  • Fixed: Align @types/vscode with the supported VS Code floor

Specification (all ports)

  • ⚠️ Breaking: Rename the config/lock files, CLI command, and scaffold to varar
    rename var.config.json -> varar.config.json and
    var.lock.json -> varar.lock.json in your project, point "$schema" at
    varar.config.schema.json, and invoke the CLI as varar instead of var.
  • ⚠️ Breaking: A stimulus returns the complete next state, replacing it
    A stimulus must return the complete next state, not a partial
    one. In TypeScript, Python and Ruby a return that omits a field now drops that
    field instead of preserving it — spread the current state to keep it, e.g.
    (state) => ({ ...state, count: 1 }). Returning nothing still leaves state
    unchanged, and is now a no-op in Java, Rust and .NET rather than wiping state.
  • Added: Step handlers accept up to five captures in every port
  • Fixed: Every port words and quotes failure messages identically

v0.4.2

Choose a tag to compare

@aslakhellesoy aslakhellesoy released this 08 Jul 21:25

Java & Kotlin (Maven Central)

  • Fixed: var-config: Reject leading-dot JSON numbers and position invalid \u escape errors

v0.4.0

Choose a tag to compare

@aslakhellesoy aslakhellesoy released this 07 Jul 19:41

TypeScript (npm)

  • Added: var-core: Detect spec drift — a paragraph that was an example and now matches zero steps
  • Added: var-core: Drift re-identifies examples by text similarity, so moving and rewording never false-alarm
  • Added: var-core: Report drift as a Diagnostic and add a BaselineStore port
  • Added: var-core: ReconcileDrift orchestrates baseline read → detect → write through the BaselineStore port
  • Added: var-cli: Var run detects spec drift and gates on it
  • Added: var-vitest: Read-only drift gate — a spec whose example stopped matching fails the suite
  • Fixed: var: Resolve a step's source file from bundled, minified stack traces

Python (PyPI)

  • Added: var-core: Detect spec drift with a byte-identical var.lock.json baseline
  • Added: var-pytest: Pytest and unittest gate on spec drift, writing var.lock.json
  • Added: var-runner: Scaffold a starter project with var init

Java & Kotlin (Maven Central)

  • Added: var-core: Detect spec drift with a byte-identical var.lock.json baseline
  • Added: var-junit: The JUnit engine gates on spec drift
  • Added: var-kotest: Kotest VarSpec gates on spec drift

Ruby (RubyGems)

  • ⚠️ Breaking: var: Block-based step DSL
    step files no longer destructure steps into
    param, stimulus, sensor and call them with .call/.(). Move the
    registrations into a steps(...) do … end block and pass the initial state as
    an argument instead of a factory block.
  • Added: var-core: Scaffold the ruby workspace and port the UTF-16 span layer
  • Added: var-core: Parse Markdown specs to a var-doc AST with UTF-16 spans
  • Added: var-core: Register step definitions via cucumber-expressions
  • Added: var-core: Match steps and build execution plans
  • Added: var-core: Execute plans and compare returns against the document
  • Added: var-core: Detect spec drift with a byte-identical var.lock.json baseline
  • Added: var-config: Read var.config.json
  • Added: var-rspec: Run Markdown specs as RSpec examples
  • Added: var-runner: Scaffold a starter project with var init

VS Code extension (Marketplace & Open VSX)

  • Added: Drift shows as an editor warning with an "Accept as prose" quick fix
  • Added: Recognize Ruby step definitions in the editor
  • Fixed: Kotlin parameter types declared with raw-string regexes are now discovered

Specification (all ports)

  • ⚠️ Breaking: Custom parameter types pair parse with a format function — mismatches render in the document's notation
    declare a custom parameter type's transform function as
    parse (was transformer) in defineState (TypeScript), define_state (Python),
    Registrar.defineParameterType (Java) and parameterType (Kotlin).

  • ⚠️ Breaking: Step matching runs against raw inline text — markup is never stripped
    expressions that relied on emphasis stripping must move
    the markers into a parameter type (e.g. regexp /*[^*]+*/ with parse
    raw.slice(1, -1)); the var-doc artifact's inlineMap field is now
    segmentMap.

  • ⚠️ Breaking: Unify step authoring on steps() → param, stimulus, sensor
    the step-authoring API is renamed and restructured in every
    port; parse is now a varargs function over the capture groups.

  • TypeScript: const { stimulus, sensor } = defineState(factory, paramTypes)
    becomes const { stimulus, sensor } = steps(factory).param(name, regexp, parse?, format?).
    Chain .param() before destructuring to keep custom-param handler-arg
    inference.

  • Python: stimulus, sensor = define_state(factory, param_types=...) becomes
    param, stimulus, sensor = steps(factory), then
    param(name, regexp, parse=None, format=None).

  • Java: registrar.defineState(factory) becomes registrar.steps(factory),
    and registrar.defineParameterType(...) becomes s.param(name, Pattern, parse?, format?)
    on the returned binder (parse is a String... varargs SAM; a
    two-argument param(name, Pattern) gives identity parse).

  • Kotlin: top-level defineState { ... } becomes steps { ... }, and
    parameterType(...) becomes param(...).

  • Added: The state factory argument to defineState/define_state is now optional — step files with pure steps can omit it

v0.3.1

Choose a tag to compare

@aslakhellesoy aslakhellesoy released this 06 Jul 13:11

Python (PyPI)

  • Added: var-unittest: Run Markdown specs as unittest tests — generate_tests(globals()) in one test module is the entire integration
  • Fixed: var-runner: Symlinked specs match the docs globs by their apparent path

Java & Kotlin (Maven Central)

  • Fixed: var-junit: Symlinked specs are discovered, and docs globs resolve against var.config.root

v0.3.0

Choose a tag to compare

@aslakhellesoy aslakhellesoy released this 04 Jul 11:47

TypeScript (npm)

  • Added: var-vitest: Cell and doc string mismatches render vitest's expected/received diff in the terminal and VS Code peek view
  • Added: Cell mismatches diff the authored line against the actual values and anchor editors at the first failing cell
  • Added: var-vitest: Cell mismatch diffs show only the differing values, not the whole step text

Specification (all ports)

  • ⚠️ Breaking: Sensors return a single parameter, table or doc string bare — positional arrays only for two or more values
    sensors no longer wrap a single comparison value in an
    array/list/tuple. When a step has exactly one comparison slot (one
    expression parameter, or just a trailing table/doc string), return the
    value itself: return total, not return [total]. Keep the positional
    array only when there are two or more slots. A sensor with no slots must
    return nothing — returning a value now raises ReturnShapeError (throw to
    fail instead). Single-slot returns are never read as positional arrays,
    so a custom parameter type transforming to an array is deep-compared
    as-is.
  • ⚠️ Breaking: Context and action merge into a single stimulus step kind — defineState returns { stimulus, sensor }
    the context and action step kinds are gone; register
    both kinds of step with stimulus instead (TS/Kotlin stimulus(...),
    Python @stimulus(...), Java s.stimulus(...)). Behaviour is
    unchanged — a stimulus evolves state exactly as context/action did, and
    sensors are untouched. The arrange/act (given/when) concepts remain
    useful narration in your Markdown, but they share one mechanism.
    Snippet generation now infers stimulus for any step with steps after it
    and sensor for the last one, and generated snippets offer the other
    role as a single commented alternative.
  • Added: Conformance pins each failure's anchor span, so a mismatch points at its first failing cell in every port

v0.2.0

Choose a tag to compare

@aslakhellesoy aslakhellesoy released this 03 Jul 18:04

TypeScript (npm)

  • ⚠️ Breaking: var-lsp: Var/stepGlobs reports each step glob's language
    the var/stepGlobs custom request now returns
    ReadonlyArray<StepGlob> ({ glob, language? }) instead of
    ReadonlyArray<string>; clients should filter globs by the language
    field rather than classifying file paths themselves.
  • ⚠️ Breaking: Packages no longer re-export other packages' APIs
    import VarConfig, loadVarConfig (was readVarConfig) and
    findFiles (was findSpecs) from @oselvar/var-config; VarDoc and
    resolveScannerPlugins from @oselvar/var-core; StepDef from
    @oselvar/var-language. @oselvar/var-vitest/runtime's collectVarExamples
    now takes scanner-plugin names (strings) instead of resolved plugin
    instances.
  • Fixed: var-vitest: Generated modules import runtime helpers from @oselvar/var-vitest/runtime
  • Fixed: var-cli: Installing @oselvar/var-cli no longer pulls in @oselvar/var

Python (PyPI)

  • ⚠️ Breaking: var-runner: Var_runner no longer re-exports var_config's API
    import VarConfig and read_var_config from var_config
    instead of var_runner.

v0.1.0

Choose a tag to compare

@aslakhellesoy aslakhellesoy released this 02 Jul 20:56

Added

  • First public release of var: Markdown-native BDD for TypeScript (npm),
    Python (PyPI), and Java/Kotlin (Maven Central), plus the Vár VS Code
    extension (Marketplace and Open VSX).