opal-browser 0.2.0.beta1 → 0.3.2

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 (218) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/build.yml +95 -0
  3. data/.gitignore +3 -0
  4. data/CHANGELOG.md +8 -0
  5. data/Gemfile +17 -3
  6. data/LICENSE +2 -1
  7. data/README.md +183 -52
  8. data/Rakefile +29 -1
  9. data/config.ru +20 -3
  10. data/docs/polyfills.md +24 -0
  11. data/examples/2048/Gemfile +6 -0
  12. data/examples/2048/README.md +13 -0
  13. data/examples/2048/app/application.rb +169 -0
  14. data/examples/2048/config.ru +9 -0
  15. data/examples/canvas/Gemfile +6 -0
  16. data/examples/canvas/README.md +9 -0
  17. data/examples/canvas/app/application.rb +55 -0
  18. data/examples/canvas/config.ru +9 -0
  19. data/examples/component/Gemfile +6 -0
  20. data/examples/component/README.md +10 -0
  21. data/examples/component/app/application.rb +66 -0
  22. data/examples/component/config.ru +9 -0
  23. data/examples/integrations/README.md +24 -0
  24. data/examples/integrations/dynamic-rack-opal-sprockets-server/Gemfile +6 -0
  25. data/examples/integrations/dynamic-rack-opal-sprockets-server/README.md +16 -0
  26. data/examples/integrations/dynamic-rack-opal-sprockets-server/app/application.rb +6 -0
  27. data/examples/integrations/dynamic-rack-opal-sprockets-server/config.ru +9 -0
  28. data/examples/integrations/dynamic-roda-roda-sprockets/.gitignore +1 -0
  29. data/examples/integrations/dynamic-roda-roda-sprockets/Gemfile +7 -0
  30. data/examples/integrations/dynamic-roda-roda-sprockets/README.md +22 -0
  31. data/examples/integrations/dynamic-roda-roda-sprockets/Rakefile +4 -0
  32. data/examples/integrations/dynamic-roda-roda-sprockets/app/application.rb +6 -0
  33. data/examples/integrations/dynamic-roda-roda-sprockets/app.rb +32 -0
  34. data/examples/integrations/dynamic-roda-roda-sprockets/config.ru +3 -0
  35. data/examples/integrations/dynamic-roda-tilt/.gitignore +1 -0
  36. data/examples/integrations/dynamic-roda-tilt/Gemfile +8 -0
  37. data/examples/integrations/dynamic-roda-tilt/README.md +17 -0
  38. data/examples/integrations/dynamic-roda-tilt/Rakefile +6 -0
  39. data/examples/integrations/dynamic-roda-tilt/app/application.rb +6 -0
  40. data/examples/integrations/dynamic-roda-tilt/app.rb +50 -0
  41. data/examples/integrations/dynamic-roda-tilt/config.ru +3 -0
  42. data/examples/integrations/dynamic-sinatra-opal-sprockets-server/Gemfile +7 -0
  43. data/examples/integrations/dynamic-sinatra-opal-sprockets-server/README.md +16 -0
  44. data/examples/integrations/dynamic-sinatra-opal-sprockets-server/app/application.rb +6 -0
  45. data/examples/integrations/dynamic-sinatra-opal-sprockets-server/config.ru +29 -0
  46. data/examples/integrations/static-bash/.gitignore +2 -0
  47. data/examples/integrations/static-bash/Gemfile +3 -0
  48. data/examples/integrations/static-bash/README.md +8 -0
  49. data/examples/integrations/static-bash/app/application.rb +6 -0
  50. data/examples/integrations/static-bash/build.sh +4 -0
  51. data/examples/integrations/static-bash/index.html +10 -0
  52. data/examples/integrations/static-bash-opal-parser/.gitignore +3 -0
  53. data/examples/integrations/static-bash-opal-parser/Gemfile +3 -0
  54. data/examples/integrations/static-bash-opal-parser/README.md +10 -0
  55. data/examples/integrations/static-bash-opal-parser/build.sh +4 -0
  56. data/examples/integrations/static-bash-opal-parser/index.html +19 -0
  57. data/examples/integrations/static-rake/.gitignore +1 -0
  58. data/examples/integrations/static-rake/Gemfile +4 -0
  59. data/examples/integrations/static-rake/README.md +7 -0
  60. data/examples/integrations/static-rake/Rakefile +10 -0
  61. data/examples/integrations/static-rake/app/application.rb +6 -0
  62. data/examples/integrations/static-rake/index.html +9 -0
  63. data/examples/integrations/static-rake-guard/.gitignore +1 -0
  64. data/examples/integrations/static-rake-guard/Gemfile +6 -0
  65. data/examples/integrations/static-rake-guard/Guardfile +3 -0
  66. data/examples/integrations/static-rake-guard/README.md +10 -0
  67. data/examples/integrations/static-rake-guard/Rakefile +10 -0
  68. data/examples/integrations/static-rake-guard/app/application.rb +6 -0
  69. data/examples/integrations/static-rake-guard/index.html +9 -0
  70. data/examples/svg/.gitignore +1 -0
  71. data/examples/svg/Gemfile +4 -0
  72. data/examples/svg/README.md +7 -0
  73. data/examples/svg/Rakefile +10 -0
  74. data/examples/svg/app/application.rb +11 -0
  75. data/examples/svg/index.html +17 -0
  76. data/examples/svg/index.svg +6 -0
  77. data/index.html.erb +8 -6
  78. data/lib/opal-browser.rb +1 -0
  79. data/opal/browser/animation_frame.rb +26 -1
  80. data/opal/browser/audio/node.rb +121 -0
  81. data/opal/browser/audio/param_schedule.rb +43 -0
  82. data/opal/browser/audio.rb +66 -0
  83. data/opal/browser/blob.rb +94 -0
  84. data/opal/browser/canvas/data.rb +1 -11
  85. data/opal/browser/canvas/gradient.rb +1 -11
  86. data/opal/browser/canvas/style.rb +3 -11
  87. data/opal/browser/canvas/text.rb +1 -11
  88. data/opal/browser/canvas.rb +17 -13
  89. data/opal/browser/console.rb +3 -1
  90. data/opal/browser/cookies.rb +78 -42
  91. data/opal/browser/crypto.rb +79 -0
  92. data/opal/browser/css/declaration.rb +1 -1
  93. data/opal/browser/css/rule.rb +1 -1
  94. data/opal/browser/css/style_sheet.rb +2 -2
  95. data/opal/browser/css.rb +23 -7
  96. data/opal/browser/database/sql.rb +193 -0
  97. data/opal/browser/delay.rb +41 -7
  98. data/opal/browser/dom/attribute.rb +13 -12
  99. data/opal/browser/dom/builder.rb +31 -17
  100. data/opal/browser/dom/document.rb +174 -42
  101. data/opal/browser/dom/document_fragment.rb +18 -0
  102. data/opal/browser/dom/document_or_shadow_root.rb +19 -0
  103. data/opal/browser/dom/element/attributes.rb +111 -0
  104. data/opal/browser/dom/element/button.rb +31 -0
  105. data/opal/browser/dom/element/custom.rb +177 -0
  106. data/opal/browser/dom/element/data.rb +82 -0
  107. data/opal/browser/dom/element/editable.rb +47 -0
  108. data/opal/browser/dom/element/form.rb +38 -0
  109. data/opal/browser/dom/element/iframe.rb +37 -0
  110. data/opal/browser/dom/element/image.rb +2 -0
  111. data/opal/browser/dom/element/input.rb +48 -1
  112. data/opal/browser/dom/element/media.rb +17 -0
  113. data/opal/browser/dom/element/offset.rb +5 -0
  114. data/opal/browser/dom/element/position.rb +11 -2
  115. data/opal/browser/dom/element/scroll.rb +123 -24
  116. data/opal/browser/dom/element/select.rb +42 -0
  117. data/opal/browser/dom/element/size.rb +17 -0
  118. data/opal/browser/dom/element/template.rb +11 -0
  119. data/opal/browser/dom/element/textarea.rb +26 -0
  120. data/opal/browser/dom/element.rb +468 -238
  121. data/opal/browser/dom/mutation_observer.rb +4 -4
  122. data/opal/browser/dom/node.rb +142 -60
  123. data/opal/browser/dom/node_set.rb +73 -44
  124. data/opal/browser/dom/shadow_root.rb +12 -0
  125. data/opal/browser/dom/text.rb +2 -2
  126. data/opal/browser/dom.rb +40 -16
  127. data/opal/browser/effects.rb +180 -3
  128. data/opal/browser/event/all.rb +26 -0
  129. data/opal/browser/{dom/event → event}/animation.rb +4 -2
  130. data/opal/browser/{dom/event → event}/audio_processing.rb +4 -2
  131. data/opal/browser/{dom/event → event}/base.rb +98 -9
  132. data/opal/browser/{dom/event → event}/before_unload.rb +4 -2
  133. data/opal/browser/{dom/event → event}/clipboard.rb +11 -2
  134. data/opal/browser/{dom/event → event}/close.rb +4 -2
  135. data/opal/browser/{dom/event → event}/composition.rb +4 -2
  136. data/opal/browser/{dom/event → event}/custom.rb +3 -3
  137. data/opal/browser/event/data_transfer.rb +95 -0
  138. data/opal/browser/{dom/event → event}/device_light.rb +4 -2
  139. data/opal/browser/{dom/event → event}/device_motion.rb +4 -2
  140. data/opal/browser/{dom/event → event}/device_orientation.rb +4 -2
  141. data/opal/browser/{dom/event → event}/device_proximity.rb +4 -2
  142. data/opal/browser/{dom/event → event}/drag.rb +11 -7
  143. data/opal/browser/{dom/event → event}/focus.rb +4 -2
  144. data/opal/browser/{dom/event → event}/gamepad.rb +5 -3
  145. data/opal/browser/{dom/event → event}/hash_change.rb +4 -2
  146. data/opal/browser/{dom/event → event}/keyboard.rb +16 -3
  147. data/opal/browser/{dom/event → event}/message.rb +4 -2
  148. data/opal/browser/{dom/event → event}/mouse.rb +12 -8
  149. data/opal/browser/{dom/event → event}/page_transition.rb +4 -2
  150. data/opal/browser/{dom/event → event}/pop_state.rb +4 -2
  151. data/opal/browser/{dom/event → event}/progress.rb +4 -2
  152. data/opal/browser/{dom/event → event}/sensor.rb +4 -2
  153. data/opal/browser/{dom/event → event}/storage.rb +4 -2
  154. data/opal/browser/{dom/event → event}/touch.rb +4 -2
  155. data/opal/browser/{dom/event → event}/ui.rb +2 -2
  156. data/opal/browser/{dom/event → event}/wheel.rb +4 -2
  157. data/opal/browser/event.rb +163 -0
  158. data/opal/browser/event_source.rb +2 -2
  159. data/opal/browser/form_data.rb +225 -0
  160. data/opal/browser/history.rb +4 -8
  161. data/opal/browser/http/binary.rb +1 -0
  162. data/opal/browser/http/headers.rb +16 -2
  163. data/opal/browser/http/request.rb +46 -48
  164. data/opal/browser/http/response.rb +5 -1
  165. data/opal/browser/http.rb +25 -2
  166. data/opal/browser/immediate.rb +9 -5
  167. data/opal/browser/interval.rb +34 -11
  168. data/opal/browser/location.rb +7 -1
  169. data/opal/browser/navigator.rb +127 -7
  170. data/opal/browser/polyfill/visual_viewport.rb +216 -0
  171. data/opal/browser/screen.rb +3 -3
  172. data/opal/browser/setup/base.rb +6 -0
  173. data/opal/browser/setup/full.rb +13 -0
  174. data/opal/browser/setup/large.rb +17 -0
  175. data/opal/browser/setup/mini.rb +8 -0
  176. data/opal/browser/setup/traditional.rb +10 -0
  177. data/opal/browser/socket.rb +8 -4
  178. data/opal/browser/storage.rb +53 -35
  179. data/opal/browser/support.rb +72 -5
  180. data/opal/browser/utils.rb +94 -14
  181. data/opal/browser/version.rb +1 -1
  182. data/opal/browser/visual_viewport.rb +39 -0
  183. data/opal/browser/window/size.rb +31 -3
  184. data/opal/browser/window/view.rb +15 -0
  185. data/opal/browser/window.rb +46 -25
  186. data/opal/browser.rb +1 -10
  187. data/opal/opal-browser.rb +1 -0
  188. data/opal-browser.gemspec +3 -3
  189. data/spec/database/sql_spec.rb +139 -0
  190. data/spec/delay_spec.rb +41 -0
  191. data/spec/dom/attribute_spec.rb +49 -0
  192. data/spec/dom/builder_spec.rb +25 -8
  193. data/spec/dom/document_spec.rb +22 -0
  194. data/spec/dom/element/attributes_spec.rb +52 -0
  195. data/spec/dom/element/custom_spec.rb +106 -0
  196. data/spec/dom/element/subclass_spec.rb +144 -0
  197. data/spec/dom/element_spec.rb +181 -4
  198. data/spec/dom/mutation_observer_spec.rb +12 -8
  199. data/spec/dom/node_set_spec.rb +44 -0
  200. data/spec/dom/node_spec.rb +48 -0
  201. data/spec/dom_spec.rb +8 -0
  202. data/spec/event_source_spec.rb +15 -12
  203. data/spec/{dom/event_spec.rb → event_spec.rb} +44 -15
  204. data/spec/history_spec.rb +23 -19
  205. data/spec/http_spec.rb +19 -31
  206. data/spec/immediate_spec.rb +5 -4
  207. data/spec/interval_spec.rb +59 -0
  208. data/spec/native_cached_wrapper_spec.rb +46 -0
  209. data/spec/runner.rb +62 -69
  210. data/spec/socket_spec.rb +16 -12
  211. data/spec/spec_helper.rb +2 -5
  212. data/spec/spec_helper_promise.rb.erb +25 -0
  213. data/spec/storage_spec.rb +1 -1
  214. metadata +172 -50
  215. data/.travis.yml +0 -60
  216. data/opal/browser/dom/event.rb +0 -253
  217. data/opal/browser/http/parameters.rb +0 -8
  218. data/opal/browser/window/scroll.rb +0 -59
