cypress-on-rails 1.17.0 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (337) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/claude-code-review.yml +57 -0
  3. data/.github/workflows/claude.yml +50 -0
  4. data/.github/workflows/ruby.yml +14 -14
  5. data/CHANGELOG.md +319 -98
  6. data/README.md +271 -23
  7. data/RELEASING.md +200 -0
  8. data/Rakefile +1 -4
  9. data/cypress-on-rails.gemspec +1 -0
  10. data/docs/BEST_PRACTICES.md +678 -0
  11. data/docs/DX_IMPROVEMENTS.md +163 -0
  12. data/docs/PLAYWRIGHT_GUIDE.md +554 -0
  13. data/docs/RELEASE.md +124 -0
  14. data/docs/TROUBLESHOOTING.md +351 -0
  15. data/docs/VCR_GUIDE.md +499 -0
  16. data/docs/authentication.md +30 -0
  17. data/docs/factory_bot_associations.md +14 -0
  18. data/lib/cypress_on_rails/configuration.rb +29 -0
  19. data/lib/cypress_on_rails/railtie.rb +17 -2
  20. data/lib/cypress_on_rails/server.rb +197 -0
  21. data/lib/cypress_on_rails/state_reset_middleware.rb +58 -0
  22. data/lib/cypress_on_rails/vcr/insert_eject_middleware.rb +75 -0
  23. data/lib/cypress_on_rails/vcr/middleware_helpers.rb +51 -0
  24. data/lib/cypress_on_rails/vcr/use_cassette_middleware.rb +56 -0
  25. data/lib/cypress_on_rails/version.rb +1 -1
  26. data/lib/generators/cypress_on_rails/templates/config/initializers/cypress_on_rails.rb.erb +20 -0
  27. data/lib/generators/cypress_on_rails/templates/spec/cypress/e2e/rails_examples/using_factory_bot.cy.js +2 -2
  28. data/lib/generators/cypress_on_rails/templates/spec/cypress/e2e/rails_examples/using_scenarios.cy.js +1 -1
  29. data/lib/generators/cypress_on_rails/templates/spec/cypress/support/commands.js +22 -0
  30. data/lib/generators/cypress_on_rails/templates/spec/cypress/support/on-rails.js +2 -1
  31. data/lib/generators/cypress_on_rails/templates/spec/e2e/e2e_helper.rb.erb +0 -5
  32. data/lib/tasks/cypress.rake +33 -0
  33. data/rakelib/release.rake +80 -0
  34. data/rakelib/task_helpers.rb +23 -0
  35. data/rakelib/update_changelog.rake +63 -0
  36. data/spec/cypress_on_rails/configuration_spec.rb +4 -1
  37. data/spec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb +177 -0
  38. data/spec/cypress_on_rails/vcr/use_cassette_middleware_spec.rb +68 -0
  39. data/specs_e2e/rails_6_1/.gitattributes +10 -0
  40. data/specs_e2e/rails_6_1/Gemfile +20 -0
  41. data/specs_e2e/{rails_5_2 → rails_6_1}/Rakefile +1 -1
  42. data/specs_e2e/rails_6_1/app/assets/stylesheets/application.css +15 -0
  43. data/specs_e2e/rails_6_1/app/jobs/application_job.rb +7 -0
  44. data/specs_e2e/{rails_5_2 → rails_6_1}/app/views/layouts/application.html.erb +1 -1
  45. data/specs_e2e/rails_6_1/bin/bundle +114 -0
  46. data/specs_e2e/rails_6_1/bin/rails +5 -0
  47. data/specs_e2e/rails_6_1/bin/rake +5 -0
  48. data/specs_e2e/{rails_5_2 → rails_6_1}/bin/setup +15 -4
  49. data/specs_e2e/rails_6_1/bin/spring +14 -0
  50. data/specs_e2e/rails_6_1/bin/yarn +17 -0
  51. data/specs_e2e/rails_6_1/config/application.rb +34 -0
  52. data/specs_e2e/rails_6_1/config/boot.rb +4 -0
  53. data/specs_e2e/rails_6_1/config/cable.yml +10 -0
  54. data/specs_e2e/rails_6_1/config/credentials.yml.enc +1 -0
  55. data/specs_e2e/{rails_5_2 → rails_6_1}/config/database.yml +7 -0
  56. data/specs_e2e/{rails_5_2 → rails_6_1}/config/environment.rb +1 -1
  57. data/specs_e2e/{rails_5_2 → rails_6_1}/config/environments/development.rb +22 -5
  58. data/specs_e2e/rails_6_1/config/environments/production.rb +120 -0
  59. data/specs_e2e/{rails_5_2 → rails_6_1}/config/environments/test.rb +24 -7
  60. data/specs_e2e/rails_6_1/config/initializers/backtrace_silencers.rb +8 -0
  61. data/specs_e2e/{rails_5_2 → rails_6_1}/config/initializers/content_security_policy.rb +5 -0
  62. data/specs_e2e/{rails_4_2 → rails_6_1}/config/initializers/filter_parameter_logging.rb +3 -1
  63. data/specs_e2e/rails_6_1/config/initializers/permissions_policy.rb +11 -0
  64. data/specs_e2e/{rails_3_2 → rails_6_1}/config/initializers/wrap_parameters.rb +5 -1
  65. data/specs_e2e/{rails_5_2 → rails_6_1}/config/locales/en.yml +1 -1
  66. data/specs_e2e/rails_6_1/config/master.key +1 -0
  67. data/specs_e2e/rails_6_1/config/puma.rb +43 -0
  68. data/specs_e2e/rails_6_1/config/storage.yml +34 -0
  69. data/specs_e2e/{rails_5_2 → rails_6_1}/config.ru +2 -1
  70. data/specs_e2e/{rails_5_2 → rails_6_1}/db/migrate/20180621085832_create_posts.rb +1 -1
  71. data/specs_e2e/rails_6_1/package.json +8 -0
  72. data/specs_e2e/rails_6_1/playwright-report/index.html +71 -0
  73. data/specs_e2e/rails_6_1/public/robots.txt +1 -0
  74. data/specs_e2e/rails_6_1/test-results/.last-run.json +4 -0
  75. data/specs_e2e/{rails_4_2 → rails_6_1}/test.sh +22 -15
  76. data/specs_e2e/rails_7_2/.gitattributes +9 -0
  77. data/specs_e2e/rails_7_2/.gitignore +16 -0
  78. data/specs_e2e/rails_7_2/.rubocop.yml +8 -0
  79. data/specs_e2e/rails_7_2/Gemfile +11 -0
  80. data/specs_e2e/{rails_4_2 → rails_7_2}/Rakefile +1 -1
  81. data/specs_e2e/rails_7_2/app/assets/stylesheets/application.css +15 -0
  82. data/specs_e2e/rails_7_2/app/controllers/application_controller.rb +4 -0
  83. data/specs_e2e/rails_7_2/app/controllers/posts_controller.rb +58 -0
  84. data/specs_e2e/rails_7_2/app/helpers/posts_helper.rb +2 -0
  85. data/specs_e2e/rails_7_2/app/jobs/application_job.rb +7 -0
  86. data/specs_e2e/rails_7_2/app/models/application_record.rb +3 -0
  87. data/specs_e2e/rails_7_2/app/models/post.rb +2 -0
  88. data/specs_e2e/rails_7_2/app/views/layouts/application.html.erb +22 -0
  89. data/specs_e2e/rails_7_2/app/views/posts/_form.html.erb +32 -0
  90. data/specs_e2e/rails_7_2/app/views/posts/edit.html.erb +6 -0
  91. data/specs_e2e/rails_7_2/app/views/posts/index.html.erb +31 -0
  92. data/specs_e2e/rails_7_2/app/views/posts/new.html.erb +5 -0
  93. data/specs_e2e/rails_7_2/app/views/posts/show.html.erb +19 -0
  94. data/specs_e2e/rails_7_2/bin/brakeman +7 -0
  95. data/specs_e2e/rails_7_2/bin/bundle +109 -0
  96. data/specs_e2e/rails_7_2/bin/importmap +4 -0
  97. data/specs_e2e/rails_7_2/bin/rails +4 -0
  98. data/specs_e2e/rails_7_2/bin/rake +4 -0
  99. data/specs_e2e/rails_7_2/bin/setup +37 -0
  100. data/specs_e2e/rails_7_2/config/application.rb +37 -0
  101. data/specs_e2e/rails_7_2/config/boot.rb +4 -0
  102. data/specs_e2e/rails_7_2/config/cable.yml +10 -0
  103. data/specs_e2e/rails_7_2/config/credentials.yml.enc +1 -0
  104. data/specs_e2e/rails_7_2/config/database.yml +32 -0
  105. data/specs_e2e/{rails_4_2 → rails_7_2}/config/environment.rb +1 -1
  106. data/specs_e2e/rails_7_2/config/environments/development.rb +54 -0
  107. data/specs_e2e/rails_7_2/config/environments/production.rb +105 -0
  108. data/specs_e2e/rails_7_2/config/environments/test.rb +45 -0
  109. data/specs_e2e/rails_7_2/config/importmap.rb +7 -0
  110. data/specs_e2e/rails_7_2/config/initializers/content_security_policy.rb +25 -0
  111. data/specs_e2e/rails_7_2/config/initializers/filter_parameter_logging.rb +8 -0
  112. data/specs_e2e/{rails_5_2 → rails_7_2}/config/initializers/inflections.rb +4 -4
  113. data/specs_e2e/rails_7_2/config/initializers/permissions_policy.rb +13 -0
  114. data/specs_e2e/rails_7_2/config/locales/en.yml +31 -0
  115. data/specs_e2e/rails_7_2/config/master.key +1 -0
  116. data/specs_e2e/rails_7_2/config/puma.rb +34 -0
  117. data/specs_e2e/rails_7_2/config/routes.rb +5 -0
  118. data/specs_e2e/rails_7_2/config/storage.yml +34 -0
  119. data/specs_e2e/{rails_4_2 → rails_7_2}/config.ru +3 -1
  120. data/specs_e2e/rails_7_2/db/migrate/20180621085832_create_posts.rb +11 -0
  121. data/specs_e2e/rails_7_2/db/seeds.rb +9 -0
  122. data/specs_e2e/rails_7_2/db/test.sqlite3-shm +0 -0
  123. data/specs_e2e/rails_7_2/db/test.sqlite3-wal +0 -0
  124. data/specs_e2e/rails_7_2/package.json +8 -0
  125. data/specs_e2e/rails_7_2/playwright-report/index.html +71 -0
  126. data/specs_e2e/{rails_4_2 → rails_7_2}/public/404.html +6 -6
  127. data/specs_e2e/rails_7_2/public/406-unsupported-browser.html +66 -0
  128. data/specs_e2e/{rails_4_2 → rails_7_2}/public/422.html +6 -6
  129. data/specs_e2e/{rails_4_2 → rails_7_2}/public/500.html +6 -6
  130. data/specs_e2e/rails_7_2/public/icon.png +0 -0
  131. data/specs_e2e/rails_7_2/public/icon.svg +3 -0
  132. data/specs_e2e/rails_7_2/public/robots.txt +1 -0
  133. data/specs_e2e/rails_7_2/storage/test.sqlite3 +0 -0
  134. data/specs_e2e/rails_7_2/test/controllers/posts_controller_test.rb +48 -0
  135. data/specs_e2e/rails_7_2/test/cypress_fixtures/posts.yml +11 -0
  136. data/specs_e2e/rails_7_2/test/fixtures/posts.yml +11 -0
  137. data/specs_e2e/rails_7_2/test/models/post_test.rb +7 -0
  138. data/specs_e2e/rails_7_2/test-results/.last-run.json +4 -0
  139. data/specs_e2e/rails_7_2/test.sh +57 -0
  140. data/specs_e2e/rails_8/.gitattributes +9 -0
  141. data/specs_e2e/rails_8/.gitignore +16 -0
  142. data/specs_e2e/rails_8/.rubocop.yml +8 -0
  143. data/specs_e2e/rails_8/Gemfile +20 -0
  144. data/specs_e2e/{rails_3_2 → rails_8}/Rakefile +2 -3
  145. data/specs_e2e/rails_8/app/assets/stylesheets/application.css +10 -0
  146. data/specs_e2e/rails_8/app/controllers/application_controller.rb +4 -0
  147. data/specs_e2e/rails_8/app/controllers/posts_controller.rb +58 -0
  148. data/specs_e2e/rails_8/app/helpers/posts_helper.rb +2 -0
  149. data/specs_e2e/rails_8/app/jobs/application_job.rb +7 -0
  150. data/specs_e2e/rails_8/app/models/application_record.rb +3 -0
  151. data/specs_e2e/rails_8/app/models/post.rb +2 -0
  152. data/specs_e2e/rails_8/app/views/layouts/application.html.erb +27 -0
  153. data/specs_e2e/rails_8/app/views/posts/_form.html.erb +32 -0
  154. data/specs_e2e/rails_8/app/views/posts/edit.html.erb +6 -0
  155. data/specs_e2e/rails_8/app/views/posts/index.html.erb +31 -0
  156. data/specs_e2e/rails_8/app/views/posts/new.html.erb +5 -0
  157. data/specs_e2e/rails_8/app/views/posts/show.html.erb +19 -0
  158. data/specs_e2e/rails_8/bin/brakeman +7 -0
  159. data/specs_e2e/rails_8/bin/bundle +109 -0
  160. data/specs_e2e/rails_8/bin/dev +2 -0
  161. data/specs_e2e/rails_8/bin/importmap +4 -0
  162. data/specs_e2e/rails_8/bin/rails +4 -0
  163. data/specs_e2e/rails_8/bin/rake +4 -0
  164. data/specs_e2e/rails_8/bin/setup +34 -0
  165. data/specs_e2e/rails_8/bin/thrust +5 -0
  166. data/specs_e2e/rails_8/config/application.rb +27 -0
  167. data/specs_e2e/rails_8/config/boot.rb +4 -0
  168. data/specs_e2e/rails_8/config/cable.yml +17 -0
  169. data/specs_e2e/rails_8/config/cache.yml +16 -0
  170. data/specs_e2e/rails_8/config/credentials.yml.enc +1 -0
  171. data/specs_e2e/rails_8/config/database.yml +41 -0
  172. data/specs_e2e/rails_8/config/deploy.yml +116 -0
  173. data/specs_e2e/rails_8/config/environment.rb +5 -0
  174. data/specs_e2e/rails_8/config/environments/development.rb +57 -0
  175. data/specs_e2e/rails_8/config/environments/production.rb +90 -0
  176. data/specs_e2e/rails_8/config/environments/test.rb +45 -0
  177. data/specs_e2e/rails_8/config/importmap.rb +7 -0
  178. data/specs_e2e/rails_8/config/initializers/content_security_policy.rb +25 -0
  179. data/specs_e2e/rails_8/config/initializers/filter_parameter_logging.rb +8 -0
  180. data/specs_e2e/rails_8/config/initializers/inflections.rb +16 -0
  181. data/specs_e2e/rails_8/config/locales/en.yml +31 -0
  182. data/specs_e2e/rails_8/config/master.key +1 -0
  183. data/specs_e2e/rails_8/config/puma.rb +41 -0
  184. data/specs_e2e/rails_8/config/queue.yml +18 -0
  185. data/specs_e2e/rails_8/config/recurring.yml +10 -0
  186. data/specs_e2e/rails_8/config/routes.rb +5 -0
  187. data/specs_e2e/rails_8/config/storage.yml +34 -0
  188. data/specs_e2e/rails_8/config.ru +6 -0
  189. data/specs_e2e/rails_8/db/cable_schema.rb +11 -0
  190. data/specs_e2e/rails_8/db/cache_schema.rb +14 -0
  191. data/specs_e2e/rails_8/db/migrate/20180621085832_create_posts.rb +11 -0
  192. data/specs_e2e/rails_8/db/queue_schema.rb +129 -0
  193. data/specs_e2e/rails_8/db/seeds.rb +9 -0
  194. data/specs_e2e/rails_8/package.json +8 -0
  195. data/specs_e2e/rails_8/playwright-report/index.html +71 -0
  196. data/specs_e2e/rails_8/public/400.html +114 -0
  197. data/specs_e2e/rails_8/public/404.html +114 -0
  198. data/specs_e2e/rails_8/public/406-unsupported-browser.html +114 -0
  199. data/specs_e2e/rails_8/public/422.html +114 -0
  200. data/specs_e2e/rails_8/public/500.html +114 -0
  201. data/specs_e2e/rails_8/public/icon.png +0 -0
  202. data/specs_e2e/rails_8/public/icon.svg +3 -0
  203. data/specs_e2e/rails_8/public/robots.txt +1 -0
  204. data/specs_e2e/rails_8/storage/test.sqlite3 +0 -0
  205. data/specs_e2e/rails_8/storage/test.sqlite3-shm +0 -0
  206. data/specs_e2e/rails_8/storage/test.sqlite3-wal +0 -0
  207. data/specs_e2e/rails_8/test/application_system_test_case.rb +5 -0
  208. data/specs_e2e/rails_8/test/controllers/posts_controller_test.rb +48 -0
  209. data/specs_e2e/rails_8/test/cypress_fixtures/posts.yml +11 -0
  210. data/specs_e2e/rails_8/test/fixtures/posts.yml +11 -0
  211. data/specs_e2e/rails_8/test/models/post_test.rb +7 -0
  212. data/specs_e2e/rails_8/test/test_helper.rb +15 -0
  213. data/specs_e2e/rails_8/test-results/.last-run.json +4 -0
  214. data/specs_e2e/{rails_5_2 → rails_8}/test.sh +1 -1
  215. metadata +246 -150
  216. data/lib/cypress_on_rails/vcr_middleware.rb +0 -73
  217. data/spec/cypress_on_rails/vcr_middleware_spec.rb +0 -119
  218. data/specs_e2e/rails_3_2/.gitignore +0 -9
  219. data/specs_e2e/rails_3_2/.ruby_version +0 -1
  220. data/specs_e2e/rails_3_2/Gemfile +0 -7
  221. data/specs_e2e/rails_3_2/README.rdoc +0 -261
  222. data/specs_e2e/rails_3_2/app/assets/stylesheets/application.css +0 -13
  223. data/specs_e2e/rails_3_2/app/controllers/application_controller.rb +0 -3
  224. data/specs_e2e/rails_3_2/app/controllers/welcome_controller.rb +0 -4
  225. data/specs_e2e/rails_3_2/app/helpers/application_helper.rb +0 -2
  226. data/specs_e2e/rails_3_2/app/models/post.rb +0 -21
  227. data/specs_e2e/rails_3_2/app/views/layouts/application.html.erb +0 -13
  228. data/specs_e2e/rails_3_2/app/views/welcome/index.html.erb +0 -24
  229. data/specs_e2e/rails_3_2/bin/rails +0 -6
  230. data/specs_e2e/rails_3_2/config/application.rb +0 -68
  231. data/specs_e2e/rails_3_2/config/boot.rb +0 -6
  232. data/specs_e2e/rails_3_2/config/environment.rb +0 -5
  233. data/specs_e2e/rails_3_2/config/environments/development.rb +0 -31
  234. data/specs_e2e/rails_3_2/config/environments/production.rb +0 -64
  235. data/specs_e2e/rails_3_2/config/environments/test.rb +0 -35
  236. data/specs_e2e/rails_3_2/config/initializers/backtrace_silencers.rb +0 -7
  237. data/specs_e2e/rails_3_2/config/initializers/inflections.rb +0 -15
  238. data/specs_e2e/rails_3_2/config/initializers/mime_types.rb +0 -5
  239. data/specs_e2e/rails_3_2/config/initializers/secret_token.rb +0 -7
  240. data/specs_e2e/rails_3_2/config/initializers/session_store.rb +0 -8
  241. data/specs_e2e/rails_3_2/config/locales/en.yml +0 -5
  242. data/specs_e2e/rails_3_2/config/routes.rb +0 -60
  243. data/specs_e2e/rails_3_2/config.ru +0 -4
  244. data/specs_e2e/rails_3_2/public/404.html +0 -26
  245. data/specs_e2e/rails_3_2/public/422.html +0 -26
  246. data/specs_e2e/rails_3_2/public/500.html +0 -25
  247. data/specs_e2e/rails_3_2/public/robots.txt +0 -5
  248. data/specs_e2e/rails_3_2/test.sh +0 -50
  249. data/specs_e2e/rails_4_2/.gitignore +0 -12
  250. data/specs_e2e/rails_4_2/Gemfile +0 -11
  251. data/specs_e2e/rails_4_2/README.rdoc +0 -28
  252. data/specs_e2e/rails_4_2/app/assets/javascripts/using_vcr.js +0 -2
  253. data/specs_e2e/rails_4_2/app/assets/stylesheets/using_vcr.css +0 -4
  254. data/specs_e2e/rails_4_2/app/controllers/application_controller.rb +0 -5
  255. data/specs_e2e/rails_4_2/app/controllers/using_vcr_controller.rb +0 -10
  256. data/specs_e2e/rails_4_2/app/controllers/welcome_controller.rb +0 -4
  257. data/specs_e2e/rails_4_2/app/models/post.rb +0 -23
  258. data/specs_e2e/rails_4_2/app/views/layouts/application.html.erb +0 -12
  259. data/specs_e2e/rails_4_2/app/views/using_vcr/index.html.erb +0 -6
  260. data/specs_e2e/rails_4_2/app/views/using_vcr/record_cats.html.erb +0 -7
  261. data/specs_e2e/rails_4_2/app/views/welcome/index.html.erb +0 -24
  262. data/specs_e2e/rails_4_2/bin/bundle +0 -3
  263. data/specs_e2e/rails_4_2/bin/rails +0 -4
  264. data/specs_e2e/rails_4_2/bin/rake +0 -4
  265. data/specs_e2e/rails_4_2/bin/setup +0 -29
  266. data/specs_e2e/rails_4_2/config/application.rb +0 -32
  267. data/specs_e2e/rails_4_2/config/boot.rb +0 -3
  268. data/specs_e2e/rails_4_2/config/environments/development.rb +0 -25
  269. data/specs_e2e/rails_4_2/config/environments/production.rb +0 -64
  270. data/specs_e2e/rails_4_2/config/environments/test.rb +0 -42
  271. data/specs_e2e/rails_4_2/config/initializers/backtrace_silencers.rb +0 -7
  272. data/specs_e2e/rails_4_2/config/initializers/cookies_serializer.rb +0 -3
  273. data/specs_e2e/rails_4_2/config/initializers/session_store.rb +0 -3
  274. data/specs_e2e/rails_4_2/config/initializers/to_time_preserves_timezone.rb +0 -10
  275. data/specs_e2e/rails_4_2/config/initializers/wrap_parameters.rb +0 -9
  276. data/specs_e2e/rails_4_2/config/locales/en.yml +0 -23
  277. data/specs_e2e/rails_4_2/config/routes.rb +0 -61
  278. data/specs_e2e/rails_4_2/config/secrets.yml +0 -22
  279. data/specs_e2e/rails_4_2/package.json +0 -12
  280. data/specs_e2e/rails_4_2/playwright-report/index.html +0 -62
  281. data/specs_e2e/rails_4_2/public/favicon.ico +0 -0
  282. data/specs_e2e/rails_4_2/public/robots.txt +0 -5
  283. data/specs_e2e/rails_4_2/spec/fixtures/vcr_cassettes/cats.yml +0 -63
  284. data/specs_e2e/rails_5_2/Gemfile +0 -15
  285. data/specs_e2e/rails_5_2/app/assets/javascripts/posts.js +0 -2
  286. data/specs_e2e/rails_5_2/app/assets/stylesheets/posts.css +0 -4
  287. data/specs_e2e/rails_5_2/app/assets/stylesheets/scaffold.css +0 -80
  288. data/specs_e2e/rails_5_2/app/jobs/application_job.rb +0 -2
  289. data/specs_e2e/rails_5_2/app/views/welcome/index.html.erb +0 -5
  290. data/specs_e2e/rails_5_2/bin/bundle +0 -3
  291. data/specs_e2e/rails_5_2/bin/rails +0 -4
  292. data/specs_e2e/rails_5_2/bin/rake +0 -4
  293. data/specs_e2e/rails_5_2/bin/update +0 -25
  294. data/specs_e2e/rails_5_2/config/application.rb +0 -33
  295. data/specs_e2e/rails_5_2/config/boot.rb +0 -4
  296. data/specs_e2e/rails_5_2/config/credentials.yml.enc +0 -1
  297. data/specs_e2e/rails_5_2/config/environments/production.rb +0 -68
  298. data/specs_e2e/rails_5_2/config/initializers/backtrace_silencers.rb +0 -7
  299. data/specs_e2e/rails_5_2/config/initializers/filter_parameter_logging.rb +0 -4
  300. data/specs_e2e/rails_5_2/config/initializers/mime_types.rb +0 -4
  301. data/specs_e2e/rails_5_2/config/initializers/wrap_parameters.rb +0 -9
  302. data/specs_e2e/rails_5_2/config/master.key +0 -1
  303. data/specs_e2e/rails_5_2/public/favicon.ico +0 -0
  304. data/specs_e2e/rails_5_2/public/robots.txt +0 -1
  305. /data/specs_e2e/{rails_5_2 → rails_6_1}/.gitignore +0 -0
  306. /data/specs_e2e/{rails_5_2 → rails_6_1}/app/controllers/application_controller.rb +0 -0
  307. /data/specs_e2e/{rails_5_2 → rails_6_1}/app/controllers/posts_controller.rb +0 -0
  308. /data/specs_e2e/{rails_5_2 → rails_6_1}/app/helpers/posts_helper.rb +0 -0
  309. /data/specs_e2e/{rails_5_2 → rails_6_1}/app/models/application_record.rb +0 -0
  310. /data/specs_e2e/{rails_5_2 → rails_6_1}/app/models/post.rb +0 -0
  311. /data/specs_e2e/{rails_5_2 → rails_6_1}/app/views/posts/_form.html.erb +0 -0
  312. /data/specs_e2e/{rails_5_2 → rails_6_1}/app/views/posts/edit.html.erb +0 -0
  313. /data/specs_e2e/{rails_5_2 → rails_6_1}/app/views/posts/index.html.erb +0 -0
  314. /data/specs_e2e/{rails_5_2 → rails_6_1}/app/views/posts/new.html.erb +0 -0
  315. /data/specs_e2e/{rails_5_2 → rails_6_1}/app/views/posts/show.html.erb +0 -0
  316. /data/specs_e2e/{rails_5_2 → rails_6_1}/config/initializers/application_controller_renderer.rb +0 -0
  317. /data/specs_e2e/{rails_5_2 → rails_6_1}/config/initializers/cookies_serializer.rb +0 -0
  318. /data/specs_e2e/{rails_4_2 → rails_6_1}/config/initializers/inflections.rb +0 -0
  319. /data/specs_e2e/{rails_4_2 → rails_6_1}/config/initializers/mime_types.rb +0 -0
  320. /data/specs_e2e/{rails_5_2 → rails_6_1}/config/routes.rb +0 -0
  321. /data/specs_e2e/{rails_5_2 → rails_6_1}/public/404.html +0 -0
  322. /data/specs_e2e/{rails_5_2 → rails_6_1}/public/422.html +0 -0
  323. /data/specs_e2e/{rails_5_2 → rails_6_1}/public/500.html +0 -0
  324. /data/specs_e2e/{rails_5_2 → rails_6_1}/public/apple-touch-icon-precomposed.png +0 -0
  325. /data/specs_e2e/{rails_5_2 → rails_6_1}/public/apple-touch-icon.png +0 -0
  326. /data/specs_e2e/{rails_3_2 → rails_6_1}/public/favicon.ico +0 -0
  327. /data/specs_e2e/{rails_5_2 → rails_6_1}/test/controllers/posts_controller_test.rb +0 -0
  328. /data/specs_e2e/{rails_5_2 → rails_6_1}/test/cypress_fixtures/posts.yml +0 -0
  329. /data/specs_e2e/{rails_5_2 → rails_6_1}/test/fixtures/posts.yml +0 -0
  330. /data/specs_e2e/{rails_5_2 → rails_6_1}/test/models/post_test.rb +0 -0
  331. /data/specs_e2e/{rails_3_2/log → rails_6_1/vendor}/.keep +0 -0
  332. /data/specs_e2e/{rails_3_2/tmp → rails_7_2/vendor}/.keep +0 -0
  333. /data/specs_e2e/{rails_4_2/spec → rails_7_2/vendor/javascript}/.keep +0 -0
  334. /data/specs_e2e/{rails_5_2 → rails_8}/README.md +0 -0
  335. /data/specs_e2e/{rails_4_2/vendor → rails_8/storage}/.keep +0 -0
  336. /data/specs_e2e/{rails_5_2 → rails_8}/vendor/.keep +0 -0
  337. /data/specs_e2e/{rails_3_2/vendor/.gitkeep → rails_8/vendor/javascript/.keep} +0 -0
