turbo-rails 0.5.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +113 -18
  3. data/Rakefile +19 -2
  4. data/app/assets/javascripts/turbo.js +4143 -1431
  5. data/app/assets/javascripts/turbo.min.js +29 -0
  6. data/app/assets/javascripts/turbo.min.js.map +1 -0
  7. data/app/channels/turbo/streams/broadcasts.rb +58 -22
  8. data/app/channels/turbo/streams/stream_name.rb +7 -0
  9. data/app/channels/turbo/streams_channel.rb +30 -2
  10. data/app/controllers/concerns/turbo/request_id_tracking.rb +12 -0
  11. data/app/controllers/turbo/frames/frame_request.rb +22 -8
  12. data/app/controllers/turbo/native/navigation.rb +19 -9
  13. data/app/helpers/turbo/drive_helper.rb +75 -3
  14. data/app/helpers/turbo/frames_helper.rb +21 -2
  15. data/app/helpers/turbo/includes_helper.rb +2 -0
  16. data/app/helpers/turbo/streams/action_helper.rb +34 -9
  17. data/app/helpers/turbo/streams_helper.rb +20 -7
  18. data/app/javascript/turbo/cable.js +6 -3
  19. data/app/javascript/turbo/cable_stream_source_element.js +19 -3
  20. data/app/javascript/turbo/fetch_requests.js +59 -0
  21. data/app/javascript/turbo/index.js +6 -0
  22. data/app/javascript/turbo/snakeize.js +31 -0
  23. data/app/jobs/turbo/streams/action_broadcast_job.rb +4 -2
  24. data/app/jobs/turbo/streams/broadcast_job.rb +2 -0
  25. data/app/jobs/turbo/streams/broadcast_stream_job.rb +7 -0
  26. data/app/models/concerns/turbo/broadcastable.rb +246 -38
  27. data/app/models/turbo/debouncer.rb +24 -0
  28. data/app/models/turbo/streams/tag_builder.rb +163 -21
  29. data/app/models/turbo/thread_debouncer.rb +28 -0
  30. data/app/views/layouts/turbo_rails/frame.html.erb +8 -0
  31. data/config/routes.rb +1 -2
  32. data/lib/install/turbo_needs_redis.rb +20 -0
  33. data/lib/install/turbo_with_bun.rb +9 -0
  34. data/lib/install/turbo_with_importmap.rb +5 -0
  35. data/lib/install/turbo_with_node.rb +9 -0
  36. data/lib/tasks/turbo_tasks.rake +50 -8
  37. data/lib/turbo/broadcastable/test_helper.rb +172 -0
  38. data/lib/turbo/engine.rb +40 -6
  39. data/lib/turbo/test_assertions/integration_test_assertions.rb +76 -0
  40. data/lib/turbo/test_assertions.rb +69 -8
  41. data/lib/turbo/version.rb +1 -1
  42. data/lib/turbo-rails.rb +12 -0
  43. metadata +48 -173
  44. data/.github/workflows/ci.yml +0 -30
  45. data/.gitignore +0 -2
  46. data/Gemfile +0 -6
  47. data/Gemfile.lock +0 -147
  48. data/lib/install/turbo_with_asset_pipeline.rb +0 -20
  49. data/lib/install/turbo_with_webpacker.rb +0 -24
  50. data/package.json +0 -47
  51. data/rollup.config.js +0 -23
  52. data/test/drive/drive_helper_test.rb +0 -8
  53. data/test/dummy/.babelrc +0 -18
  54. data/test/dummy/.gitignore +0 -3
  55. data/test/dummy/.postcssrc.yml +0 -3
  56. data/test/dummy/Rakefile +0 -6
  57. data/test/dummy/app/assets/config/manifest.js +0 -2
  58. data/test/dummy/app/assets/images/.keep +0 -0
  59. data/test/dummy/app/assets/stylesheets/application.css +0 -15
  60. data/test/dummy/app/assets/stylesheets/scaffold.css +0 -80
  61. data/test/dummy/app/channels/application_cable/channel.rb +0 -4
  62. data/test/dummy/app/channels/application_cable/connection.rb +0 -4
  63. data/test/dummy/app/controllers/application_controller.rb +0 -2
  64. data/test/dummy/app/controllers/concerns/.keep +0 -0
  65. data/test/dummy/app/controllers/messages_controller.rb +0 -12
  66. data/test/dummy/app/controllers/trays_controller.rb +0 -17
  67. data/test/dummy/app/helpers/application_helper.rb +0 -2
  68. data/test/dummy/app/javascript/packs/application.js +0 -0
  69. data/test/dummy/app/jobs/application_job.rb +0 -2
  70. data/test/dummy/app/mailboxes/application_mailbox.rb +0 -2
  71. data/test/dummy/app/mailboxes/messages_mailbox.rb +0 -4
  72. data/test/dummy/app/mailers/application_mailer.rb +0 -4
  73. data/test/dummy/app/models/application_record.rb +0 -3
  74. data/test/dummy/app/models/concerns/.keep +0 -0
  75. data/test/dummy/app/models/message.rb +0 -29
  76. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  77. data/test/dummy/app/views/layouts/mailer.html.erb +0 -13
  78. data/test/dummy/app/views/layouts/mailer.text.erb +0 -1
  79. data/test/dummy/app/views/messages/_message.html.erb +0 -1
  80. data/test/dummy/app/views/messages/_message.turbo_stream.erb +0 -1
  81. data/test/dummy/app/views/messages/show.turbo_stream.erb +0 -9
  82. data/test/dummy/app/views/trays/index.html.erb +0 -3
  83. data/test/dummy/app/views/trays/show.html.erb +0 -3
  84. data/test/dummy/bin/bundle +0 -3
  85. data/test/dummy/bin/rails +0 -4
  86. data/test/dummy/bin/rake +0 -4
  87. data/test/dummy/bin/setup +0 -36
  88. data/test/dummy/bin/update +0 -31
  89. data/test/dummy/bin/yarn +0 -11
  90. data/test/dummy/config/application.rb +0 -22
  91. data/test/dummy/config/boot.rb +0 -5
  92. data/test/dummy/config/cable.yml +0 -10
  93. data/test/dummy/config/environment.rb +0 -5
  94. data/test/dummy/config/environments/development.rb +0 -34
  95. data/test/dummy/config/environments/production.rb +0 -96
  96. data/test/dummy/config/environments/test.rb +0 -38
  97. data/test/dummy/config/initializers/application_controller_renderer.rb +0 -8
  98. data/test/dummy/config/initializers/assets.rb +0 -14
  99. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  100. data/test/dummy/config/initializers/content_security_policy.rb +0 -22
  101. data/test/dummy/config/initializers/cookies_serializer.rb +0 -5
  102. data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -4
  103. data/test/dummy/config/initializers/inflections.rb +0 -16
  104. data/test/dummy/config/initializers/mime_types.rb +0 -4
  105. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  106. data/test/dummy/config/locales/en.yml +0 -33
  107. data/test/dummy/config/puma.rb +0 -34
  108. data/test/dummy/config/routes.rb +0 -4
  109. data/test/dummy/config/spring.rb +0 -6
  110. data/test/dummy/config/webpack/development.js +0 -3
  111. data/test/dummy/config/webpack/environment.js +0 -3
  112. data/test/dummy/config/webpack/production.js +0 -3
  113. data/test/dummy/config/webpack/test.js +0 -3
  114. data/test/dummy/config/webpacker.yml +0 -65
  115. data/test/dummy/config.ru +0 -5
  116. data/test/dummy/lib/assets/.keep +0 -0
  117. data/test/dummy/log/.keep +0 -0
  118. data/test/dummy/public/404.html +0 -67
  119. data/test/dummy/public/422.html +0 -67
  120. data/test/dummy/public/500.html +0 -66
  121. data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
  122. data/test/dummy/public/apple-touch-icon.png +0 -0
  123. data/test/dummy/public/favicon.ico +0 -0
  124. data/test/frames/frame_request_controller_test.rb +0 -21
  125. data/test/frames/frames_helper_test.rb +0 -21
  126. data/test/native/navigation_controller_test.rb +0 -42
  127. data/test/streams/broadcastable_test.rb +0 -80
  128. data/test/streams/streams_channel_test.rb +0 -105
  129. data/test/streams/streams_controller_test.rb +0 -29
  130. data/test/turbo_test.rb +0 -10
  131. data/turbo-rails.gemspec +0 -17
  132. data/yarn.lock +0 -283
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b0552458511ec8ad34c4b0b3978d2a9ffb88485b844f60f6bc283287e0eecdd
4
- data.tar.gz: eccd64955e5db2682efe9b503c24feeb6cbf50c1e542d7bcef0416ded95026fb
3
+ metadata.gz: 1b66ce6805bd7f4ed7bf032d98080748a3d123959ef81940ca62d1c394b69d79
4
+ data.tar.gz: 2245107df78ba671eb787f683cc77ac508778fd3832c3396c0d52d4be6f9d64c
5
5
  SHA512:
6
- metadata.gz: 950a8abe637775b61e610d9c99a61f22fa514704a2a3d4453a0e53854c2c4dfe4e4c65f342cd534869d9d1edd83c513590a70744632a6981df52265b20ca142e
7
- data.tar.gz: 5d97247505d6934b2bda932a53b0ca3b19d69fe7000a269001cd50ecc9f38bba090e26f50a3d489073699a93ccc50093f218465f45b054969d10c10026052100
6
+ metadata.gz: e6d95bdd5abce68fda1895b52b53474a8c0306545a238af6b0caba6f20354a7e48add0a6c662cd4861152fb0b293468f2f3c2a0c67002c9926922a19c4e734aa
7
+ data.tar.gz: e9daf44cbd3abf3c120aaf0b7bd58e13feb58f60c8738a57624c9721b6965636214a7e44a47eff5f752890b6df5915dbd852eb58d6449326aaa3969b1e3a91f7
data/README.md CHANGED
@@ -1,57 +1,152 @@
1
- # Turbo
1
+ # <img src="assets/logo.png?sanitize=true" width="24" height="24" alt="Turbo"> Turbo
2
2
 
3
- [Turbo](https://turbo.hotwire.dev) gives you the speed of a single-page web application without having to write any JavaScript. Turbo accelerates links and form submissions without requiring you to change your server-side generated HTML. It lets you carve up a page into independent frames, which can be lazy-loaded and operate as independent components. And finally, helps you make partial page updates using just HTML and a set of CRUD-like container tags. These three techniques reduce the amount of custom JavaScript that many web applications need to write by an order of magnitude. And for the few dynamic bits that are left, you're invited to finish the job with [Stimulus](https://github.com/hotwired/stimulus).
3
+ [Turbo](https://turbo.hotwired.dev) gives you the speed of a single-page web application without having to write any JavaScript. Turbo accelerates links and form submissions without requiring you to change your server-side generated HTML. It lets you carve up a page into independent frames, which can be lazy-loaded and operate as independent components. And finally, helps you make partial page updates using just HTML and a set of CRUD-like container tags. These three techniques reduce the amount of custom JavaScript that many web applications need to write by an order of magnitude. And for the few dynamic bits that are left, you're invited to finish the job with [Stimulus](https://github.com/hotwired/stimulus).
4
4
 
5
- On top of accelerating web applications, Turbo was built from the ground-up to form the foundation of hybrid native applications. Write the navigational shell of your Android or iOS app using the standard platform tooling, then seamlessly fill in features from the web, following native navigation patterns. Not every mobile screen needs to be written in Swift or Kotlin to feel native. With Turbo, you spend less time wrangling JSON, waiting on app stores to approve updates, or reimplementing features you've already created in HTML.
5
+ On top of accelerating web applications, Turbo was built from the ground-up to form the foundation of hybrid native applications. Write the navigational shell of your [Android](https://github.com/hotwired/turbo-android) or [iOS](https://github.com/hotwired/turbo-ios) app using the standard platform tooling, then seamlessly fill in features from the web, following native navigation patterns. Not every mobile screen needs to be written in Swift or Kotlin to feel native. With Turbo, you spend less time wrangling JSON, waiting on app stores to approve updates, or reimplementing features you've already created in HTML.
6
6
 
7
- Turbo is a language-agnostic framework written in TypeScript, but this gem builds on top of those basics to make the integration with Rails as smooth as possible. You can deliver turbo updates via model callbacks over Action Cable, respond to controller actions with native navigation or standard redirects, and render turbo frames with helpers and layout-free responses.
7
+ Turbo is a language-agnostic framework written in JavaScript, but this gem builds on top of those basics to make the integration with Rails as smooth as possible. You can deliver turbo updates via model callbacks over Action Cable, respond to controller actions with native navigation or standard redirects, and render turbo frames with helpers and layout-free responses.
8
8
 
9
9
 
10
- ## Turbo Drive
10
+ ## Navigate with Turbo Drive
11
11
 
12
- Turbo is a continuation of the ideas from the previous Turbolinks framework, and the heart of that past approach lives on as Turbo Drive. When installed, Turbo automatically intercepts all clicks on `<a href>` links to the same domain. When you click an eligible link, Turbo prevents the browser from following it. Instead, Turbo changes the browser’s URL using the History API, requests the new page using `fetch`, and then renders the HTML response.
12
+ Turbo is a continuation of the ideas from the previous [Turbolinks](https://github.com/turbolinks/turbolinks) framework, and the heart of that past approach lives on as Turbo Drive. When installed, Turbo automatically intercepts all clicks on `<a href>` links to the same domain. When you click an eligible link, Turbo prevents the browser from following it. Instead, Turbo changes the browser’s URL using the History API, requests the new page using `fetch`, and then renders the HTML response.
13
13
 
14
- During rendering, Turbo replaces the current `<body>` element outright and merges the contents of the `<head>` element. The JavaScript window and document objects, and the HTML `<html>` element, persist from one rendering to the next.
14
+ During rendering, Turbo replaces the current `<body>` element outright and merges the contents of the `<head>` element. The JavaScript window and document objects, and the `<html>` element, persist from one rendering to the next.
15
15
 
16
16
  Whereas Turbolinks previously just dealt with links, Turbo can now also process form submissions and responses. This means the entire flow in the web application is wrapped into Turbo, making all the parts fast. No more need for `data-remote=true`.
17
17
 
18
+ Turbo Drive can be disabled on a per-element basis by annotating the element or any of its ancestors with `data-turbo="false"`. If you want Turbo Drive to be disabled by default, then you can adjust your import like this:
18
19
 
19
- ## Turbo Frames
20
+ ```js
21
+ import "@hotwired/turbo-rails"
22
+ Turbo.session.drive = false
23
+ ```
20
24
 
21
- Turbo reinvents the old HTML technique of frames without any of the drawbacks that lead to developers abandoning it. With Turbo Frames, you can treat a subset of the page as its own component, where links and form submissions replace only that part. This removes an entire class of problems around partial interactivity that before would have required custom JavaScript.
25
+ Then you can use `data-turbo="true"` to enable Drive on a per-element basis.
22
26
 
23
- It also makes it dead easy to carve a single page into smaller pieces that can all live on their own cache timeline. While the bulk of the page might easily be cached between users, a small personalized toolbar perhaps cannot. With Turbo::Frames, you can designate the toolbar as a frame, which will be lazy-loaded automatically by the publicly-cached root page. This means simpler pages, easier caching schemes with fewer dependent keys, and all without needing to write a lick of custom JavaScript.
27
+ [See documentation](https://turbo.hotwired.dev/handbook/drive).
24
28
 
29
+ ## Decompose with Turbo Frames
25
30
 
26
- ## Turbo Streams
31
+ Turbo reinvents the old HTML technique of frames without any of the drawbacks that lead to developers abandoning it. With Turbo Frames, **you can treat a subset of the page as its own component**, where links and form submissions **replace only that part**. This removes an entire class of problems around partial interactivity that before would have required custom JavaScript.
27
32
 
28
- Partial page updates that are delivered asynchronously over a web socket connection is the hallmark of modern, reactive web applications. With Turbo Streams, you can get all of that modern goodness using the existing server-side HTML you're already rendering to deliver the first page load. With a set of simple CRUD container tags, you can send HTML fragments over the web socket (or in response to direct interactions), and see the page change in response to new data. Again, no need to construct an entirely separate API, no need to wrangle JSON, no need to reimplement the HTML construction in JavaScript. Take the HTML you're already making, wrap it in an update tag, and, voila, your page comes alive.
33
+ It also makes it dead easy to carve a single page into smaller pieces that can all live on their own cache timeline. While the bulk of the page might easily be cached between users, a small personalized toolbar perhaps cannot. With Turbo::Frames, you can designate the toolbar as a frame, which will be **lazy-loaded automatically** by the publicly-cached root page. This means simpler pages, easier caching schemes with fewer dependent keys, and all without needing to write a lick of custom JavaScript.
34
+
35
+ This gem provides a `turbo_frame_tag` helper to create those frames.
36
+
37
+ For instance:
38
+ ```erb
39
+ <%# app/views/todos/show.html.erb %>
40
+ <%= turbo_frame_tag @todo do %>
41
+ <p><%= @todo.description %></p>
42
+
43
+ <%= link_to 'Edit this todo', edit_todo_path(@todo) %>
44
+ <% end %>
45
+
46
+ <%# app/views/todos/edit.html.erb %>
47
+ <%= turbo_frame_tag @todo do %>
48
+ <%= render "form" %>
49
+
50
+ <%= link_to 'Cancel', todo_path(@todo) %>
51
+ <% end %>
52
+ ```
53
+
54
+ When the user clicks on the `Edit this todo` link, as a direct response to this user interaction, the turbo frame will be automatically replaced with the one in the `edit.html.erb` page.
55
+
56
+ [See documentation](https://turbo.hotwired.dev/handbook/frames).
57
+
58
+ ### A note on custom layouts
59
+
60
+ In order to render turbo frame requests without the application layout, Turbo registers a custom [layout method](https://api.rubyonrails.org/classes/ActionView/Layouts/ClassMethods.html#method-i-layout).
61
+ If your application uses custom layout resolution, you have to make sure to return `"turbo_rails/frame"` (or `false` for TurboRails < 1.4.0) for turbo frame requests:
62
+
63
+ ```ruby
64
+ layout :custom_layout
65
+
66
+ def custom_layout
67
+ return "turbo_rails/frame" if turbo_frame_request?
68
+
69
+ # ... your custom layout logic
70
+ ```
71
+
72
+ If you are using a custom, but "static" layout,
73
+
74
+ ```ruby
75
+ layout "some_static_layout"
76
+ ```
77
+
78
+ you **have** to change it to a layout method in order to conditionally return `false` for turbo frame requests:
79
+
80
+ ```ruby
81
+ layout :custom_layout
82
+
83
+ def custom_layout
84
+ return "turbo_rails/frame" if turbo_frame_request?
85
+
86
+ "some_static_layout"
87
+ ```
88
+
89
+ ## Come Alive with Turbo Streams
90
+
91
+ Partial page updates that are **delivered asynchronously over a web socket connection** is the hallmark of modern, reactive web applications. With Turbo Streams, you can get all of that modern goodness using the existing server-side HTML you're already rendering to deliver the first page load. With a set of simple CRUD container tags, you can send HTML fragments over the web socket (or in response to direct interactions), and see the page change in response to new data. Again, **no need to construct an entirely separate API**, **no need to wrangle JSON**, **no need to reimplement the HTML construction in JavaScript**. Take the HTML you're already making, wrap it in an update tag, and, voila, your page comes alive.
29
92
 
30
93
  With this Rails integration, you can create these asynchronous updates directly in response to your model changes. Turbo uses Active Jobs to provide asynchronous partial rendering and Action Cable to deliver those updates to subscribers.
31
94
 
95
+ This gem provides a `turbo_stream_from` helper to create a turbo stream.
96
+
97
+ ```erb
98
+ <%# app/views/todos/show.html.erb %>
99
+ <%= turbo_stream_from dom_id(@todo) %>
100
+
101
+ <%# Rest of show here %>
102
+ ```
103
+
104
+ [See documentation](https://turbo.hotwired.dev/handbook/streams).
32
105
 
33
106
  ## Installation
34
107
 
35
- The JavaScript for Turbo can either be run through the asset pipeline, which is included with this gem, or through the package that lives on NPM, through Webpacker.
108
+ This gem is automatically configured for applications made with Rails 7+ (unless --skip-hotwire is passed to the generator). But if you're on Rails 6, you can install it manually:
36
109
 
37
110
  1. Add the `turbo-rails` gem to your Gemfile: `gem 'turbo-rails'`
38
111
  2. Run `./bin/bundle install`
39
112
  3. Run `./bin/rails turbo:install`
113
+ 4. Run `./bin/rails turbo:install:redis` to change the development Action Cable adapter from Async (the default one) to Redis. The Async adapter does not support Turbo Stream broadcasting.
114
+
115
+ Running `turbo:install` will install through NPM if Node.js is used in the application. Otherwise the asset pipeline version is used. To use the asset pipeline version, you must have `importmap-rails` installed first and listed higher in the Gemfile.
40
116
 
41
- Running `turbo:install` will install through NPM if Webpacker is installed in the application. Otherwise the asset pipeline version is used.
117
+ If you're using node and need to use the cable consumer, you can import [`cable`](https://github.com/hotwired/turbo-rails/blob/main/app/javascript/turbo/cable.js) (`import { cable } from "@hotwired/turbo-rails"`), but ensure that your application actually *uses* the members it `import`s when using this style (see [turbo-rails#48](https://github.com/hotwired/turbo-rails/issues/48)).
42
118
 
43
- If you're using Webpack and need to use either the cable consumer or the Turbo instance, you can import [`Turbo`](https://turbo.hotwire.dev/reference/drive) and/or [`cable`](https://github.com/hotwired/turbo-rails/blob/87542edecc4008c46249e5d8ede79b3eda62a5e2/app/javascript/turbo/cable.js) (`import { Turbo, cable } from "@hotwired/turbo-rails"`), but ensure that your application actually *uses* the members it `import`s when using this style (see [turbo-rails#48](https://github.com/hotwired/turbo-rails/issues/48)).
119
+ The `Turbo` instance is automatically assigned to `window.Turbo` upon import:
120
+
121
+ ```js
122
+ import "@hotwired/turbo-rails"
123
+ ```
44
124
 
45
125
 
46
126
  ## Usage
47
127
 
48
- You can watch [the video introduction to Hotwire](https://hotwire.dev/#screencast), which focuses extensively on demonstration Turbo in a Rails demo. Then you should familiarize yourself with [Turbo handbook](https://turbo.hotwire.dev/handbook/introduction) to understand Drive, Frames, and Streams in-depth. Finally, dive into the code documentation by starting with [`Turbo::FramesHelper`](https://github.com/hotwired/turbo-rails/blob/main/app/helpers/turbo/frames_helper.rb), [`Turbo::StreamsHelper`](https://github.com/hotwired/turbo-rails/blob/main/app/helpers/turbo/streams_helper.rb), [`Turbo::Streams::TagBuilder`](https://github.com/hotwired/turbo-rails/blob/main/app/models/turbo/streams/tag_builder.rb), and [`Turbo::Broadcastable`](https://github.com/hotwired/turbo-rails/blob/main/app/models/concerns/turbo/broadcastable.rb).
128
+ You can watch [the video introduction to Hotwire](https://hotwired.dev/#screencast), which focuses extensively on demonstrating Turbo in a Rails demo. Then you should familiarize yourself with [Turbo handbook](https://turbo.hotwired.dev/handbook/introduction) to understand Drive, Frames, and Streams in-depth. Finally, dive into the code documentation by starting with [`Turbo::FramesHelper`](https://github.com/hotwired/turbo-rails/blob/main/app/helpers/turbo/frames_helper.rb), [`Turbo::StreamsHelper`](https://github.com/hotwired/turbo-rails/blob/main/app/helpers/turbo/streams_helper.rb), [`Turbo::Streams::TagBuilder`](https://github.com/hotwired/turbo-rails/blob/main/app/models/turbo/streams/tag_builder.rb), and [`Turbo::Broadcastable`](https://github.com/hotwired/turbo-rails/blob/main/app/models/concerns/turbo/broadcastable.rb).
129
+
130
+ ### RubyDoc Documentation
131
+
132
+ For the API documentation covering this gem's classes and packages, [visit the RubyDoc page](https://rubydoc.info/github/hotwired/turbo-rails/main).
133
+
134
+ ## Compatibility with Rails UJS
135
+
136
+ Turbo can coexist with Rails UJS, but you need to take a series of upgrade steps to make it happen. See [the upgrading guide](https://github.com/hotwired/turbo-rails/blob/main/UPGRADING.md).
137
+
138
+ ## Testing
139
+
140
+
141
+ The [`Turbo::TestAssertions`](./lib/turbo/test_assertions.rb) concern provides Turbo Stream test helpers that assert the presence or absence of `<turbo-stream>` elements in a rendered fragment of HTML. `Turbo::TestAssertions` are automatically included in [`ActiveSupport::TestCase`](https://edgeapi.rubyonrails.org/classes/ActiveSupport/TestCase.html) and depend on the presence of [`rails-dom-testing`](https://github.com/rails/rails-dom-testing/) assertions.
142
+
143
+ The [`Turbo::TestAssertions::IntegrationTestAssertions`](./lib/turbo/test_assertions/integration_test_assertions.rb) are built on top of `Turbo::TestAssertions`, and add support for passing a `status:` keyword. They are automatically included in [`ActionDispatch::IntegrationTest`](https://edgeguides.rubyonrails.org/testing.html#integration-testing).
49
144
 
145
+ The [`Turbo::Broadcastable::TestHelper`](./lib/turbo/broadcastable/test_helper.rb) concern provides Action Cable-aware test helpers that assert that `<turbo-stream>` elements were or were not broadcast over Action Cable. They are not automatically included. To use them in your tests, make sure to `include Turbo::Broadcastable::TestHelper`.
50
146
 
51
147
  ## Development
52
148
 
53
- * To run the Rails tests: `bundle exec rake`.
54
- * To compile the JavaScript for the asset pipeline: `yarn build`
149
+ Run the tests with `./bin/test`.
55
150
 
56
151
 
57
152
  ## License
data/Rakefile CHANGED
@@ -2,10 +2,27 @@ require "bundler/setup"
2
2
  require "bundler/gem_tasks"
3
3
  require "rake/testtask"
4
4
 
5
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
6
+ load "rails/tasks/engine.rake"
7
+ load "rails/tasks/statistics.rake"
8
+
5
9
  Rake::TestTask.new do |test|
6
10
  test.libs << "test"
7
11
  test.test_files = FileList["test/**/*_test.rb"]
8
- test.warning = false
9
12
  end
10
13
 
11
- task default: :test
14
+ task :test_prereq do
15
+ puts "Installing Ruby dependencies"
16
+ `bundle install`
17
+
18
+ puts "Installing JavaScript dependencies"
19
+ `yarn install`
20
+
21
+ puts "Building JavaScript"
22
+ `yarn build`
23
+
24
+ puts "Preparing test database"
25
+ `cd test/dummy; ./bin/rails db:test:prepare; cd ../..`
26
+ end
27
+
28
+ task default: [:test_prereq, :test]