data/spec/history_spec.rb CHANGED
@@ -19,39 +19,43 @@ describe Browser::History do
19
19
  end
20
20
 
21
21
  describe '#back' do
22
- async 'should go back once' do
22
+ it 'should go back once' do
23
23
  expect($window.history.current).to eq('/')
24
24
  $window.history.push('/wut')
25
25
  expect($window.history.current).to eq('/wut')
26
26
 
27
- $window.on 'pop:state' do |e|
28
- e.off
27
+ promise = Browser::Promise.new
29
28
 
30
- async {
31
- expect($window.history.current).to eq('/')
32
- }
29
+ $window.one 'pop:state' do |e|
30
+ expect($window.history.current).to eq('/')
31
+ promise.resolve
33
32
  end
34
33
 
35
34
  $window.history.back
35
+ promise.for_rspec
36
36
  end
37
37
  end
38
38
 
39
39
  describe '#state' do
40
- async 'gets the right state' do
41
- $window.history.push('/wut', 42)
42
- $window.history.state.should eq(42)
43
- $window.history.push('/omg', 23)
44
- $window.history.state.should eq(23)
45
-
46
- $window.on 'pop:state' do |e|
47
- e.off
48
-
49
- async {
40
+ it 'gets the right state' do
41
+ # XX: The previous test creates a race condition with this one.
42
+ # Adding a delay fixes it.
43
+ promise = Browser::Promise.new
44
+
45
+ after 0.05 do
46
+ $window.history.push('/wut', 42)
47
+ $window.history.state.should eq(42)
48
+ $window.history.push('/omg', 23)
49
+ $window.history.state.should eq(23)
50
+
51
+ $window.one 'pop:state' do |e|
50
52
  expect(true).to eq(true)
51
- }
52
- end
53
+ promise.resolve
54
+ end
53
55
 
