Skip to content

Commit 2ecd478

Browse files
committed
rails install generator working again, attempt to fix intermittent poly assoc failures
1 parent 2c242d7 commit 2ecd478

File tree

8 files changed

+160
-114
lines changed

8 files changed

+160
-114
lines changed

docs/installation/installation.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ This template will create a **new** Rails app with Webpacker from Hyperstack edg
2323
Simply run the command below to create a new Rails app with Hyperstack all configured:
2424

2525
```
26-
rails new MyApp -m https://rawgit.com/hyperstack-org/hyperstack/edge/install/rails-webpacker.rb
26+
rails new MyApp -T -m https://rawgit.com/hyperstack-org/hyperstack/edge/install/rails-webpacker.rb
2727
```
28+
> Note: The -T flag will not install minitest directories, leaving room for Rspec and HyperSpec see the HyperSpec readme under "Tools" for more info.
2829
2930
### Start the Rails app
3031

@@ -37,14 +38,21 @@ If you have an existing Rails app, you can use the built in generator to install
3738

3839
+ add `gem 'rails-hyperstack', "~> 1.0.alpha1.0"` to your gem file
3940
+ run `bundle install`
40-
+ run `rails g hyperstack:install`
41+
+ run `bundle exec rails g hyperstack:install`
4142

43+
> Note: if you want to use the unreleased edge branch your gem specification will be:
44+
```ruby
45+
gem 'rails-hyperstack',
46+
git: 'git://github.com/hyperstack-org/hyperstack.git',
47+
branch: 'edge',
48+
glob: 'ruby/*/*.gemspec'
49+
```
4250
### Start the Rails app
4351

44-
+ `foreman start` to start Rails and the Hotloader
52+
+ `bundle exec foreman start` to start Rails and the Hotloader
4553
+ Navigate to `http://localhost:5000/`
4654

47-
> Note that the generator will add a wild card route to the beginning of your routes file. This will let you immediately test Hyperstack, but will also mean that all of your existing routes are now unreachable. So after getting Hyperstack up, you will want to adjust things to your needs. See that last steps in the detailed installation for more info.
55+
> Note that the generator will add a wild card route to the beginning of your routes file. This will let you immediately test Hyperstack, but will also mean that all of your existing routes are now unreachable. So after getting Hyperstack up, you will want to adjust things to your needs. See that last steps in the **Manual Installation** section for more info.
4856
4957
## Manual Installation
5058

@@ -96,8 +104,6 @@ documented uniform interface to the DOM. To use it require it and its Rails
96104
counter part in `application.js` before the `hyperstack-loader`
97105

98106
```javascript
99-
//= require jquery
100-
//= require jquery_ujs
101107
//= require hyperstack-loader
102108
//= require_tree .
103109
```

docs/tools/hyper-spec.md

Lines changed: 94 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
# HyperSpec
22

3-
**Work in progress - ALPHA (docs and code)**
4-
5-
With HyperSpec you can run *isomorphic* specs for all your Hyperloop code using RSpec. Everything runs as standard RSpec test specs.
3+
With HyperSpec you can run *isomorphic* specs for all your Hyperstack code using RSpec. Everything runs as standard RSpec test specs.
64

75
For example if you have a component like this:
86

97
```ruby
10-
class SayHello < React::Component::Base
8+
class SayHello < HyperComponent
119
param :name
1210
render(DIV) do
13-
"Hello there #{params.name}"
11+
"Hello there #{name}"
1412
end
1513
end
1614
```
@@ -30,13 +28,13 @@ The `mount` method will setup a blank client window, and *mount* the named compo
3028

3129
Notice that the spec will need a client environment so we must set `js: true`.
3230

33-
The `mount` method can also take a block which will be recompiled and set to the client before mounting the component. You can place any client side code in the mount block including the definition of components.
31+
The `mount` method can also take a block which will be recompiled and sent to the client before mounting the component. You can place any client side code in the mount block including the definition of components.
3432

