Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Browser Spec: Testing Hotwire with Ruby

Browser Spec: Testing Hotwire with Ruby

Avatar for Masayoshi Takahashi

Masayoshi Takahashi

October 17, 2026

More Decks by Masayoshi Takahashi

Other Decks in Technology

Transcript

  1. Browser Spec: Testing Hotwire with Ruby 2026/10/17 Kaigi on Rails

    2026 株式会社達人出版会・一般社団法人日本Rubyの会 高橋征義
  2. 自己紹介 / About Me 高橋征義 (Masayoshi Takahashi, @takahashim) 北海道は札幌からやって来ました Living

    in Sapporo, Hokkaido 20世紀からWeb開発者をやっています Web developer since the 20th century 日本Rubyの会をやってます Founder of Nihon Ruby no Kai 達人出版会もやってます Tatsu-zine Publishing Inc. 技術書典もやってます 好きな作家は新井素子 ebooks publisher / seller for IT Engineer TechBookFest
  3. 日本Rubyの会 / Nihon Ruby no Kai Events RubyKaigi Kaigi on

    Rails Regional RubyKaigi https://regional.rubykaigi.org/
  4. 最近の趣味 / My Latest Hobby AIにコードを書かせること Claude Code, Codex, OpenCodeな

    どを利用 例: 今見ているこのプレゼンツール Kotoyomi(Ruby) + Lilac + mrubywasm-runtime AIはプレゼンツールを作らせると最高 中身を書かせると微妙 Agentic Coding with Claude Code, Codex, OpenCode This presentation tool Kotoyomi(Ruby) + Lilac + mrubywasm-runtime AI is the best tool to create slide's theme, not content
  5. 最近の趣味 / My Latest Hobby Ruby用のML(学習・推論)ツール ML Tools for Rubyists

    Kohagi(Rust): Ruri v3などの ModernBERT用エンコーダ Kohagi (Rust): embedding encoder of ModernBERT like Ruri v3 kohagi-ruby: RubyからKohagiを使 kohagi-ruby: Ruby interface of Kohagi うためのライブラリ Torobi(Ruby + Rust): Rubyでファイ ンチューニングするツール Rubyで書けるAIツール・ライブラリに 興味のある方がいれば相談したい Rubyの会でサポートしたい Torobi (Ruby + Rust): fine tuning tool in Ruby Looking for Rubists interested in building AI tools and libraries in Ruby We'd like to support them through the Ruby no Kai
  6. Dommy Dommy RubyによるDOM実装 Browser Spec (dommy-rails) 実ブラウザなしにJSも含むRailsアプ リをテストする Dommy::Js::Quickjs DommyでJSを動かすためのライブ

    ラリ Dommy A DOM implementation in Ruby Browser Spec (dommy-rails) Rails app tests with JS, no real browser Dommy::Js::Quickjs A libarary to execute JS on Dommy
  7. オラクル / Oracle 正しいかどうかを教えてくれるもの とりわけ実行できるもの Tells us what's correct or

    not Especially executable ones 「テストオラクル」 "(Executable) test oracles" 良いオラクルがあれば勝てる A good oracle is the key to success
  8. 本セッションの流れ / Outline 概要 Overview DOMとDommyとBrowser Spec DOM, Dommy and

    Browser Spec Dommyの実装 Dommy Internals 開発のポイント Key Development Decisions 今後の計画 Future plans
  9. DOM

  10. DOM Document Object Model Document Object Model Webというかブラウザの基本の一部 fundametal part

    of web and/or web browsers HTMLの各要素の振る舞いなどのモ デル WHATWG DOM StandardやWHATWG HTML Standardなどで規定されている A model of HTML elements and their behavior Specified by WHATWG DOM and HTML Standard
  11. DOMの実装 / Implementations of DOM Web Browsers Google Chrome, Safari,

    Firefox, ... JSDOM (JavaScript) Happy DOM (JavaScript) [NEW!] Dommy (Ruby)
  12. Why Dommy? グ用 For test/debug of this presentaiton tool 最初はNode

    + Happy DOM At first, use Node + Happy DOM Nodeを用意するのが面倒 Setting up Node is a hassle Rubyで書けば(AIに書かせれば)いいの Why not write it in Ruby (with AI)? では? → Dommy was born このプレゼンツールのテスト・デバッ → Dommy爆誕
  13. Browser Spec せっかく作ったので有効活用したい Make more use of it KoRの発表ネタにも良さそう talk

    for KoR? Railsのテストをできるように Reuse it for Rails testing → Browser Spec → Browser Spec
  14. Browser Spec (もちろん)簡単ではない But implementing a browser is (of course)

    not easy レイアウト機能を全部捨てる Drop all layout functionality とはいえブラウザそのものの実装は 論理的なDOM要素の関係性だけ表現 する JSDOM, Happy DOMも同様 Only model the logical relationships between DOM elements. Same as JSDOM and Happy DOM
  15. Real browser vs Dommy Real browser (Cuprite) Chrome separate process

    CDP over WebSocket HTTP Ruby process Test Capybara Cuprite Puma Rails app server thread capybara-dommy (with Capybara) method call Ruby process Test Capybara capybara-dommy dommy-rack Rails app javascript: true dommy (DOM) dommy-js-quickjs JavaScript in the same process No browser, no server, no HTTP
  16. With or without Capybara capybara-dommy (with Capybara) method call Ruby

    process Test Capybara capybara-dommy dommy-rack Rails app javascript: true dommy (DOM) dommy-js-quickjs JavaScript in the same process Browser Spec (no Capybara) method call Ruby process Test dommy-rails dommy-rack dommy (DOM) Rails app dommy-js-quickjs JavaScript in the same process No browser, no server, no HTTP
  17. Browser Spec benchmark Scenario browse form table stimulus(JS) turbo-drive(JS) turbo-frame(JS)

    turbo-form(JS) fetch(JS) total peak memory (MB) dommy_js 236 41.3 84.4 144 315 142 55.3 48.4 1138 140 cuprite 1574 529 1733 1962 2391 1667 605 438 11583 961 cuprite_tuned 1483 528 1704 1923 1934 1665 605 431 10901 982 cuprite / dommy_js 6.7× 12.8× 20.5× 13.6× 7.6× 11.7× 10.9× 9.0× 10.2× —
  18. Dommyの実装 / Dommy Internals Your tests RSpec / Minitest ·

    Capybara DSL dommy-rails capybara-dommy Browser Spec, matchers Capybara driver dommy-rack method call Browser-like session: navigation, cookies, forms, history any Rack app no server, no network dommy DOM & HTML Standard in pure Ruby Document Element Event URL parser Cookies Storage Makiri Rails app Rust HTML / CSS parser · XML / XPath fetch JS Bridge __js_get__ / __js_set__ __js_call__ / __js_new__ dommy-js-quickjs JS adapter gem QuickJS JavaScript engine lexbor (C library) Turbo / Stimulus run here
  19. capybara-dommy vs Browser Spec System spec (with Capybara) Browser Spec

    (no Capybara) driven_by :dommy_js browser.visit root_path visit root_path browser.fill_in "q", with: "ru" fill_in "q", with: "ru" browser.advance_time(300) expect(page).to have_text "Ruby" expect(browser).to have_css "li", text: "Ruby" ▪ Reuse existing system specs ▪ Just switch the driver ▪ Request-spec style ▪ Virtual clock: settle, advance_time capybara-dommy dommy-rails Capybara driver browser helper dommy-rack Session (javascript: true) dommy (DOM) Same engine for both: navigation, cookies, forms, history QuickJS method call Rails app no server, no HTTP Di erent entry, same engine
  20. Makiri HTMLとCSSのparseはlexborを使用 https://lexbor.com/ XMLとXPathは自力で実装 Rust拡張を使用 lexborはCなので当初はCで実装 メモリ安全性が気になりRustに変更 Using lexbor for

    HTML/CSS parsing https://lexbor.com/ implement XML and XPath from scratch Write the extension in Rust Initially written in C, since Lexbor is also in C Switched to Rust for memory safety
  21. Makiri benchmark Makiri Nokogiri ratio parse only 645 124 5.20×

    parse + xpath('//li') 557 122 4.57× parse + text 545 123 4.42× parse + css('ul li.item') 573 105 5.48× parse + at_css('#main') 614 97 6.34× 2626895 429 6120× (reuse index)
  22. Dommy 本体 / Dommy repository monorepo Dommy Dommy::Rack : session

    layer Dommy::Rails : matchers for Rails Capybara::Dommy : capybara adapter
  23. Dommyの実装方針 / Implemetation Policy 基本的にはWHATWG DOM Standard とHTML Standardに準拠する Basically

    follows the WHATWG DOM and HTML Standard ただし例外はある(後述) With some exceptions (see later) 他のライブラリにはあまり依存しない MakiriとBase64のみ Minimizes external dependencies Only Makiri and Base64
  24. Dommy::Internal::UrlParser 標準のURIライブラリは使わず、自力で 実装している URI(RFC 3986)はデータ構造が中 心、WHATWGは操作が中心の印象 https://url.spec.whatwg.org/ にアルゴ リズムが書いてある (AIが)それを見ながらRubyにする

    IDNAとかPunycodeとかも頑張って 実装する From scratch, instead of using the standard URI library URI(RFC 3986) seems dataoriented, while WHATWG URL is process-oriented The algorithms are documented at https://url.spec.whatwg.org/ Follow the spec, and translate into Ruby (by AI) Implement IDNA, Punycode, and others
  25. JavaScript for Dommy 現代WebサイトはJSがないとまともに 見られない Modern websites are broken without

    JavaScript SPA SPAs JSがないとログインできない Can't sign in without JavaScript 素のフォームでもCAPTCHA Even plain HTML forms have CAPTCHAs
  26. Dommy::Js::Quickjs DommyでJSを動かすためのgem https://github.com/takahashim/do mmy-js-quickjs QuickJS.rb + Dommyとのアダプタ https://github.com/hmsk/quickj s.rb 外部エンジンに依存するので別gem

    A gem for running JavaScript in Dommy https://github.com/takahashim/do mmy-js-quickjs QuickJS.rb + an adapter for Dommy https://github.com/hmsk/quickj s.rb A separate gem due to the external engine dependency
  27. 開発のポイント / Key Development Decisions テストの役に立つ程度には正しく動く 必要がある どうすればそれっぽく動作するものが 作れるか Needs

    to work correctly enough to be useful for testing How can we make something that behaves correctly? 難しい問題 A difficult problem Agentic Codingではありがち A common challenge in agentic coding
  28. オラクル / Oracle 正しいかどうかを教えてくれるもの とりわけ実行できるもの Tells us what's correct or

    not Especially executable ones 「テストオラクル」 "(Executable) test oracles" 良いオラクルがあれば勝てる A good oracle is the key to success
  29. オラクルの使い方 / How to use an Oracle 良いオラクルを用意する Find a

    good oracle オラクルと照らし合わせる 実装とオラクルが一致するまで修正す Compare the results against the oracle る Keep fixing until they match さすがに仕様書をAIに投げてもそれ だけではオラクルと一致する実装に ならない Of course, the spec alone isn't enough to implement it
  30. What is Oracle for DOM? DOM実装 JSDOM, Happy DOM, ...

    ブラウザ Chrome, Safari, Firefox, ... 仕様書 WHATWG DOM Standard, WHATWG HTML Standard, ... DOM implementations JSDOM, Happy DOM, ... Browsers Chrome, Safari, Firefox, ... Specifications WHATWG DOM Standard, WHATWG HTML Standard, ...
  31. Dommyの開発方法 / Developing Dommy 当初はHappy DOMを目標にして開発 Initially aimed to match

    Happy DOM 作っていくうちに仕様準拠度が低いの が気になる Began noticing its lack of standards compliance 最近はHappy DOMはほとんど参照して Rarely refer to Happy DOM anymore いない 実装としてはJSDOMと比較する Now aim to match jsdom
  32. JSDOMに合わせれば良い? / Is Matching JSDOM Enough? 良くなかった Turns out, it

    isn't ブラウザと挙動が違う Behavior differs from browsers 仕様と挙動が違う Behavior differs from the spec
  33. ブラウザに合わせればよい? / Is Matching JSDOM Enough? 良くなかった Turns out, it

    isn't ブラウザごとに挙動が違う Behavior differs across browsers 仕様と挙動が違う Behavior differs from the spec そもそもあらゆる動作を確認できない 抜け・漏れが発生する We can't test every possible behavior Many cases inevitably get missed
  34. Web Platform Tests (WPT) とはいえDommyにはレイアウト機能が ないので全部は通らない 取捨選択した上で通るように修正する 113688/115188 subtests (98.7%)

    across 2718 files; 1862 files fully green But Dommy has no layout engine, so not all tests can pass Select relevant tests and fix Dommy until they pass 113688/115188 subtests (98.7%) across 2718 files; 1862 files fully green
  35. WPTがあれば十分? / Is Matching WPT Enough? もちろんそんなことはない Of course not

    あらゆる機能を網羅しているわけでは WPT doesn't cover everything ない
  36. Lean プログラミング言語 Programming Language 定理証明支援ツール Proof Assistant 定理を自動で証明してくるわけでは ない 対話的に証明を記述するDSL的なも

    の(タクティク)を提供 Doesn't automatically prove theorems for you Provides DSL-like tactics for constructing proofs interactively
  37. lean4-dom DOMやURL、CSSセレクタの仕様を Lean 4で形式化したモデル A formal model of the DOM,

    URL, and CSS Selectors in Lean 4 実行可能なオラクルでもある Also serves as an executable oracle DOMの操作が実行できる Can execute DOM operations 実行例をJSONにして、そのJSONを DommyなどのDOM実装と突き合わせ て確認できる Export execution results as JSON for comparison with Dommy and other implementations
  38. lean4-dom DOM Standard dom.bs · natural language formalized by hand

    Executable model runs DOM operations transcribed by hand proved by Lean machine-checked lean4-dom human reading (no guarantee) machine-checked Theorems invariants · spec relations
  39. 差分テスト / Differential Testing lean4-dom executable model observation Scenario JSON

    initial DOM tree + operations Dommy Ruby implementation observation from spec steps, or generated compare same result? 27 divergences found jsdom / browsers other implementations 25 in Dommy · 2 in the model observation the oracle can be wrong, too
  40. 見つかった不具合の例 / A Bug Found Given text = document.createTextNode("hi") document.documentElement.after(text)

    Spec / lean4-dom HierarchyRequestError // insert text next to <html> ✓ Dommy (before x) no error #document #document <html> <html> ✗ "hi" tree unchanged Text under Document: not allowed appendChild ran the pre-insert validity check; after() skipped it. In lean4-dom every insertion API goes through the check (proved). Found by di erential testing (lean4-dom docs/status.md, #1)
  41. Leanを使った感想 / My Experience with Lean 証明がぜんぜん読めない プログラミング言語と違いすぎ テストを通るオブジェクトを限られ たメソッドで生成するパズル?みた

    いな とりあえず定理だけ理解して証明自体 はLeanに丸投げ状態 Very hard to read the proofs Too different from programming language Constructing objects that passes tests using a limited set of methods? For now, just try to understand the theorems and leave the proofs entirely
  42. lean4-domでも不十分 / lean4-dom is not enough 検証・証明できるのは限られた性質の み そもそもモデルが仕様と合致している かは保証されない

    望ましい性質を持った仕様に近いもう 一つのオラクル、くらいの位置づけ Only limited properties can be verified or proven No guarantee that the model matches the spec Another oracle with desirable properties, close to the spec
  43. lean4-domでも不十分 / lean4-dom is not enough DOM Standard dom.bs ·

    natural language formalized by hand transcribed by hand No formal guarantee Does the model really match the spec? Executable model runs DOM operations proved by Lean machine-checked lean4-dom human reading (no guarantee) machine-checked Theorems invariants · spec relations
  44. オラクル / Oracles 仕様書/規格 specifications/standard 他のDOM実装 otner DOM impleentations ブラウザ

    web browsers WPT WPT test suites 形式化モデルに沿った実装 formalized model これら全部を突き合わせて、どこがどの くらい正しいかを考えながら実装を進め ていく with all of them, create implementation
  45. Dommy::Js::Zipp Zippという新しいJSエンジンによる実 装 Using Zipp, a new JavaScript engine https://zipp.org/

    https://zipp.org/ Rust製 safe-sandboxというunsafeを使わない 版がある 他にも凝った機能があるけどDommyで はsafe-sandboxのみ使用 Written in Rust Offers a safe-sandbox mode that uses no unsafe Rust Has other advanced features, but Dommy only uses the mode
  46. QuickJSの課題 / Issues with QuickJS いろいろ修正したい点がある 例: globalThis !== window

    C実装だと独自に修正すると壊れそう safe Rustなら安心感が強い unsafeなRustだと微妙 There are several things I'd like to fix e.g., globalThis !== window Modifying the C implementation myself feels risky Safe Rust gives me much more confidence Unsafe Rust, not so much
  47. OSSと依存 / OSS and dependency 開発効率 全部書くのは単純にコストがでかい メンテナンスの手間 一度書くことができてもメンテが大 変

    Development efficiency Writing everything from scratch is simply too costly Maintenance overhead Even if we can modify it, maintaining it is hard
  48. OSSは(また)死ぬ? / OSS is dead (again)? AI時代にはOSSとか意味ないのでは? というひとはいる 一方で、AIはOSSもいくらでも量産で きる

    単純に死ぬことはなさそう Some say OSS will become irrelevant in the age of AI But AI can generate endless amounts of OSS OSS probably isn't going to die anytime soon
  49. Dependency considered harmful? 依存OSSの対処はAIでもめんどくさい 便利なOSSは機能が多い 広く使われるためには多機能かつ柔 軟なものが好まれる とはいえ本当に必要な機能は多くない のでは? そしてそれならAIで実装してしまえ

    ばいいのでは? Dealing with OSS dependencies is a hassle, even with AI Useful OSS tends to have lots of features To be widely adopted, it needs to be feature-rich and flexible But do we really need all those features? If not, why not just implement what we need with AI?
  50. Dependency considered harmful? みんなでOSSを改善していく、という 流れがなくなる OSSは単に参照されるかforkされるの The practice of improving

    OSS together may disappear み OSS may simply be used as a reference or forked fork元が更新された際にもそれを適切 に取り込むのはAIならできそう AI could handle merging upstream changes into forks コミュニケーションが成立してない OSSは死ななくてもOSSコミュニティ は廃れてしまうのでは? It's not communication What does this mean for OSS communities?
  51. Zippでの経験 / My Experience with Zipp 要修正な点はforkして改変 Forked Zipp to

    fix issues myself 一部フィードバックしたらすぐ修正さ Reported a few issues, and they were fixed almost immediately れた issuesのみ、PRなし Only issues, no PRs 18件ほどフィードバックしたら1日 All 18 issues were fixed in just one day で全部直った AI時代ならではの得がたい体験 A remarkable experience unique to the AI era
  52. Zippでの経験 / My Experience with Zipp OSSのコミュニケーションは大きく変 わりそう OSS collaboration

    is likely to change dramatically とはいえ暗いだけではないかも But maybe the future isn't all that bad いやー、どうなるんでしょうね…? Who knows what will happen...?
  53. まとめ / Summary RubyでDOMを書くのは面白いし勉強 Implementing the DOM in Ruby is

    fun になる A good oracle is essential for AI coding AIコーディングには良いオラクルが大 事 Leanも面白いけど証明は読めない AI時代のOSSコミュニティは本当に悩 ましい 技術書典21は2026/11/21〜12/6開催予 定です Lean is fascinating, but the proofs are hard OSS communities in the AI are a real dilemma TechBookFest 21 is scheduled for Nov 21 – Dec 6, 2026