54
- $window.history.back(2)
56
+ $window.history.back(2)
57
+ end
58
+ promise.for_rspec
55
59
  end
56
60
  end if Browser.supports? 'History.state'
57
61
  end if Browser::History.supported?
data/spec/http_spec.rb CHANGED
@@ -2,20 +2,15 @@ require 'spec_helper'
2
2
  require 'browser/http'
3
3
 
4
4
  describe Browser::HTTP do
5
- let :path do
6
- '/http'
7
- end
5
+ let(:path) { '/http' }
6
+ let(:path_file) { '/http-file' }
8
7
 
9
8
  describe '.get' do
10
- async 'fetches a path' do
9
+ it 'fetches a path' do
11
10
  Browser::HTTP.get(path).then {|res|
12
- async {
13
- expect(res.text).to eq('lol')
14
- }
11
+ expect(res.text).to eq('lol')
15
12
  }.rescue {
16
- async {
17
- fail
18
- }
13
+ fail
19
14
  }
20
15
  end
21
16
  end
@@ -27,15 +22,11 @@ describe Browser::HTTP do
27
22
  end
28
23
 
29
24
  describe '.post' do
30
- async 'sends parameters properly' do
25
+ it 'sends parameters properly' do
31
26
  Browser::HTTP.post(path, lol: 'wut').then {|res|
32
- async {
33
- expect(res.text).to eq('ok')
34
- }
27
+ expect(res.text).to eq('ok')
35
28
  }.rescue {
36
- async {
37
- fail
38
- }
29
+ fail
39
30
  }