3533
```ruby
3634
describe "the mount's code block", js: true do
3735
it 'will be recompiled on the client' do
3836
mount 'ShowOff' do
39-
class ShowOff < React::Component::Base
37+
class ShowOff < HyperComponent
4038
render(DIV) { 'Now how cool is that???' }
4139
end
4240
end
@@ -47,39 +45,106 @@ end
4745

4846
## Why?
4947

50-
Hyperloop wants to make the server-client divide as transparent to the developer as practical. Given this, it makes sense that the testing should also be done with as little concern for client versus server.
51-
52-
HyperSpec allows you to directly use tools like FactoryBot (or Hyperloop Operations) to setup some test data, then run a spec to make sure that a component correctly displays, or modifies that data. You can use Timecop to manipulate time and keep in sync between the server and client. This makes testing easier and more realistic without writing a lot of redundant code.
48+
Hyperstack wants to make the server-client divide as transparent to the developer as practical. Given this, it makes sense that the testing should also be done with as little concern for client versus server.
5349

50+
HyperSpec allows you to directly use tools like FactoryBot (or Hyperstack Operations) to setup some test data, then run a spec to make sure that a component correctly displays, or modifies that data. You can use Timecop to manipulate time and keep in sync between the server and client. This makes testing easier and more realistic without writing a lot of redundant code.
5451

5552
## Installation
5653

57-
Add this line to your application's Gemfile in the test section:
54+
These instructions are assuming you are using Rails as the backend. However the `hyper-spec` gem itself does not require Rails, so you can adapt these instructions as needed.
55+
56+
### Add the gems
5857

58+
In your `Gemfile` add
5959
```ruby
60-
gem 'hyper-spec'
60+
group :test do
61+
gem 'hyper-spec', path: '../hyperstack/ruby/hyper-spec'
62+
gem 'database_cleaner' # optional but we find it works best due to the concurrency of hyperstack
63+
end
6164
```
65+
and `bundle install`
66+
67+
### Install RSpec files
6268

63-
Execute:
69+
`bundle exec rails g rspec:install`
6470

65-
$ bundle install
71+
> Skip this step if rspec is already installed.
6672
67-
and then in your spec_helper.rb file
73+
### Configure HyperSpec
74+
75+
Update your `spec/rails_helper.rb` so it looks like this:
6876

6977
```ruby
78+
# This file is copied to spec/ when you run 'rails generate rspec:install'
79+
require 'spec_helper'
80+
ENV['RAILS_ENV'] ||= 'test'
81+
require File.expand_path('../../config/environment', __FILE__)
82+
# Prevent database truncation if the environment is production
83+
abort("The Rails environment is running in production mode!") if Rails.env.production?
84+
require 'rspec/rails'
85+
# Add additional requires below this line. Rails is not loaded until this point!
86+
87+
# THESE ARE LINES WE ARE ADDING
88+
# JUST MAKE SURE THEY ARE AFTER `require 'rspec/rails'`
89+
90+
# pull in the hyper-spec code.
7091
require 'hyper-spec'
92+
93+
# If you are using DatabaseCleaner here is where
94+
# you set the mode. We recommend truncation.
95+
DatabaseCleaner.strategy = :truncation
96+
97+
# Now we setup Rspec details
98+
RSpec.configure do |config|
99+
100+
# This is only needed if you are using DatabaseCleaner
101+
config.before(:each) do
102+
DatabaseCleaner.clean
103+
end
104+
105+
# If you are NOT using webpacker remove this block
106+
config.before(:suite) do # compile front-end
107+
Webpacker.compile
108+
end
109+
end
110+
...
71111
```
112+
### Create an install smoke test
72113

73-
You will also need to install selenium, poltergeist and firefox version **46.0.1** (ff latest still does not play well with selenium).
114+
Make sure your installation is working by creating a simple smoke test like this:
115+
```ruby
116+
# spec/hyperspec_smoke_test.rb
117+
require 'rails_helper'
118+
119+
describe 'Hyperspec', js: true do
120+
it 'can mount and test a component' do
121+
mount "HyperSpecTest" do
122+
class HyperSpecTest < HyperComponent
123+
render(DIV) do
124+
"It's Alive!"
125+
end
126+
end
127+
end
128+
expect(page).to have_content("It's Alive!")
129+
end
130+
it 'can evaluate and test expressions on the client' do
131+
expect_evaluate_ruby do
132+
[1, 2, 3].reverse
133+
end.to eq [3, 2, 1]
134+
end
135+
end
136+
```
137+
To run it do a
138+
`bundle exec rspec spec/hyperspec_smoke_test.rb`
74139

75-
Sadly at this time the selenium chrome driver does not play nicely with Opal, so you can't use Chrome. We are working on getting rid of the whole selenium business. Stay tuned.
140+
> Note that because the test does not end in `_spec.rb` it will not be run with the rest of your specs.
76141
77142
## Environment Variables
78143

79-
You can set `DRIVER` to `ff` to run the client in Firefox and see what is going on. By default tests will run in poltergeist which is quicker, but harder to debug problems.
144+
You can set `DRIVER` to `chrome` to run the client in chrome and see what is going on. By default tests will run in chrome headless mode which is quicker, but harder to debug problems.
80145

81146
```
82-
DRIVER=ff bundle exec rspec
147+
DRIVER=chrome bundle exec rspec
83148
```
84149

85150
## Spec Helpers
@@ -109,9 +174,9 @@ mounted may be actually defined in the block, which is useful for setting up top
109174

110175
```ruby
111176
mount 'Display', test: 123 do
112-
class Display < React::Component::Base
177+
class Display < HyperComponent
113178
param :test
114-
render(DIV) { params.test.to_s }
179+
render(DIV) { test.to_s }
115180
end
116181
end
117182
```
@@ -222,12 +287,12 @@ HyperReact components can *generate* events and perform callbacks. HyperSpec pr
222287

223288
```ruby
224289
mount 'CallBackOnEveryThirdClick' do
225-
class CallBackOnEveryThirdClick < React::Component::Base
226-
param :click3, type: Proc
290+
class CallBackOnEveryThirdClick < HyperComponent
291+
fires :click3
227292
def increment_click
228293
@clicks ||= 0
229294
@clicks = (@clicks + 1)
230-
params.click3(@clicks) if @clicks % 3 == 0
295+
click3!(@clicks) if @clicks % 3 == 0
231296
end
232297
render do
233298
DIV(class: :tp_clicker) { "click me" }
@@ -240,16 +305,14 @@ end
240305
expect(callback_history_for(:click3)).to eq([[3], [6]])
241306
```
242307

243-
Note that for things to work, the param must be declared as a `type: Proc`.
244-
245308
+ `callback_history_for`: the entire history given as an array of arrays
246309
+ `last_callback_for`: same as `callback_history_for(xxx).last`
247310
+ `clear_callback_history_for`: clears the array (userful for repeating test variations without remounting)
248311
+ `event_history_for, last_event_for, clear_event_history_for`: same but for events.
249312

250313
#### The `pause` Method
251314

252-
For debugging. Everything stops, until you type `go()` in the client console. Running binding.pry also has this effect, and is often sufficient, however it will also block the server from responding unless you have a multithreaded server.
315+
For debugging. Everything stops, until you type `go()` in the client console. Running `binding.pry` also has this effect, and is often sufficient, however it will also block the server from responding unless you have a multithreaded server.
253316

254317
#### The `attributes_on_client` Method
255318

@@ -263,7 +326,7 @@ In other words the method `attributes_on_client` is added to all ActiveRecord mo
263326
expect(some_record_on_server.attributes_on_client(page)[:fred]).to eq(12)
264327
```
265328