data/docs/VCR_GUIDE.md ADDED
@@ -0,0 +1,499 @@
1
+ # VCR Integration Guide
2
+
3
+ Complete guide for recording and replaying HTTP interactions in your tests using VCR with cypress-playwright-on-rails.
4
+
5
+ ## Table of Contents
6
+ - [Overview](#overview)
7
+ - [Installation](#installation)
8
+ - [Configuration](#configuration)
9
+ - [Insert/Eject Mode](#inserteject-mode)
10
+ - [Use Cassette Mode](#use-cassette-mode)
11
+ - [GraphQL Integration](#graphql-integration)
12
+ - [Advanced Usage](#advanced-usage)
13
+ - [Troubleshooting](#troubleshooting)
14
+
15
+ ## Overview
16
+
17
+ VCR (Video Cassette Recorder) records your test suite's HTTP interactions and replays them during future test runs for fast, deterministic tests. This is particularly useful for:
18
+ - Testing against third-party APIs
19
+ - Avoiding rate limits
20
+ - Testing without internet connection
21
+ - Ensuring consistent test data
22
+ - Speeding up test execution
23
+
24
+ ## Installation
25
+
26
+ ### 1. Add required gems
27
+ ```ruby
28
+ # Gemfile
29
+ group :test, :development do
30
+ gem 'vcr'
31
+ gem 'webmock'
32
+ gem 'cypress-on-rails', '~> 1.0'
33
+ end
34
+ ```
35
+
36
+ ### 2. Install npm package (optional, for enhanced features)
37
+ ```bash
38
+ yarn add -D cypress-on-rails
39
+ # or
40
+ npm install --save-dev cypress-on-rails
41
+ ```
42
+
43
+ ## Configuration
44
+
45
+ ### Basic VCR Setup
46
+
47
+ ```ruby
48
+ # config/initializers/cypress_on_rails.rb
49
+ CypressOnRails.configure do |c|
50
+ # Enable VCR middleware
51
+ c.use_vcr_middleware = !Rails.env.production? && ENV['CYPRESS'].present?
52
+
53
+ # VCR configuration options
54
+ c.vcr_options = {
55
+ # HTTP library to hook into
56
+ hook_into: :webmock,
57
+
58
+ # Default recording mode
59
+ default_cassette_options: {
60
+ record: :once, # :once, :new_episodes, :none, :all
61
+ match_requests_on: [:method, :uri, :body],
62
+ allow_unused_http_interactions: false
63
+ },
64
+
65
+ # Where to save cassettes
66
+ cassette_library_dir: Rails.root.join('spec/fixtures/vcr_cassettes'),
67
+
68
+ # Configure which hosts to ignore
69
+ ignore_hosts: ['localhost', '127.0.0.1', '0.0.0.0'],
70
+
71
+ # Filter sensitive data
72
+ filter_sensitive_data: {
73
+ '<API_KEY>' => ENV['EXTERNAL_API_KEY'],
74
+ '<AUTH_TOKEN>' => ENV['AUTH_TOKEN']
75
+ },
76
+
77
+ # Preserve exact body bytes for binary data
78
+ preserve_exact_body_bytes: true,
79
+
80
+ # Allow HTTP connections when no cassette
81
+ allow_http_connections_when_no_cassette: false
82
+ }
83
+ end
84
+ ```
85
+
86
+ ### Cypress Setup
87
+
88
+ ```js
89
+ // cypress/support/index.js
90
+ import 'cypress-on-rails/support/index'
91
+
92
+ // Optional: Configure VCR commands
93
+ Cypress.Commands.add('vcrInsert', (name, options = {}) => {
94
+ cy.app('vcr_insert_cassette', { name, ...options });
95
+ });
96
+
97
+ Cypress.Commands.add('vcrEject', () => {
98
+ cy.app('vcr_eject_cassette');
99
+ });
100
+ ```
101
+
102
+ ### Clean Command Setup
103
+
104
+ ```ruby
105
+ # e2e/app_commands/clean.rb
106
+ # Ensure cassettes are ejected between tests
107
+ VCR.eject_cassette if VCR.current_cassette
108
+ VCR.turn_off!
109
+ WebMock.disable! if defined?(WebMock)
110
+
111
+ # Your existing clean logic...
112
+ DatabaseCleaner.clean
113
+ ```
114
+
115
+ ## Insert/Eject Mode
116
+
117
+ Insert/eject mode gives you explicit control over when to start and stop recording.
118
+
119
+ ### Configuration
120
+ ```ruby
121
+ CypressOnRails.configure do |c|
122
+ c.use_vcr_middleware = !Rails.env.production? && ENV['CYPRESS'].present?
123
+ # Don't enable use_cassette mode
124
+ end
125
+ ```
126
+
127
+ ### Basic Usage
128
+ ```js
129
+ describe('External API Tests', () => {
130
+ afterEach(() => {
131
+ cy.vcr_eject_cassette();
132
+ });
133
+
134
+ it('fetches weather data', () => {
135
+ // Start recording
136
+ cy.vcr_insert_cassette('weather_api', {
137
+ record: 'new_episodes'
138
+ });
139
+
140
+ cy.visit('/weather');
141
+ cy.contains('Current Temperature');
142
+
143
+ // Recording continues until ejected
144
+ });
145
+
146
+ it('handles API errors', () => {
147
+ // Use pre-recorded cassette
148
+ cy.vcr_insert_cassette('weather_api_error', {
149
+ record: 'none' // Only replay, don't record
150
+ });
151
+
152
+ cy.visit('/weather?city=invalid');
153
+ cy.contains('City not found');
154
+ });
155
+ });
156
+ ```
157
+
158
+ ### Advanced Options
159
+ ```js
160
+ cy.vcr_insert_cassette('api_calls', {
161
+ record: 'new_episodes', // Recording mode
162
+ match_requests_on: ['method', 'uri', 'body'], // Request matching
163
+ erb: true, // Enable ERB in cassettes
164
+ allow_playback_repeats: true, // Allow multiple replays
165
+ exclusive: true, // Disallow other cassettes
166
+ serialize_with: 'json', // Use JSON format
167
+ preserve_exact_body_bytes: true, // For binary data
168
+ decode_compressed_response: true // Handle gzipped responses
169
+ });
170
+ ```
171
+
172
+ ## Use Cassette Mode
173
+
174
+ Use cassette mode automatically wraps each request with VCR.use_cassette.
175
+
176
+ ### Configuration
177
+ ```ruby
178
+ CypressOnRails.configure do |c|
179
+ # Use this instead of use_vcr_middleware
180
+ c.use_vcr_use_cassette_middleware = !Rails.env.production? && ENV['CYPRESS'].present?
181
+
182
+ c.vcr_options = {
183
+ hook_into: :webmock,
184
+ default_cassette_options: {
185
+ record: :once,
186
+ match_requests_on: [:method, :uri]
187
+ },
188
+ cassette_library_dir: Rails.root.join('spec/fixtures/vcr_cassettes')
189
+ }
190
+ end
191
+ ```
192
+
193
+ ### How It Works
194
+ Each request is automatically wrapped with `VCR.use_cassette`. The cassette name is derived from the request URL or operation name.
195
+
196
+ ### Directory Structure
197
+ ```
198
+ spec/fixtures/vcr_cassettes/
199
+ ├── api/
200
+ │ ├── users/
201
+ │ │ └── index.yml
202
+ │ └── products/
203
+ │ ├── index.yml
204
+ │ └── show.yml
205
+ └── graphql/
206
+ ├── GetUser.yml
207
+ └── CreatePost.yml
208
+ ```
209
+
210
+ ## GraphQL Integration
211
+
212
+ GraphQL requires special handling due to all requests going to the same endpoint.
213
+
214
+ ### Setup for GraphQL
215
+
216
+ ```js
217
+ // cypress/support/commands.js
218
+ Cypress.Commands.add('mockGraphQL', () => {
219
+ cy.on('window:before:load', (win) => {
220
+ const originalFetch = win.fetch;
221
+ const fetch = (path, options, ...rest) => {
222
+ if (options && options.body) {
223
+ try {
224
+ const body = JSON.parse(options.body);
225
+ // Add operation name to URL for VCR matching
226
+ if (body.operationName) {
227
+ return originalFetch(
228
+ `${path}?operation=${body.operationName}`,
229
+ options,
230
+ ...rest
231
+ );
232
+ }
233
+ } catch (e) {
234
+ return originalFetch(path, options, ...rest);
235
+ }
236
+ }
237
+ return originalFetch(path, options, ...rest);
238
+ };
239
+ cy.stub(win, 'fetch', fetch);
240
+ });
241
+ });
242
+
243
+ // cypress/support/index.js
244
+ beforeEach(() => {
245
+ cy.mockGraphQL(); // Enable GraphQL operation tracking
246
+ });
247
+ ```
248
+
249
+ ### GraphQL Test Example
250
+ ```js
251
+ it('queries user data', () => {
252
+ // Cassette will be saved as vcr_cassettes/graphql/GetUser.yml
253
+ cy.visit('/profile');
254
+
255
+ // The GraphQL query with operationName: 'GetUser'
256
+ // will be automatically recorded
257
+
258
+ cy.contains('John Doe');
259
+ });
260
+ ```
261
+
262
+ ### Custom GraphQL Matching
263
+ ```ruby
264
+ # config/initializers/cypress_on_rails.rb
265
+ c.vcr_options = {
266
+ match_requests_on: [:method, :uri,
267
+ lambda { |req1, req2|
268
+ # Custom matching for GraphQL requests
269
+ if req1.uri.path == '/graphql' && req2.uri.path == '/graphql'
270
+ body1 = JSON.parse(req1.body)
271
+ body2 = JSON.parse(req2.body)
272
+
273
+ # Match by operation name and variables
274
+ body1['operationName'] == body2['operationName'] &&
275
+ body1['variables'] == body2['variables']
276
+ else
277
+ true
278
+ end
279
+ }
280
+ ]
281
+ }
282
+ ```
283
+
284
+ ## Advanced Usage
285
+
286
+ ### Dynamic Cassette Names
287
+ ```js
288
+ // Use test context for cassette names
289
+ it('fetches user data', function() {
290
+ const cassetteName = `${this.currentTest.parent.title}_${this.currentTest.title}`
291
+ .replace(/\s+/g, '_')
292
+ .toLowerCase();
293
+
294
+ cy.vcr_insert_cassette(cassetteName, { record: 'once' });
295
+
296
+ cy.visit('/users');
297
+ // Test continues...
298
+ });
299
+ ```
300
+
301
+ ### Conditional Recording
302
+ ```js
303
+ const shouldRecord = Cypress.env('RECORD_VCR') === 'true';
304
+
305
+ cy.vcr_insert_cassette('api_calls', {
306
+ record: shouldRecord ? 'new_episodes' : 'none'
307
+ });
308
+ ```
309
+
310
+ ### Multiple Cassettes
311
+ ```js
312
+ it('combines multiple API sources', () => {
313
+ // Stack multiple cassettes
314
+ cy.vcr_insert_cassette('weather_api');
315
+ cy.vcr_insert_cassette('news_api');
316
+
317
+ cy.visit('/dashboard');
318
+
319
+ // Both APIs will be recorded
320
+
321
+ // Eject in reverse order
322
+ cy.vcr_eject_cassette(); // Ejects news_api
323
+ cy.vcr_eject_cassette(); // Ejects weather_api
324
+ });
325
+ ```
326
+
327
+ ### Custom Matchers
328
+ ```ruby
329
+ # e2e/app_commands/vcr_custom.rb
330
+ VCR.configure do |c|
331
+ # Custom request matcher
332
+ c.register_request_matcher :uri_ignoring_params do |req1, req2|
333
+ URI(req1.uri).host == URI(req2.uri).host &&
334
+ URI(req1.uri).path == URI(req2.uri).path
335
+ end
336
+ end
337
+
338
+ # Use in test
339
+ VCR.use_cassette('api_call',
340
+ match_requests_on: [:method, :uri_ignoring_params]
341
+ )
342
+ ```
343
+
344
+ ### Filtering Sensitive Data
345
+ ```ruby
346
+ VCR.configure do |c|
347
+ # Filter authorization headers
348
+ c.filter_sensitive_data('<AUTHORIZATION>') do |interaction|
349
+ interaction.request.headers['Authorization']&.first
350
+ end
351
+
352
+ # Filter API keys from URLs
353
+ c.filter_sensitive_data('<API_KEY>') do |interaction|
354
+ URI(interaction.request.uri).query
355
+ &.match(/api_key=([^&]+)/)
356
+ &.captures
357
+ &.first
358
+ end
359
+
360
+ # Filter response tokens
361
+ c.filter_sensitive_data('<TOKEN>') do |interaction|
362
+ JSON.parse(interaction.response.body)['token'] rescue nil
363
+ end
364
+ end
365
+ ```
366
+
367
+ ## Troubleshooting
368
+
369
+ ### Issue: "No route matches [POST] '/api/__e2e__/vcr/insert'"
370
+
371
+ **Solution:** Ensure VCR middleware is enabled:
372
+ ```ruby
373
+ # config/initializers/cypress_on_rails.rb
374
+ c.use_vcr_middleware = !Rails.env.production? && ENV['CYPRESS'].present?
375
+ ```
376
+
377
+ And that the API prefix matches:
378
+ ```ruby
379
+ c.api_prefix = '/api' # If your app uses /api prefix
380
+ ```
381
+
382
+ ### Issue: "VCR::Errors::UnhandledHTTPRequestError"
383
+
384
+ **Cause:** Request not matching any cassette.
385
+
386
+ **Solutions:**
387
+ 1. Re-record the cassette:
388
+ ```js
389
+ cy.vcr_insert_cassette('my_cassette', { record: 'new_episodes' });
390
+ ```
391
+
392
+ 2. Adjust matching criteria:
393
+ ```ruby
394
+ c.vcr_options = {
395
+ default_cassette_options: {
396
+ match_requests_on: [:method, :host, :path] # Ignore query params
397
+ }
398
+ }
399
+ ```
400
+
401
+ 3. Allow new requests:
402
+ ```ruby
403
+ c.vcr_options = {
404
+ default_cassette_options: {
405
+ record: 'new_episodes', # Record new requests
406
+ allow_unused_http_interactions: true
407
+ }
408
+ }
409
+ ```
410
+
411
+ ### Issue: "Cassette not found"
412
+
413
+ **Solution:** Check the cassette path:
414
+ ```ruby
415
+ # Verify the directory exists
416
+ c.vcr_options = {
417
+ cassette_library_dir: Rails.root.join('spec/fixtures/vcr_cassettes')
418
+ }
419
+ ```
420
+
421
+ Create the directory if needed:
422
+ ```bash
423
+ mkdir -p spec/fixtures/vcr_cassettes
424
+ ```
425
+
426
+ ### Issue: "WebMock::NetConnectNotAllowedError"
427
+
428
+ **Cause:** HTTP connection attempted without cassette.
429
+
430
+ **Solutions:**
431
+ 1. Insert a cassette before the request:
432
+ ```js
433
+ cy.vcr_insert_cassette('api_calls');
434
+ ```
435
+
436
+ 2. Allow connections to specific hosts:
437
+ ```ruby
438
+ WebMock.disable_net_connect!(
439
+ allow_localhost: true,
440
+ allow: ['chromedriver.storage.googleapis.com']
441
+ )
442
+ ```
443
+
444
+ 3. Disable WebMock for specific tests:
445
+ ```js
446
+ cy.app('eval', { code: 'WebMock.disable!' });
447
+ // Run test
448
+ cy.app('eval', { code: 'WebMock.enable!' });
449
+ ```
450
+
451
+ ### Issue: Binary/Encoded Response Issues
452
+
453
+ **Solution:** Configure VCR to handle binary data:
454
+ ```ruby
455
+ c.vcr_options = {
456
+ preserve_exact_body_bytes: true,
457
+ decode_compressed_response: true
458
+ }
459
+ ```
460
+
461
+ ### Issue: Timestamps in Recordings
462
+
463
+ **Solution:** Filter dynamic timestamps:
464
+ ```ruby
465
+ VCR.configure do |c|
466
+ c.before_record do |interaction|
467
+ # Normalize timestamps in responses
468
+ if interaction.response.headers['date']
469
+ interaction.response.headers['date'] = ['2024-01-01 00:00:00']
470
+ end
471
+ end
472
+ end
473
+ ```
474
+
475
+ ## Best Practices
476
+
477
+ 1. **Organize cassettes by feature**: Use subdirectories for different features
478
+ 2. **Use descriptive names**: Make cassette names self-documenting
479
+ 3. **Commit cassettes to version control**: Share recordings with team
480
+ 4. **Periodically refresh cassettes**: Re-record to catch API changes
481
+ 5. **Filter sensitive data**: Never commit real API keys or tokens
482
+ 6. **Use appropriate record modes**:
483
+ - `:once` for stable APIs
484
+ - `:new_episodes` during development
485
+ - `:none` for CI/production
486
+ 7. **Document external dependencies**: List which APIs are being mocked
487
+ 8. **Handle errors gracefully**: Record both success and error responses
488
+
489
+ ## Summary
490
+
491
+ VCR integration with cypress-playwright-on-rails provides powerful HTTP mocking capabilities. Choose between:
492
+ - **Insert/Eject mode**: For explicit control over recording
493
+ - **Use Cassette mode**: For automatic recording, especially with GraphQL
494
+
495
+ Remember to:
496
+ - Configure VCR appropriately for your needs
497
+ - Filter sensitive data
498
+ - Organize cassettes logically
499
+ - Keep cassettes up to date
@@ -51,3 +51,33 @@ cy.forceLogin()
51
51
  cy.forceLogin({redirect_to: '/profile'})
52
52
  cy.forceLogin({email: 'someuser@mail.com'})
53
53
  ```
54
+
55
+ In `playwright/support/on-rails.js`:
56
+
57
+ ```js
58
+ async function forceLogin(page, { email, redirect_to = '/' }) {
59
+ // Validate inputs
60
+ if (typeof email !== 'string' || typeof redirect_to !== 'string') {
61
+ throw new Error('Invalid input: email and redirect_to must be non-empty strings');
62
+ }
63
+
64
+ const response = await page.request.post('/__e2e__/force_login', {
65
+ data: { email: email, redirect_to: redirect_to },
66
+ headers: { 'Content-Type': 'application/json' }
67
+ });
68
+
69
+ // Handle response based on status code
70
+ if (response.ok()) {
71
+ await page.goto(redirect_to);
72
+ } else {
73
+ // Throw an exception for specific error statuses
74
+ throw new Error(`Login failed with status: ${response.status()}`);
75
+ }
76
+ }
77
+ ```
78
+
79
+ Examples of usage in Playwright specs:
80
+ ```js
81
+ await forceLogin(page, { email: 'someuser@mail.com', redirect_to: '/profile' });
82
+
83
+ ```
@@ -54,6 +54,15 @@ cy.appFactories([['create', 'author']]).then((records) => {
54
54
  })
55
55
  ```
56
56
 
57
+ then in Playwright
58
+ There are a few ways you can set up associations with the correct data using Playwright and FactoryBot.
59
+ ```js
60
+ const records = await appFactories([['create', 'author', { name: 'James' }]], context);
61
+ await appFactories([['create', 'post', { title: 'Playwright is cool', author_id: records[0].id }]], context);
62
+ // Note: These Playwright examples demonstrate asynchronous interactions with the server for setting up data associations. Ensure that your environment is configured to handle these async operations.
63
+ ```
64
+
65
+
57
66
  ## 2. Using transient attributes
58
67
 
59
68
  ```rb
@@ -81,6 +90,11 @@ cy.appFactories([['create', 'post', { title: 'Cypress is cool', author_name: 'Ja
81
90
  cy.appFactories([['create', 'post']])
82
91
  ```
83
92
 
93
+ then in Playwright
94
+ ```js
95
+ const records = await appFactories([['create', 'post', { title: 'Playwright is cool', author_name: 'James' }]]);
96
+ ```
97
+
84
98
  ## 3. Using Nested Attributes
85
99
 
86
100
  ```rb
@@ -6,8 +6,22 @@ module CypressOnRails
6
6
  attr_accessor :install_folder
7
7
  attr_accessor :use_middleware
8
8
  attr_accessor :use_vcr_middleware
9
+ attr_accessor :use_vcr_use_cassette_middleware
9
10
  attr_accessor :before_request
10
11
  attr_accessor :logger
12
+ attr_accessor :vcr_options
13
+
14
+ # Server hooks for managing test lifecycle
15
+ attr_accessor :before_server_start
16
+ attr_accessor :after_server_start
17
+ attr_accessor :after_transaction_start
18
+ attr_accessor :after_state_reset
19
+ attr_accessor :before_server_stop
20
+
21
+ # Server configuration
22
+ attr_accessor :server_host
23
+ attr_accessor :server_port
24
+ attr_accessor :transactional_server
11
25
 
12
26
  # Attributes for backwards compatibility
13
27
  def cypress_folder
@@ -25,14 +39,29 @@ module CypressOnRails
25
39
 
26
40
  alias :use_middleware? :use_middleware
27
41
  alias :use_vcr_middleware? :use_vcr_middleware
42
+ alias :use_vcr_use_cassette_middleware? :use_vcr_use_cassette_middleware
28
43
 
29
44
  def reset
30
45
  self.api_prefix = ''
31
46
  self.install_folder = 'spec/e2e'
32
47
  self.use_middleware = true
33
48
  self.use_vcr_middleware = false
49
+ self.use_vcr_use_cassette_middleware = false
34
50
  self.before_request = -> (request) {}
35
51
  self.logger = Logger.new(STDOUT)
52
+ self.vcr_options = {}
53
+
54
+ # Server hooks
55
+ self.before_server_start = nil
56
+ self.after_server_start = nil
57
+ self.after_transaction_start = nil
58
+ self.after_state_reset = nil
59
+ self.before_server_stop = nil
60
+
61
+ # Server configuration
62
+ self.server_host = ENV.fetch('CYPRESS_RAILS_HOST', 'localhost')
63
+ self.server_port = ENV.fetch('CYPRESS_RAILS_PORT', nil)
64
+ self.transactional_server = true
36
65
  end
37
66
 
38
67
  def tagged_logged
@@ -3,14 +3,29 @@ require 'cypress_on_rails/configuration'
3
3
 
4
4
  module CypressOnRails
5
5
  class Railtie < Rails::Railtie
6
+ rake_tasks do
7
+ load 'tasks/cypress.rake'
8
+ end
6
9
  initializer :setup_cypress_middleware, after: :load_config_initializers do |app|
7
10
  if CypressOnRails.configuration.use_middleware?
8
11
  require 'cypress_on_rails/middleware'
9
12
  app.middleware.use Middleware
13
+
14
+ # Add state reset middleware for compatibility with cypress-rails
15
+ require 'cypress_on_rails/state_reset_middleware'
16
+ app.middleware.use StateResetMiddleware
10
17
  end
11
18
  if CypressOnRails.configuration.use_vcr_middleware?
12
- require 'cypress_on_rails/vcr_middleware'
13
- app.middleware.use VCRMiddleware
19
+ require 'cypress_on_rails/vcr/insert_eject_middleware'
20
+ app.middleware.use Vcr::InsertEjectMiddleware
21
+ end
22
+ if CypressOnRails.configuration.use_vcr_use_cassette_middleware?
23
+ if CypressOnRails.configuration.use_vcr_middleware?
24
+ raise 'Configure only one VCR middleware at a time: use_vcr_middleware OR use_vcr_use_cassette_middleware'
25
+ end
26
+
27
+ require 'cypress_on_rails/vcr/use_cassette_middleware'
28
+ app.middleware.use Vcr::UseCassetteMiddleware
14
29
  end
15
30
  end
16
31
  end