40
31
  end
41
32
  end
@@ -44,18 +35,19 @@ describe Browser::HTTP do
44
35
  it 'sends parameters properly' do
45
36
  expect(Browser::HTTP.post!(path, lol: 'wut').text).to eq('ok')
46
37
  end
38
+
39
+ it 'sends files properly' do
40
+ file = Browser::File.create(["content"], "yay.txt", type: "text/plain")
41
+ expect(Browser::HTTP.post!(path_file, lol: 'wut', file: file).text).to eq('ok')
42
+ end
47
43
  end
48
44
 
49
45
  describe '.put' do
50
- async 'sends parameters properly' do
46
+ it 'sends parameters properly' do
51
47
  Browser::HTTP.put(path, lol: 'wut').then {|res|
52
- async {
53
- expect(res.text).to eq('ok')
54
- }
48
+ expect(res.text).to eq('ok')
55
49
  }.rescue {
56
- async {
57
- fail
58
- }
50
+ fail
59
51
  }
60
52
  end
61
53
  end
@@ -67,15 +59,11 @@ describe Browser::HTTP do
67
59
  end
68
60
 
69
61
  describe '.delete' do
70
- async 'fetches a path' do
62
+ it 'fetches a path' do
71
63
  Browser::HTTP.delete(path).then {|res|
72
- async {
73
- expect(res.text).to eq('lol')
74
- }
64
+ expect(res.text).to eq('lol')
75
65
  }.rescue {
76
- async {
77
- fail
78
- }
66
+ fail
79
67
  }