266-
Note that after persisting a record the client and server will be synced so this is mainly useful for debug or in rare cases where it is important to interrogate the value on the client before its persisted.
329+
> Note that after persisting a record the client and server will be synced so this is mainly useful for debug or in rare cases where it is important to interrogate the value on the client before its persisted.
267330
268331
#### The `size_window` Method
269332

@@ -300,7 +363,7 @@ The `add_class` method takes a class name (as a symbol or string), and hash repr
300363
it "can add classes during testing" do
301364
add_class :some_class, borderStyle: :solid
302365
mount 'StyledDiv' do
303-
class StyledDiv < React::Component::Base
366+
class StyledDiv < HyperComponent
304367
render(DIV, id: 'hello', class: 'some_class') do
305368
'Hello!'
306369
end
@@ -318,7 +381,7 @@ The rspec-steps gem will run each test without reloading the window, which is us
318381

319382
Checkout the rspec-steps example in the `hyper_spec.rb` file for an example.
320383

321-
*Note that hopefully in the near future we are going to build a custom capybara driver that will just directly talk to Hyperloop on the client side. Once this is in place these troubles should go away! - Volunteers welcome to help!*
384+
> Note that hopefully in the near future we are going to build a custom capybara driver that will just directly talk to Hyperstack on the client side. Once this is in place these troubles should go away! - Volunteers welcome to help!*
322385
323386
## Timecop Integration
324387

@@ -350,31 +413,4 @@ end
350413

