Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

all specs passing integrated server side specs with hyper-spec #85

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ vendor
.bundle
copycat
doc
spec/test_app/tmp/
spec/test_app/log/
BrowserStackLocal*
8 changes: 7 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
source 'https://rubygems.org'
gemspec

# specs
gem 'rake'
Expand All @@ -16,3 +15,10 @@ gem 'rest-client', require: false
# browser
gem 'opal', ['>= 1.0', '< 2.0']
gem 'paggio', github: 'meh/paggio'

# hyper-spec (for testing http requests, and DOM features)
git 'https://github.com/hyperstack-org/hyperstack.git', branch: 'edge', glob: 'ruby/*/*.gemspec' do
gem 'hyper-spec'
end

gemspec
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,47 @@ The suggested polyfill is
[wgxpath](https://code.google.com/p/wicked-good-xpath/), require it **before**
opal-browser.

Contributing
------------
git clone, then install the required gems:
```
$ bundle install
```
run the specs:
```
$ bundle exec rake
```

Most of the specs are run using opal-rspec. The specs that test http
functions or need a full browser environment use the hyper-spec gem to
test communication between a test rails server and the client. These specs
are marked with the `:js` tag.

You can also run all the tests in a browser by running:
```
$ bundle exec rackup
```
and then visiting `localhost:9292`

#### Debugging tips:

For the non-js specs (those that run strictly in the client) you can insert
a `debugger` breakpoint in the code. Run the browser server (`rackup`) but
before you load the page, bring up the browser debugger window.

The specs will stop when they hit your debugging breakpoint and you can poke
around.

For the js specs add the pry gem to the Gemfile, and then set a `binding.pry`
breakpoint in the problem spec. You can run the specific spec in the usual way
(i.e. `bundle exec spec/some_spec:227`) and you will hit the pry breakpoint.

Now you can check the state of the client code and do some experiments with
the `c?` method (evaluate on client)
```ruby
$ c? { HTTP.get('/http') } # code in the block is run on the client
```

License
=======

Expand Down
40 changes: 37 additions & 3 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,42 @@
# frozen_string_literal: true

require 'bundler'
Bundler.require

require 'opal/rspec/rake_task'
Opal::RSpec::RakeTask.new(:default) do |_, task|
require 'bundler/gem_tasks'
require 'rspec/core/rake_task'

# a few specs require a "real DOM" and/or a server response, so these
# specs are run using the hyper-spec gem. These specs are marked with
# the server_side_test tag.

# The remaining specs can be run using opal-rspec

# All the specs will run in the browser using opal-rspec:
# just run bundle exec rackup, and browse localhost:9292

# See spec/spec_helper.rb, spec/app.rb, and config.ru for more details

RSpec::Core::RakeTask.new(:server_and_client_specs) do |t|
t.rspec_opts = '--tag js'
t.pattern = 'spec/http_spec.rb,spec/native_cached_wrapper_spec.rb,spec/canvas/**/*_spec.rb'
end

Opal::RSpec::RakeTask.new(:opal_rspec_runner) do |_, task|
task.default_path = 'spec'
task.pattern = 'spec/**/*_spec.{rb,opal}'
end
end

task :client_only_specs do
# Must set the runner to chrome as after all we need a browser to test
# this stuff.
#
# Also can't see how to set the format to progress and exclude the js tags
# except by setting it up via SPEC_OPTS enviroment var and a require file
sh 'RUNNER=chrome '\
"SPEC_OPTS='--format progress --require exclude_requires_server' "\
'rake opal_rspec_runner'
end

task default: %i[server_and_client_specs client_only_specs] do
end
65 changes: 2 additions & 63 deletions config.ru
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'bundler'
Bundler.require
require './spec/app'

apps = []

Expand All @@ -15,67 +16,5 @@ apps << Opal::Sprockets::Server.new(sprockets: sprockets_env) { |s|
s.debug = false
}

apps << Class.new(Sinatra::Base) {
get '/http' do
"lol"
end

post '/http' do
if params['lol'] == 'wut'
"ok"
else
"fail"
end
end

put '/http' do
if params['lol'] == 'wut'
"ok"
else
"fail"
end
end

delete '/http' do
"lol"
end

post '/http-file' do
if params['lol'] == 'wut' &&
params['file'][:filename] == 'yay.txt' &&
params['file'][:tempfile].read == 'content'

"ok"
else
"fail"
end
end

get '/events' do
headers 'Content-Type' => 'text/event-stream'

stream do |out|
sleep 0.2

out << "data: lol\n" << "\n"
out << "event: custom\n" << "data: omg\n" << "\n"
out << "data: wut\n" << "\n"

sleep 10
end
end

get '/socket' do
request.websocket do |ws|
ws.onopen do
ws.send 'lol'
end

ws.onmessage do |msg|
ws.send msg
end
end
end
}

apps << app
run Rack::Cascade.new(apps)
5 changes: 5 additions & 0 deletions opal-browser.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,9 @@ Gem::Specification.new {|s|

s.add_dependency 'opal', ['>= 1.0', '< 2.0']
s.add_dependency 'paggio'

# s.add_development_dependency 'hyper-spec' # pulled in on the Gemfile as we need a specific version from github
s.add_development_dependency 'rails', '~> 6.0'
s.add_development_dependency 'opal-rails'
s.add_development_dependency 'puma'
}
8 changes: 7 additions & 1 deletion opal/browser/canvas.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class Canvas

attr_reader :element, :style, :text

def initialize(*args)
def initialize(*args, &block)
if DOM::Element === args.first
element = args.shift

Expand Down Expand Up @@ -49,6 +49,8 @@ def initialize(*args)
if @image
draw_image(@image)
end

instance_eval(&block) if block_given?
end

def width
Expand Down Expand Up @@ -93,6 +95,10 @@ def gradient(*args, &block)
Gradient.new(self, *args, &block)
end

def stroke=(value)
Browser::Canvas::Style.new(self).stroke = value
end

def clear(x = nil, y = nil, width = nil, height = nil)
x ||= 0
y ||= 0
Expand Down
4 changes: 4 additions & 0 deletions opal/browser/canvas/data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ def length
`#@native.data.length`
end

def to_a
`Array.prototype.slice.call(#@native.data)`
end

def [](index)
`#@native.data[index]`
end
Expand Down
28 changes: 20 additions & 8 deletions opal/browser/canvas/gradient.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,30 @@ class Gradient
def initialize(context, *args, &block)
@context = context

super(case args.length
when 4 then `#{@context.to_n}.createLinearGradient.apply(self, args)`
when 6 then `#{@context.to_n}.createRadialGradient.apply(self, args)`
else raise ArgumentError, "don't know where to dispatch"
end)

instance_eval(&block)
_this = @context.to_n

*args, stops = args if args.length.odd?

super case args.length
when 4 then `_this.createLinearGradient.apply(_this, args)`
when 6 then `_this.createRadialGradient.apply(_this, args)`
else raise ArgumentError,
'Gradients must be created with 4 or 6 parameters'
end
add_stops(stops)
instance_eval(&block) if block_given?
end

def add(position, color)
`#{@context.to_n}.addColorStop(position, color)`
`#{to_n}.addColorStop(position, color)`
self
end

alias add_stop add
alias add_color_stop add

def add_stops(stops)
stops&.each { |position, color| add_stop(position, color) }
self
end
end
Expand Down
2 changes: 1 addition & 1 deletion opal/browser/dom/element.rb
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ def inner_dom(&block)
# FIXME: when block passing is fixed
doc = document

self << Builder.new(doc, self, &block).to_a
self << Builder.new(doc, &block).to_a
end

# Set the inner DOM with the given node.
Expand Down
82 changes: 82 additions & 0 deletions spec/app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
require 'bundler'
Bundler.require

get '/http' do
"lol"
end

post '/http' do
if params['lol'] == 'wut'
"ok"
else
"fail"
end
end

put '/http' do
if params['lol'] == 'wut'
"ok"
else
"fail"
end
end

delete '/http' do
"lol"
end

post '/http-file' do
if params['lol'] == 'wut' &&
params['file'][:filename] == 'yay.txt' &&
params['file'][:tempfile].read == 'content'

"ok"
else
"fail"
end
end

get '/events' do
headers 'Content-Type' => 'text/event-stream'

stream do |out|
sleep 0.2

out << "data: lol\n" << "\n"
out << "event: custom\n" << "data: omg\n" << "\n"
out << "data: wut\n" << "\n"

sleep 10
end
end

get '/socket' do
request.websocket do |ws|
ws.onopen do
ws.send 'lol'
end

ws.onmessage do |msg|
ws.send msg
end
end
end

module OpalSprocketsServer
def self.opal
@opal ||= Opal::Sprockets::Server.new do |s|
s.append_path 'spec/app'
s.main = 'application'
s.debug = ENV['RACK_ENV'] != 'production'
end
end
end

def app
Rack::Builder.app do
map '/assets' do
run OpalSprocketsServer.opal.sprockets
end
run Sinatra::Application
end
end
4 changes: 4 additions & 0 deletions spec/app/application.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require 'opal'
require 'browser'
require 'browser/http'
require 'browser/canvas'
9 changes: 9 additions & 0 deletions spec/browser/http.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# stub the Browser::HTTP class and supported? method
# for running code server side with hyper-spec
module Browser
class HTTP
def self.supported?
true
end
end
end
6 changes: 6 additions & 0 deletions spec/browser/native_cached_wrapper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# stub the Browser::NativeCachedWrapper class method
# for running code server side with hyper-spec
module Browser
module NativeCachedWrapper
end
end
Loading