80
68
  end
81
69
  end
@@ -3,12 +3,13 @@ require 'browser/immediate'
3
3
 
4
4
  describe Proc do
5
5
  describe '#defer' do
6
- async 'defers the parameters' do
6
+ it 'defers the parameters' do
7
+ promise = Browser::Promise.new
7
8
  proc {|a|
8
- async {
9
- expect(a).to eq(42)
10
- }
9
+ expect(a).to eq(42)
10
+ promise.resolve
11
11
  }.defer(42)
12
+ promise.for_rspec
12
13
  end
13
14
  end
14
15
  end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+ require 'browser/interval'
3
+
4
+ describe Browser::Window do
5
+ describe '#every' do
6
+ it 'calls the block multiple times' do
7
+ x = 0
8
+
9
+ promise = Browser::Promise.new
10
+ $window.every 0.3 do
11
+ x += 1
12
+
13
+ if x == 3
14
+ expect(true).to be_truthy
15
+ promise.resolve
16
+ end
17
+ end
18
+ promise.for_rspec
19
+ end
20
+ end
21
+ end
22
+
23
+ describe Kernel do
24
+ describe '#every' do
25
+ it 'calls the block multiple times' do
26
+ x = 0
27
+
28
+ promise = Browser::Promise.new
29
+ every 0.3 do
30
+ x += 1
31
+
32
+ if x == 3
33
+ expect(true).to be_truthy
34
+ promise.resolve
35
+ end
36
+ end
37
+ promise.for_rspec
38
+ end
39
+ end
40
+ end
41
+
42
+ describe Proc do
43
+ describe '#every' do
44
+ it 'calls the block multiple times' do
45
+ x = 0
46
+
47
+ promise = Browser::Promise.new
48
+ -> {
49
+ x += 1
50
+
51
+ if x == 3
52
+ expect(true).to be_truthy
53
+ promise.resolve
54
+ end
55
+ }.every 0.3
56
+ promise.for_rspec
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe Browser::NativeCachedWrapper do
4
+ it 'deduplicates DOM objects' do
5
+ expect($document.at_css("body").hash).to eq($document.body.hash)
6
+ expect($document.body.hash).not_to eq($document.body.dup.hash) # Should dup/clone have different semantics?
7
+ expect($document.body.hash).not_to eq($document.head.hash)
8
+ end
9
+
10
+ it 'accurately intercepts the last new call' do
11
+ class Demo
12
+ include Browser::NativeCachedWrapper
13
+
14
+ def self.new(arg1, arg2)
15
+ super(`{arg1: #{arg1}, arg2: #{arg2}}`)
16
+ end
17
+
18
+ def data
19
+ [:data, `#@native.arg1`, `#@native.arg2`]
20
+ end
21
+ end
22
+
23
+ class SuperDemo < Demo
24
+ def self.new(arg1, arg2, arg3)
25
+ super("superdemo", "#{arg1} - #{arg2} - #{arg3}")
26
+ end
27
+ end
28
+
29
+ expect(Demo.new("a", "b").data).to eq([:data, "a", "b"])
30
+ expect(SuperDemo.new("1", "2", "3").data).to eq([:data, "superdemo", "1 - 2 - 3"])
31
+ end
32
+
33
+ html <<-HTML
34
+ <iframe id='ifr' src='about:blank' sandbox=''></iframe>
35
+ HTML
36
+
37
+ it 'supports restricted objects' do
38
+ # Window won't be restricted
39
+ expect($window.restricted?).to eq(false)
40
+ # Iframe itself won't be restricted
41
+ expect($document['ifr'].restricted?).to eq(false)
42
+ # But its content_window will be (due to CORS)
43
+ expect($document['ifr'].content_window.restricted?).to eq(true)
44
+ end
45
+ end
46
+
data/spec/runner.rb CHANGED
@@ -1,67 +1,45 @@
1
1
  #! /usr/bin/env ruby
