refactor: introduce formal RSpock AST with parse-transform pipeline#5
Merged
JPDuchesne merged 4 commits intomasterfrom Feb 27, 2026
Merged
refactor: introduce formal RSpock AST with parse-transform pipeline#5JPDuchesne merged 4 commits intomasterfrom
JPDuchesne merged 4 commits intomasterfrom
Conversation
…ctionParser to class Move all block classes (Given, When, Then, Expect, Cleanup, Where) from RSpock::AST to RSpock::AST::Parser, making them parser-phase constructs rather than top-level AST components. Tests moved accordingly. Convert InteractionParser from a module with class methods to a proper class with instance methods for better encapsulation. Introduce can_start?/can_end? on Block subclasses as declarative boundary checks, eliminating the need for StartBlock/EndBlock sentinel constructs. Clean up Block base class by removing dead code (unshift, node_container). Include NodeBuilder in Block and InteractionParser so they produce RSpock AST nodes transparently via the s() helper override. Made-with: Cursor
…arser Create a formal RSpock AST with typed node subclasses (TestNode, DefNode, GivenNode, WhenNode, ThenNode, ExpectNode, CleanupNode, WhereNode, InteractionNode) under RSpock::AST::Node, each with named accessors for their positional children. Override the s() helper via NodeBuilder to transparently construct the correct subclass for rspock_* types. Extract parsing logic from TestMethodTransformation into a dedicated TestMethodParser class, establishing a clean parse-then-transform pipeline. TestMethodTransformation now receives a fully formed RSpock AST (TestNode) and focuses solely on transformation. Rename source_map to block_registry (DEFAULT_BLOCK_REGISTRY) to accurately reflect its role as a keyword-to-block-class mapping, not source mapping. Made-with: Cursor
Split interaction handling into focused, single-responsibility transformers: - InteractionToMochaMockTransformation: converts interaction nodes to Mocha expects/stubs with cardinality, args, and return value support - InteractionToBlockIdentityAssertionTransformation: generates assert_same checks for &var block forwarding verification - InteractionBlockAssertionTransformation: detects interaction nodes within Then/Expect blocks and delegates to the above transformers Add BlockCapture helper module for capturing blocks passed to both mocked and real objects, enabling verification that the correct block was forwarded to collaborators. Support >> operator in interactions for stubbing return values, with top-level-only transformation to avoid rewriting nested >> calls. Document interaction syntax, block verification, and >> stubbing in README. Made-with: Cursor
…tions Restructure TestNode to use positional children [DefNode, BodyNode, WhereNode?] for cleaner separation of test definition, body blocks, and parameterization. Delete legacy InteractionTransformation (which violated the AbstractTransformation contract by returning a non-Node Result struct) and InteractionBlockAssertionTransformation (redundant abstraction), porting their missing test coverage to the RSpock AST-based transformations. Made-with: Cursor
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Restructure blocks into
RSpock::AST::Parsernamespace — Move block accumulators (Block,GivenBlock,WhenBlock, etc.) underParser, convertInteractionParserfrom module to class, eliminateStartBlock/EndBlockin favor of declarativecan_start?/can_end?on each block, and renamesource_maptoblock_registry.Introduce formal RSpock AST node hierarchy — Create
RSpock::AST::Nodesubclasses (TestNode,DefNode,BodyNode,WhereNode,InteractionNode, etc.) backed by a type registry andNodeBuildermodule, extractTestMethodParserto own the parse phase, and makeTestMethodTransformationstateless (operating onTestNode→ Ruby AST).TestNodeuses positional children[DefNode, BodyNode, WhereNode?]for clean structural separation.Add interaction transformations and block identity verification — Implement
InteractionToMochaMockTransformationandInteractionToBlockIdentityAssertionTransformationoperating onInteractionNode, addRSpock::Helpers::BlockCapturefor runtime block capture, delete legacyInteractionTransformation(which violated theAbstractTransformationcontract) andInteractionBlockAssertionTransformation(redundant abstraction), and port all missing test coverage.Block forwarding verification in interactions — When testing code that forwards a block to a collaborator (e.g. a method wrapping a UI frame or transaction), there was previously no way to verify that the correct block was actually passed through. This PR introduces
&varsyntax in interactions to assert block identity:This transforms into a Mocha expectation plus a
BlockCapturethat intercepts the block at runtime, followed by anassert_sameto verify the exact proc was forwarded — not just that a block was passed, but that the right one was. Inline blocks (do...end/{ }) are explicitly rejected with a clear error, since there is no external reference to compare identity against.Test plan