351414
See the Timecop [README](https://github.com/travisjeffery/timecop/blob/master/README.markdown) for more details.
352415

353-
There is one confusing thing to note: On the server if you `sleep` then you will sleep for the specified number of seconds when viewed *outside* of the test. However inside the test environment if you look at Time.now, you will see it advancing according to the scale factor. Likewise if you have a `after` or `every` block on the client, you will wait according to *simulated* time.
354-
355-
## Common Problems
356-
357-
If you are getting failures on Poltergeist but not Firefox, make sure you are not requiring `browser` in your components.rb.
358-
Requiring `browser/interval` or `browser/delay` is okay.
359-
360-
## Development
361-
362-
After checking out the repo, run bundle install and you should be good to go.
363-
364-
Tests are run either by running `rake` or for more control:
365-
366-
```
367-
DRIVER=ff bundle exec rspec spec/hyper_spec.rb
368-
```
369-
370-
where DRIVER can be either `ff` (firefox) or `pg` (poltergeist - default).
371-
372-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
373-
374-
## Contributing
375-
376-
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/hyper-spec. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
377-
378-
## License
379-
380-
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
416+
> There is one confusing thing to note: On the server if you `sleep` then you will sleep for the specified number of seconds when viewed *outside* of the test. However inside the test environment if you look at Time.now, you will see it advancing according to the scale factor. Likewise if you have a `after` or `every` block on the client, you will wait according to *simulated* time.

install/rails-webpacker.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,12 @@ class Hyperstack::ApplicationPolicy
189189
Rails.application.config.assets.paths << Rails.root.join('public', 'packs', 'js').to_s
190190
RUBY
191191
end
192+
append_file 'config/environments/test.rb' do
193+
<<-RUBY
194+
config.assets.paths << Rails.root.join('public', 'packs-test', 'js').to_s
195+
RUBY
196+
end
197+
192198

193199
# ----------------------------------- application.js
194200

ruby/hyper-model/spec/batch7/poly_assoc_spec.rb

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,18 @@ def compare_to_server(model, expression, expected_result, load=true)
163163
expect_promise("Hyperstack::Model.load { #{model.class}.find(#{model.id}).#{expression} }")
164164
.to be_expected_result
165165
else
166-
wait_for_ajax
167-
expect_evaluate_ruby("#{model.class}.find(#{model.id}).#{expression}").to be_expected_result
166+
3.times do |i|
167+
begin
168+
wait_for_ajax
169+
expect_evaluate_ruby("#{model.class}.find(#{model.id}).#{expression}")
170+
.to be_expected_result
171+
break
172+
rescue RSpec::Expectations::ExpectationNotMetError => e
173+
raise e if i == 2
174+
puts "client data not yet synced will retry in 500MS"
175+
sleep 0.5
176+
end
177+
end
168178
end
169179
end
170180

ruby/hyper-router/lib/hyperstack/router/helpers.rb

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,24 @@ module Hyperstack
22
module Router
33
module Helpers
44
def match
5-
if @__hyperstack_component_params_wrapper.param_accessor_style != :hyperstack
6-
params.match
7-
else
8-
@Match
9-
end
5+
@_match_param
106
end
117

128
def location
13-
if @__hyperstack_component_params_wrapper.param_accessor_style != :hyperstack
14-
params.location
15-
else
16-
@Location
17-
end
9+
@_location_param
1810
end
1911

2012
def history
21-
if @__hyperstack_component_params_wrapper.param_accessor_style != :hyperstack
22-
params.history
23-
else
24-
@History
25-
end
13+
@_history_param
2614
end
2715

2816
def self.included(base)
2917
base.include(Hyperstack::Internal::Router::Helpers)
3018

3119
base.class_eval do
32-
param :match, default: nil
33-
param :location, default: nil
34-
param :history, default: nil
20+
param :match, default: nil, alias: :_match_param
21+
param :location, default: nil, alias: :_location_param
22+
param :history, default: nil, alias: :_history_param
3523
end
3624
end
3725
end

ruby/hyper-spec/hyper-spec.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
2626

2727
spec.add_dependency 'capybara'
2828
spec.add_dependency 'chromedriver-helper', '1.2.0'
29-
spec.add_dependency 'libv8'
29+
spec.add_dependency 'libv8', '~> 6.7.0'
3030
spec.add_dependency 'method_source'
3131
spec.add_dependency 'mini_racer', '~> 0.2.4'
3232
spec.add_dependency 'opal', '>= 0.11.0', '< 0.12.0'

0 commit comments

Comments
 (0)