2
+ require 'webdrivers'
2
3
  require 'selenium/webdriver'
3
4
  require 'rest_client'
4
5
  require 'json'
5
6
 
6
- # setup tunnel
7
- begin
8
- File.open('tunnel.jar', 'w') {|f|
9
- f.write RestClient.get('http://www.browserstack.com/BrowserStackTunnel.jar').to_str
10
- }
11
-
12
- tunnel = IO.popen 'java -jar tunnel.jar $BS_AUTHKEY localhost,9292,0 -tunnelIdentifier $TRAVIS_JOB_ID'
13
-
14
- loop do
15
- break if tunnel.gets.start_with? 'You can now access'
16
- end
17
- end
18
-
19
- # configure based on environment variables
20
- hub = "http://#{ENV['BS_USERNAME']}:#{ENV['BS_AUTHKEY']}@hub.browserstack.com/wd/hub"
21
- plan = "https://#{ENV['BS_USERNAME']}:#{ENV['BS_AUTHKEY']}@www.browserstack.com/automate/plan.json"
22
- cap = Selenium::WebDriver::Remote::Capabilities.new
23
-
24
- cap['platform'] = ENV['SELENIUM_PLATFORM'] || 'ANY'
25
- cap['browser'] = ENV['SELENIUM_BROWSER'] || 'chrome'
26
- cap['browser_version'] = ENV['SELENIUM_VERSION'] if ENV['SELENIUM_VERSION']
27
-
28
- cap['browserstack.tunnelIdentifier'] = ENV['TRAVIS_JOB_ID']
29
- cap['browserstack.tunnel'] = 'true'
30
- cap['browserstack.debug'] = 'false'
31
-
32
7
  print 'Loading...'
33
8
 
34
- # wait until there's a spot in the parallel jobs
35
- begin
36
- loop do
37
- state = JSON.parse(RestClient.get(plan).to_str)
38
-
39
- if state["parallel_sessions_running"] < state["parallel_sessions_max_allowed"]
40
- break
41
- end
42
-
43
- print '.'
44
- sleep 30
45
- end
46
-
47
- browser = Selenium::WebDriver.for(:remote, url: hub, desired_capabilities: cap)
48
- browser.navigate.to('http://localhost:9292')
49
- rescue Selenium::WebDriver::Error::UnknownError
50
- retry
9
+ browser, options = case ENV['BROWSER']
10
+ when "chrome"
11
+ opts = Selenium::WebDriver::Chrome::Options.new(args: ['--headless', '--no-sandbox'])
12
+ [:chrome, opts]
13
+ when "gecko"
14
+ opts = Selenium::WebDriver::Firefox::Options.new(args: ['--headless'])
15
+ [:firefox, opts]
16
+ when "safari"
17
+ opts = Selenium::WebDriver::Safari::Options.new()
18
+ [:safari, opts]
19
+ when "edge"
20
+ opts = Selenium::WebDriver::Edge::Options.new(args: ['--headless'])
21
+ [:edge, opts]
22
+ else
23
+ raise "Wrong web browser provided in BROWSER. Acceptable values: chrome, gecko, safari, edge"
51
24
  end
52
25
 
26
+ browser = Selenium::WebDriver.for(browser, capabilities: options)
27
+ browser.navigate.to('http://localhost:9292')
28
+
53
29
  # if we don't quit the browser it will stall
54
30
  at_exit {
55
31
  browser.quit
56
32
  }
57
33
 
34
+ puts "Browser: " + browser.execute_script("return window.navigator.userAgent")
35
+
58
36
  # the title is a good way to know if anything went wrong while fetching the
59
37
  # page
60
38
  Selenium::WebDriver::Wait.new(timeout: 30, interval: 5).until {
61
39
  not browser.title.strip.empty?
62
40
  }
63
41
 
64
- unless browser.title =~ /Opal Browser/
42
+ unless browser.title =~ /Opal Browser|RSpec results/
65
43
  puts "\rThe page failed loading."
66
44
  exit 1
67
45
  end
@@ -78,37 +56,52 @@ begin
78
56
  puts "\r#{element.text}"
79
57
  exit 1
80
58
  end
81
- rescue Selenium::WebDriver::Error::TimeOutError; end
59
+ rescue Selenium::WebDriver::Error::TimeoutError; end
82
60
 
83
61
  print "\rRunning specs..."
84
62
 
85
- # wait until the specs have finished, thus changing the content of #totals
86
- Selenium::WebDriver::Wait.new(timeout: 1200, interval: 30).until {
87
- print '.'
63
+ begin
64
+ # wait until the specs have finished, thus changing the content of #totals
65
+ Selenium::WebDriver::Wait.new(timeout: 3000, interval: 30).until {
66
+ print '.'
88
67
 
89
- not browser['totals'].text.strip.empty?
90
- }
68
+ not browser['totals'].text.strip.empty?
69
+ }
91
70
 
92
- totals = browser['totals'].text
93
- duration = browser[css: '#duration strong'].text
71
+ totals = browser['totals'].text
72
+ duration = browser[css: '#duration strong'].text
94
73
 
95
- print "\r#{totals} in #{duration}"
74
+ print "\r#{totals} in #{duration}"
96
75
 
97
- # take a screenshot and upload it to imgur
98
- begin
99
- browser.save_screenshot('screenshot.png')
100
- response = RestClient.post('https://api.imgur.com/3/upload',
101
- { image: File.open('screenshot.png') },
102
- { 'Authorization' => 'Client-ID 1979876fe2a097e' })
103
-
104
- print " ("
105
- print JSON.parse(response.to_str)['data']['link']
106
- puts ")"
107
- rescue Exception
108
- puts
109
- end
76
+ # no failures, happy times
77
+ if totals =~ / 0 failures/
78
+ exit 0
79
+ end
80
+ rescue Selenium::WebDriver::Error::TimeoutError
81
+ if element = browser['rspec-error'] rescue nil
82
+ print "\r#{element.text}"
83
+ else
84
+ print "\rThe specs have timed out."
85
+ end
86
+ ensure
87
+ # take a screenshot and upload it to imgur
88
+ begin
89
+ upload = lambda do |filepath|
90
+ response = RestClient.post('https://api.imgur.com/3/upload',
91
+ { image: File.open(filepath) },
92
+ { 'Authorization' => 'Client-ID 1979876fe2a097e' })
93
+
94
+ JSON.parse(response.to_str)['data']['link']
95
+ end
110
96
 
111
- # no failures, happy times
112
- unless totals =~ / 0 failures/
113
- exit 1
97
+ w, h = browser.execute_script("return [document.body.clientWidth, document.body.clientHeight];")
98
+ browser.manage.window.resize_to(w, h)
99
+ browser.save_screenshot('screenshot.png')
100
+ screenshot_url = upload.('screenshot.png')
101
+ puts " (#{screenshot_url})"
102
+ rescue Exception
103
+ puts
104
+ end
114
105
  end
106
+
107
+ exit 1
data/spec/socket_spec.rb CHANGED
@@ -1,31 +1,35 @@
1
1
  require 'spec_helper'
2
+ require 'browser/location'
2
3
  require 'browser/socket'
3
4
 
4
5
  describe Browser::Socket do
5
6
  # FIXME: find out why it doesn't work inline
6
7
  ws = "ws://#{$window.location.host}/socket"
7
8
 
8
- async 'creates a socket' do
9
+ it 'creates a socket' do
10
+ promise = Browser::Promise.new
9
11
  Browser::Socket.new ws do |s|
10
12
  s.on :open do |e|
11
- async {
12
- expect(e.target).to be_a(Browser::Socket)
13
- }
13
+ expect(e.target).to be_a(Browser::Socket)
14
+ promise.resolve
14
15
  end
15
16
  end
17
+ promise.for_rspec
16
18
  end
17
19
 
18
- async 'receives messages' do
20
+ it 'receives messages' do
21
+ promise = Browser::Promise.new
19
22
  Browser::Socket.new ws do |s|
20
23
  s.on :message do |e|
21
- async {
22
- expect(e.data).to eq('lol')
23
- }
24
+ expect(e.data).to eq('lol')
25
+ promise.resolve
24
26
  end
25
27
  end
28
+ promise.for_rspec
26
29
  end
27
30
 
28
- async 'sends messages' do
31
+ it 'sends messages' do
32
+ promise = Browser::Promise.new
29
33
  Browser::Socket.new ws do |s|
30
34
  s.on :message do |e|
31
35
  e.off
@@ -33,11 +37,11 @@ describe Browser::Socket do
33
37
  s.print 'omg'
34
38
 
35
39
  s.on :message do |e|
36
- async {
37
- expect(e.data).to eq('omg')
38
- }
40
+ expect(e.data).to eq('omg')
41
+ promise.resolve
39
42
  end
40
43
  end
41
44
  end
45
+ promise.for_rspec
42
46
  end
43
47
  end if Browser::Socket.supported?
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1,6 @@
1
- require 'json2'
2
- require 'sizzle'
3
- require 'wgxpath.install'
4
-
1
+ require 'spec_helper_promise'
5
2
  require 'browser'
6
- require 'browser/console'
3
+ require 'console'
7
4
 
8
5
  module HtmlHelper
9
6
  # Add some html code to the body tag ready for testing. This will
@@ -0,0 +1,25 @@
1
+ <% if ENV['OPAL_BROWSER_PROMISE'] == 'v2' %>
2
+ require 'promise'
3
+ require 'promise/v2'
4
+ <% else %>
5
+ require 'promise'
6
+
7
+ # Polyfill #to_v1, which isn't present before Opal v1.3.0
8
+ class Promise
9
+ unless Promise.method_defined? :to_v1
10
+ alias to_v1 itself
11
+ end
12
+ end
13
+ <% end %>
14
+
15
+ require 'browser/utils'
16
+
17
+ module Browser
18
+ class Promise
19
+ # Return a correct promise for opal-rspec, which for now is
20
+ # PromiseV1 until opal-rspec is ported.
21
+ def for_rspec
22
+ to_v1
23
+ end
24
+ end
25
+ end
data/spec/storage_spec.rb CHANGED
@@ -22,5 +22,5 @@ describe Browser::Window do
22
22
  expect($window.session_storage.name).to eq(:default)
23
23
  expect($window.session_storage(:spec).name).to eq(:spec)
24
24
  end
25
- end
25
+ end if Browser::SessionStorage.supported?
26
26
  end