opal-browser 0.2.0 → 0.3.3

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 (202) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/build.yml +78 -0
  3. data/.gitignore +3 -0
  4. data/CHANGELOG.md +11 -0
  5. data/Gemfile +17 -3
  6. data/LICENSE +2 -1
  7. data/README.md +131 -54
  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 +2 -3
  78. data/opal/browser/audio/node.rb +121 -0
  79. data/opal/browser/audio/param_schedule.rb +43 -0
  80. data/opal/browser/audio.rb +66 -0
  81. data/opal/browser/blob.rb +94 -0
  82. data/opal/browser/canvas/data.rb +1 -1
  83. data/opal/browser/canvas/gradient.rb +1 -1
  84. data/opal/browser/canvas/style.rb +3 -1
  85. data/opal/browser/canvas/text.rb +1 -1
  86. data/opal/browser/canvas.rb +17 -3
  87. data/opal/browser/console.rb +3 -1
  88. data/opal/browser/cookies.rb +72 -34
  89. data/opal/browser/crypto.rb +79 -0
  90. data/opal/browser/css/declaration.rb +1 -1
  91. data/opal/browser/css/rule.rb +1 -1
  92. data/opal/browser/css/style_sheet.rb +2 -2
  93. data/opal/browser/css.rb +23 -7
  94. data/opal/browser/database/sql.rb +7 -8
  95. data/opal/browser/delay.rb +16 -0
  96. data/opal/browser/dom/attribute.rb +1 -1
  97. data/opal/browser/dom/builder.rb +29 -10
  98. data/opal/browser/dom/document.rb +81 -13
  99. data/opal/browser/dom/document_fragment.rb +18 -0
  100. data/opal/browser/dom/document_or_shadow_root.rb +19 -0
  101. data/opal/browser/dom/element/attributes.rb +28 -4
  102. data/opal/browser/dom/element/button.rb +31 -0
  103. data/opal/browser/dom/element/custom.rb +177 -0
  104. data/opal/browser/dom/element/data.rb +17 -2
  105. data/opal/browser/dom/element/editable.rb +47 -0
  106. data/opal/browser/dom/element/form.rb +38 -0
  107. data/opal/browser/dom/element/iframe.rb +37 -0
  108. data/opal/browser/dom/element/image.rb +2 -0
  109. data/opal/browser/dom/element/input.rb +36 -0
  110. data/opal/browser/dom/element/media.rb +17 -0
  111. data/opal/browser/dom/element/scroll.rb +106 -74
  112. data/opal/browser/dom/element/select.rb +6 -0
  113. data/opal/browser/dom/element/size.rb +12 -0
  114. data/opal/browser/dom/element/template.rb +2 -0
  115. data/opal/browser/dom/element/textarea.rb +2 -0
  116. data/opal/browser/dom/element.rb +194 -50
  117. data/opal/browser/dom/mutation_observer.rb +2 -2
  118. data/opal/browser/dom/node.rb +53 -13
  119. data/opal/browser/dom/node_set.rb +13 -2
  120. data/opal/browser/dom/shadow_root.rb +12 -0
  121. data/opal/browser/dom/text.rb +2 -2
  122. data/opal/browser/dom.rb +38 -5
  123. data/opal/browser/effects.rb +170 -4
  124. data/opal/browser/event/all.rb +26 -0
  125. data/opal/browser/event/animation.rb +2 -0
  126. data/opal/browser/event/audio_processing.rb +2 -0
  127. data/opal/browser/event/base.rb +35 -4
  128. data/opal/browser/event/before_unload.rb +2 -0
  129. data/opal/browser/event/clipboard.rb +9 -0
  130. data/opal/browser/event/close.rb +2 -0
  131. data/opal/browser/event/composition.rb +2 -0
  132. data/opal/browser/event/custom.rb +1 -1
  133. data/opal/browser/event/data_transfer.rb +95 -0
  134. data/opal/browser/event/device_light.rb +2 -0
  135. data/opal/browser/event/device_motion.rb +2 -0
  136. data/opal/browser/event/device_orientation.rb +2 -0
  137. data/opal/browser/event/device_proximity.rb +2 -0
  138. data/opal/browser/event/drag.rb +9 -5
  139. data/opal/browser/event/focus.rb +2 -0
  140. data/opal/browser/event/gamepad.rb +3 -1
  141. data/opal/browser/event/hash_change.rb +2 -0
  142. data/opal/browser/event/keyboard.rb +14 -1
  143. data/opal/browser/event/message.rb +2 -0
  144. data/opal/browser/event/mouse.rb +10 -6
  145. data/opal/browser/event/page_transition.rb +2 -0
  146. data/opal/browser/event/pop_state.rb +2 -0
  147. data/opal/browser/event/progress.rb +2 -0
  148. data/opal/browser/event/sensor.rb +2 -0
  149. data/opal/browser/event/storage.rb +2 -0
  150. data/opal/browser/event/touch.rb +2 -0
  151. data/opal/browser/event/wheel.rb +2 -0
  152. data/opal/browser/event.rb +26 -116
  153. data/opal/browser/event_source.rb +1 -1
  154. data/opal/browser/form_data.rb +225 -0
  155. data/opal/browser/history.rb +4 -8
  156. data/opal/browser/http/request.rb +32 -10
  157. data/opal/browser/http/response.rb +5 -1
  158. data/opal/browser/http.rb +0 -2
  159. data/opal/browser/immediate.rb +0 -2
  160. data/opal/browser/location.rb +7 -1
  161. data/opal/browser/navigator.rb +105 -4
  162. data/opal/browser/polyfill/visual_viewport.rb +216 -0
  163. data/opal/browser/screen.rb +2 -2
  164. data/opal/browser/setup/base.rb +6 -0
  165. data/opal/browser/setup/full.rb +13 -0
  166. data/opal/browser/setup/large.rb +17 -0
  167. data/opal/browser/setup/mini.rb +8 -0
  168. data/opal/browser/setup/traditional.rb +10 -0
  169. data/opal/browser/socket.rb +3 -3
  170. data/opal/browser/storage.rb +2 -2
  171. data/opal/browser/support.rb +46 -22
  172. data/opal/browser/utils.rb +94 -14
  173. data/opal/browser/version.rb +1 -1
  174. data/opal/browser/visual_viewport.rb +39 -0
  175. data/opal/browser/window/size.rb +14 -0
  176. data/opal/browser/window/view.rb +15 -0
  177. data/opal/browser/window.rb +29 -16
  178. data/opal/browser.rb +1 -11
  179. data/opal-browser.gemspec +3 -3
  180. data/spec/database/sql_spec.rb +43 -35
  181. data/spec/delay_spec.rb +15 -12
  182. data/spec/dom/document_spec.rb +10 -8
  183. data/spec/dom/element/custom_spec.rb +106 -0
  184. data/spec/dom/element/subclass_spec.rb +144 -0
  185. data/spec/dom/element_spec.rb +42 -0
  186. data/spec/dom/mutation_observer_spec.rb +12 -8
  187. data/spec/dom/node_spec.rb +48 -0
  188. data/spec/dom_spec.rb +8 -0
  189. data/spec/event_source_spec.rb +15 -12
  190. data/spec/{dom/event_spec.rb → event_spec.rb} +44 -15
  191. data/spec/history_spec.rb +23 -19
  192. data/spec/http_spec.rb +19 -31
  193. data/spec/immediate_spec.rb +5 -4
  194. data/spec/interval_spec.rb +18 -9
  195. data/spec/native_cached_wrapper_spec.rb +46 -0
  196. data/spec/runner.rb +37 -62
  197. data/spec/socket_spec.rb +15 -12
  198. data/spec/spec_helper.rb +2 -1
  199. data/spec/spec_helper_promise.rb.erb +25 -0
  200. metadata +120 -16
  201. data/.travis.yml +0 -74
  202. data/opal/browser/window/scroll.rb +0 -59
@@ -54,6 +54,20 @@ class Size
54
54
  def height=(value)
55
55
  set(height: value)
56
56
  end
57
+
58
+ # @!attribute inner_width
59
+ # @return [Integer] the inner width of the window
60
+
61
+ def inner_width
62
+ `#@native.innerWidth`
63
+ end
64
+
65
+ # @!attribute inner_height
66
+ # @return [Integer] the inner height of the window
67
+
68
+ def inner_height
69
+ `#@native.innerHeight`
70
+ end
57
71
  end
58
72
 
59
73
  end; end
@@ -31,6 +31,21 @@ class View
31
31
  raise NotImplementedError, 'window size unsupported'
32
32
  end
33
33
  end
34
+
35
+ # Get a device pixel ratio. Can be used to handle desktop browser
36
+ # zoom, retina devices and custom screen scale for mobile devices.
37
+ # Use $window.visual_viewport.scale to handle mobile zoom.
38
+ def zoom
39
+ `#@native.devicePixelRatio`
40
+ end
41
+
42
+ # Handle #pixel_ratio changes. This will trigger a block on zoom.
43
+ def on_zoom &block
44
+ %x{
45
+ var mqString = "(resolution: " + #@native.devicePixelRatio + "dppx)";
46
+ #@native.matchMedia(mqString).addListener(#{block.to_n});
47
+ }
48
+ end
34
49
  end
35
50
 
36
51
  end; end
@@ -1,6 +1,5 @@
1
1
  require 'browser/window/view'
2
2
  require 'browser/window/size'
3
- require 'browser/window/scroll'
4
3
 
5
4
  module Browser
6
5
 
@@ -30,7 +29,7 @@ class Window
30
29
  }
31
30
  end
32
31
 
33
- include Native
32
+ include Browser::NativeCachedWrapper
34
33
  include Event::Target
35
34
 
36
35
  target {|value|
@@ -45,8 +44,8 @@ class Window
45
44
  end
46
45
 
47
46
  # Display a prompt dialog with the passed string as text.
48
- def prompt(value)
49
- `#@native.prompt(value) || nil`
47
+ def prompt(value, default=nil)
48
+ `#@native.prompt(value, #{default || ""}) || nil`
50
49
  end
51
50
 
52
51
  # Display a confirmation dialog with the passed string as text.
@@ -54,25 +53,43 @@ class Window
54
53
  `#@native.confirm(value) || false`
55
54
  end
56
55
 
56
+ # @!attribute [r] parent
57
+ # @return [Window] parent of the current window or subframe
58
+ def parent
59
+ @parent ||= Browser::Window.new(`#@native.parent`)
60
+ end
61
+
62
+ # @!attribute [r] top
63
+ # @return [Window] reference to the topmost window in the window hierarchy
64
+ def top
65
+ @top ||= Browser::Window.new(`#@native.top`)
66
+ end
67
+
68
+ # @!attribute [r] opener
69
+ # @return [Window] reference to the window that opened the window using `open`
70
+ def opener
71
+ @opener ||= Browser::Window.new(`#@native.opener`)
72
+ end
73
+
57
74
  # Get the {View} for the window.
58
75
  #
59
76
  # @return [View]
60
77
  def view
61
- View.new(self)
78
+ @view ||= View.new(self)
62
79
  end
63
80
 
64
81
  # Get the {Size} for this window.
65
82
  #
66
83
  # @return [Size]
67
84
  def size
68
- Size.new(self)
85
+ @size ||= Size.new(self)
69
86
  end
70
87
 
71
- # Get the {Scroll} for this window.
88
+ # Get the {DOM::Element::Scroll} for this window.
72
89
  #
73
- # @return [Scroll]
90
+ # @return [DOM::Element::Scroll]
74
91
  def scroll
75
- Scroll.new(self)
92
+ @scroll ||= DOM::Element::Scroll.new(self)
76
93
  end
77
94
 
78
95
  if Browser.supports? 'Window.send'
@@ -90,11 +107,7 @@ class Window
90
107
  end
91
108
 
92
109
  def close
93
- %x{
94
- return (window.open('', '_self', '') && window.close()) ||
95
- (window.opener = null && window.close()) ||
96
- (window.opener = '' && window.close());
97
- }
110
+ `#{@native}.close()`
98
111
  end
99
112
  end
100
113
 
@@ -109,8 +122,8 @@ module Kernel
109
122
  end
110
123
 
111
124
  # (see Browser::Window#prompt)
112
- def prompt(value)
113
- $window.prompt(value)
125
+ def prompt(value, default=nil)
126
+ $window.prompt(value, default)
114
127
  end
115
128
 
116
129
  # (see Browser::Window#confirm)
data/opal/browser.rb CHANGED
@@ -1,11 +1 @@
1
- require 'native'
2
- require 'paggio'
3
-
4
- require 'browser/version'
5
- require 'browser/utils'
6
- require 'browser/support'
7
-
8
- require 'browser/event'
9
- require 'browser/window'
10
- require 'browser/dom'
11
- require 'browser/css'
1
+ require 'browser/setup/traditional'
data/opal-browser.gemspec CHANGED
@@ -4,7 +4,7 @@ require 'browser/version'
4
4
  Gem::Specification.new {|s|
5
5
  s.name = 'opal-browser'
6
6
  s.version = Browser::VERSION
7
- s.author = 'meh.'
7
+ s.author = ['meh.', 'hmdne']
8
8
  s.email = 'meh@schizofreni.co'
9
9
  s.homepage = 'http://github.com/opal/opal-browser'
10
10
  s.platform = Gem::Platform::RUBY
@@ -16,6 +16,6 @@ Gem::Specification.new {|s|
16
16
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
17
  s.require_paths = ['lib']
18
18
 
19
- s.add_dependency 'opal'
20
- s.add_dependency 'paggio'
19
+ s.add_dependency 'opal', ['>= 1.0', '< 2.0']
20
+ s.add_dependency 'paggio', '>= 0.3.0'
21
21
  }
@@ -24,107 +24,115 @@ describe Browser::Database::SQL do
24
24
  end
25
25
 
26
26
  describe '#transaction' do
27
- async 'calls the block with the transaction' do
27
+ it 'calls the block with the transaction' do
28
28
  sql = SQL.new('test', size: SIZE)
29
29
 
30
+ promise = Browser::Promise.new
30
31
  sql.transaction {|t|
31
- async {
32
- expect(t).to be_a(SQL::Transaction)
33
- }
32
+ expect(t).to be_a(SQL::Transaction)
33
+ promise.resolve
34
34
  }
35
+ promise.for_rspec
35
36
  end
36
37
 
37
- async 'the transaction database is the right one' do
38
+ it 'the transaction database is the right one' do
38
39
  sql = SQL.new('test', size: SIZE)
39
40
 
41
+ promise = Browser::Promise.new
40
42
  sql.transaction {|t|
41
- async {
42
- expect(t.database).to eq(sql)
43
- }
43
+ expect(t.database).to eq(sql)
44
+ promise.resolve
44
45
  }
46
+ promise.for_rspec
45
47
  end
46
48
  end
47
49
 
48
50
  describe SQL::Transaction do
49
51
  describe '#query' do
50
- async 'returns a promise' do
52
+ it 'returns a promise' do
51
53
  sql = SQL.new('test', size: SIZE)
52
54
 
55
+ promise = Browser::Promise.new
53
56
  sql.transaction {|t|
54
- async {
55
- expect(t.query('hue')).to be_a(Promise)
56
- }
57
+ expect(t.query('hue')).to be_a(Promise)
58
+ promise.resolve
57
59
  }
60
+ promise.for_rspec
58
61
  end
59
62
 
60
- async 'resolves on success' do
63
+ it 'resolves on success' do
61
64
  sql = SQL.new('test', size: SIZE)
62
65
 
66
+ promise = Browser::Promise.new
63
67
  sql.transaction {|t|
64
68
  t.query('CREATE TABLE IF NOT EXISTS test(ID INTEGER PRIMARY KEY ASC, a TEXT)').then {|r|
65
- async {
66
- expect(r).to be_a(SQL::Result)
67
- }
69
+ expect(r).to be_a(SQL::Result)
70
+ promise.resolve
68
71
  }
69
72
  }
73
+ promise.for_rspec
70
74
  end
71
75
 
72
- async 'rejects on failure' do
76
+ it 'rejects on failure' do
73
77
  sql = SQL.new('test', size: SIZE)
74
78
 
79
+ promise = Browser::Promise.new
75
80
  sql.transaction {|t|
76
81
  t.query('huehue').rescue {|e|
77
- async {
78
- expect(e).to be_a(SQL::Error::Syntax)
79
- }
82
+ expect(e).to be_a(SQL::Error::Syntax)
83
+ promise.resolve
80
84
  }
81
85
  }
86
+ promise.for_rspec
82
87
  end
83
88
  end
84
89
  end
85
90
 
86
91
  describe SQL::Result do
87
92
  describe '#length' do
88
- async 'has the proper length' do
93
+ it 'has the proper length' do
89
94
  sql = SQL.new('test', size: SIZE)
90
95
 
96
+ promise = Browser::Promise.new
91
97
  sql.transaction {|t|
92
98
  t.query('SELECT 1').then {|r|
93
- async {
94
- expect(r.length).to eq(1)
95
- }
99
+ expect(r.length).to eq(1)
100
+ promise.resolve
96
101
  }
97
102
  }
103
+ promise.for_rspec
98
104
  end
99
105
  end
100
106
 
101
107
  describe '#[]' do
102
- async 'returns a row' do
108
+ it 'returns a row' do
103
109
  sql = SQL.new('test', size: SIZE)
104
110
 
111
+ promise = Browser::Promise.new
105
112
  sql.transaction {|t|
106
113
  t.query('SELECT 1, 2, 3').then {|r|
107
- async {
108
- expect(r[0]).to be_a(SQL::Row)
109
- expect(r[-1]).to be_a(SQL::Row)
114
+ expect(r[0]).to be_a(SQL::Row)
115
+ expect(r[-1]).to be_a(SQL::Row)
110
116
 
111
- expect(r[0]).to eq(r[-1])
112
- }
117
+ expect(r[0]).to eq(r[-1])
118
+ promise.resolve
113
119
  }
114
120
  }
121
+ promise.for_rspec
115
122
  end
116
123
 
117
- async 'returns nil on missing row' do
124
+ it 'returns nil on missing row' do
118
125
  sql = SQL.new('test', size: SIZE)
119
126
 
127
+ promise = Browser::Promise.new
120
128
  sql.transaction {|t|
121
129
  t.query('SELECT 1, 2, 3').then {|r|
122
- async {
123
- expect(r[5]).to be_nil
124
- expect(r[-5]).to be_nil
125
- }
130
+ expect(r[5]).to be_nil
131
+ expect(r[-5]).to be_nil
132
+ promise.resolve
126
133
  }
127
134
  }
135
+ promise.for_rspec
128
136
  end
129
137
  end
130
138
  end
data/spec/delay_spec.rb CHANGED
@@ -3,36 +3,39 @@ require 'browser/delay'
3
3
 
4
4
  describe Browser::Window do
5
5
  describe '#after' do
6
- async 'calls the block after the given time' do
6
+ it 'calls the block after the given time' do
7
+ promise = Browser::Promise.new
7
8
  $window.after 0.3 do
8
- async {
9
- expect(true).to be_truthy
10
- }
9
+ expect(true).to be_truthy
10
+ promise.resolve
11
11
  end
12
+ promise.for_rspec
12
13
  end
13
14
  end
14
15
  end
15
16
 
16
17
  describe Kernel do
17
18
  describe '#after' do
18
- async 'calls the block after the given time' do
19
+ it 'calls the block after the given time' do
20
+ promise = Browser::Promise.new
19
21
  after 0.3 do
20
- async {
21
- expect(true).to be_truthy
22
- }
22
+ expect(true).to be_truthy
23
+ promise.resolve
23
24
  end
25
+ promise.for_rspec
24
26
  end
25
27
  end
26
28
  end
27
29
 
28
30
  describe Proc do
29
31
  describe '#after' do
30
- async 'calls the block after the given time' do
32
+ it 'calls the block after the given time' do
33
+ promise = Browser::Promise.new
31
34
  -> {
32
- async {
33
- expect(true).to be_truthy
34
- }
35
+ expect(true).to be_truthy
36
+ promise.resolve
35
37
  }.after 0.3
38
+ promise.for_rspec
36
39
  end
37
40
  end
38
41
  end
@@ -39,22 +39,24 @@ describe Browser::DOM::Document do
39
39
  end
40
40
 
41
41
  describe "#ready" do
42
- async "calls the block when the document is ready" do
42
+ it "calls the block when the document is ready" do
43
+ promise = Browser::Promise.new
43
44
  $document.ready do
44
- async {
45
- expect(true).to be_truthy
46
- }
45
+ expect(true).to be_truthy
46
+ promise.resolve
47
47
  end
48
+ promise.for_rspec
48
49
  end
49
50
  end
50
51
 
51
52
  describe "#ready?" do
52
- async "is true inside a #ready block" do
53
+ it "is true inside a #ready block" do
54
+ promise = Browser::Promise.new
53
55
  $document.ready do
54
- async {
55
- expect($document.ready?).to be_truthy
56
- }
56
+ expect($document.ready?).to be_truthy
57
+ promise.resolve
57
58
  end
59
+ promise.for_rspec
58
60
  end
59
61
  end
60
62
  end
@@ -0,0 +1,106 @@
1
+ require 'spec_helper'
2
+ require 'browser/dom/element/custom'
3
+
4
+ describe Browser::DOM::Element::Custom do
5
+ before(:each) do
6
+ $scratchpad = Hash.new { false }
7
+ end
8
+
9
+ def create_custom_class(name, observed_attrs = [])
10
+ Class.new(Browser::DOM::Element::Custom) do
11
+ def initialize(node)
12
+ super
13
+ $scratchpad[:initialized] = true
14
+ end
15
+
16
+ def attached
17
+ $scratchpad[:attached] = true
18
+ end
19
+
20
+ def detached
21
+ $scratchpad[:detached] = true
22
+ end
23
+
24
+ def adopted
25
+ $scratchpad[:adopted] = true
26
+ end
27
+
28
+ def attribute_changed(attr, from, to)
29
+ $scratchpad[:attribute_changed] = [attr, from, to]
30
+ end
31
+
32
+ self.observed_attributes = observed_attrs
33
+
34
+ def_custom name
35
+ end
36
+ end
37
+
38
+ describe "upgrades" do
39
+ html <<-HTML
40
+ <app-ex1></app-ex1>
41
+ <app-ex2></app-ex2>
42
+ <app-ex7 prop="true"></app-ex7>
43
+ HTML
44
+
45
+ it "existing elements when they have been initialized before" do
46
+ expect($document.at_css("app-ex1").class).to eq(Browser::DOM::Element)
47
+ klass = create_custom_class("app-ex1")
48
+ expect($document.at_css("app-ex1").class).to eq(klass)
49
+ expect($scratchpad[:initialized]).to be(true)
50
+ expect($scratchpad[:attached]).to be(true)
51
+ end
52
+
53
+ it "existing elements when they have not been initialized before" do
54
+ klass = create_custom_class("app-ex2")
55
+ expect($scratchpad[:initialized]).to be(true)
56
+ expect($scratchpad[:attached]).to be(true)
57
+ expect($document.at_css("app-ex2").class).to eq(klass)
58
+ end
59
+
60
+ it "and fires property update events when upgraded" do
61
+ klass = create_custom_class("app-ex7", ["prop"])
62
+ expect($scratchpad[:attribute_changed]).to eq([:prop, nil, "true"])
63
+ end
64
+ end
65
+
66
+ it "creates and handles new elements correctly" do
67
+ klass = create_custom_class("app-ex3")
68
+ elem = klass.new
69
+ expect($scratchpad[:initialized]).to be(true)
70
+ expect($scratchpad[:attached]).to be(false)
71
+ $document.body << elem
72
+ expect($scratchpad[:detached]).to be(false)
73
+ expect($scratchpad[:attached]).to be(true)
74
+ elem.remove
75
+ expect($scratchpad[:detached]).to be(true)
76
+ end
77
+
78
+ it "correctly tracks updated properties" do
79
+ klass = create_custom_class("app-ex4")
80
+ elem = klass.new
81
+ expect($scratchpad[:attribute_changed]).to be(false)
82
+ elem[:untracked] = "test"
83
+ expect($scratchpad[:attribute_changed]).to be(false)
84
+
85
+ klass = create_custom_class("app-ex5", ["tracked"])
86
+ elem = klass.new
87
+ expect($scratchpad[:attribute_changed]).to be(false)
88
+ elem[:untracked] = "test"
89
+ expect($scratchpad[:attribute_changed]).to be(false)
90
+ elem[:tracked] = "test"
91
+ expect($scratchpad[:attribute_changed]).to eq([:tracked, nil, "test"])
92
+ end
93
+
94
+ it "allows creation of custom elements in various ways" do
95
+ klass = create_custom_class("app-ex6")
96
+
97
+ elem = klass.new
98
+ expect(elem).to be_a(klass)
99
+ elem = $document.create_element("app-ex6")
100
+ expect(elem).to be_a(klass)
101
+ elem = DOM("<app-ex6>")
102
+ expect(elem).to be_a(klass)
103
+ elem = DOM { e("app-ex6") }
104
+ expect(elem).to be_a(klass)
105
+ end
106
+ end
@@ -0,0 +1,144 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Browser::DOM::Element subclassing" do
4
+ class1 = Class.new(Browser::DOM::Element) do
5
+ def_selector ".class1"
6
+
7
+ def hello
8
+ "world"
9
+ end
10
+ end
11
+
12
+ class2 = Class.new(Browser::DOM::Element::Input) do
13
+ def_selector "input.class2[type='text']"
14
+
15
+ def hello
16
+ "goodbye"
17
+ end
18
+ end
19
+
20
+ class3 = Class.new(class2) do
21
+ def_selector "input.class2.class3[type='text']"
22
+
23
+ def self.create(value)
24
+ super().tap { |elem| elem.value = value }
25
+ end
26
+ end
27
+
28
+ class4 = Class.new(Browser::DOM::Element) do
29
+ def_selector "custom-element"
30
+
31
+ def hello
32
+ text
33
+ end
34
+ end
35
+
36
+ html <<-HTML
37
+ <div class='class1' id='hiho'></div>
38
+ <input class='class2' type='text' id='hoho'></div>
39
+ <input class='class2' type='hidden' id='hehe'></div>
40
+ <custom-element id='class4'>value</custom-element>
41
+ HTML
42
+
43
+ it 'dispatches from DOM correctly' do
44
+ elem = $document.at_css('#hiho')
45
+ expect(elem.class).to eq(class1)
46
+ expect(elem.hello).to eq('world')
47
+
48
+ elem = $document.at_css('#hoho')
49
+ expect(elem.class).to eq(class2)
50
+ expect(elem.hello).to eq('goodbye')
51
+
52
+ elem = $document.at_css('#hehe')
53
+ expect(elem.class).to eq(Browser::DOM::Element::Input)
54
+ end
55
+
56
+ it 'supports creating elements correctly' do
57
+ elem = class1.create
58
+ expect(elem.class).to eq(class1)
59
+ expect(elem.class_name).to eq('class1')
60
+ expect(elem.name).to eq('DIV')
61
+ expect(elem.hello).to eq('world')
62
+
63
+ elem = class2.create
64
+ expect(elem.class).to eq(class2)
65
+ expect(elem.class_name).to eq('class2')
66
+ expect(elem.name).to eq('INPUT')
67
+ expect(elem.hello).to eq('goodbye')
68
+ expect(elem.type).to eq('text')
69
+ end
70
+
71
+ it 'supports nested subclassing and .create overloading' do
72
+ elem = class3.create('well')
73
+ expect(elem.class).to eq(class3)
74
+ expect(elem.class_name).to eq('class2 class3')
75
+ expect(elem.value).to eq('well')
76
+ expect(elem.hello).to eq('goodbye')
77
+ end
78
+
79
+ it 'supports custom elements' do
80
+ elem = $document.at_css('#class4')
81
+ expect(elem.class).to eq(class4)
82
+ expect(elem.name).to eq('CUSTOM-ELEMENT')
83
+ expect(elem.hello).to eq('value')
84
+
85
+ elem = class4.create
86
+ expect(elem.class).to eq(class4)
87
+ expect(elem.name).to eq('CUSTOM-ELEMENT')
88
+ expect(elem.hello).to eq('')
89
+ end
90
+
91
+ it 'works with Paggio' do
92
+ elem = DOM { div.class1 }
93
+ expect(elem.class).to eq(class1)
94
+ expect(elem.hello).to eq('world')
95
+ end
96
+
97
+ it 'works with Paggio with a .create/.new intializer' do
98
+ elems = DOM {
99
+ class1.create(self)
100
+ class1.new(self, attrs: { x: :y })
101
+ class1.new(self)
102
+ }
103
+ expect(elems.class).to eq(Browser::DOM::NodeSet)
104
+ expect(elems.length).to eq(3)
105
+ expect(elems[1][:x]).to eq(:y)
106
+ expect(elems.to_ary.map(&:class)).to eq([class1] * 3)
107
+ end
108
+
109
+ it 'works with Paggio, .create/.new and nested blocks' do
110
+ elem = DOM { |d|
111
+ class1.new(d) {
112
+ d.div.noticeme
113
+ class1.new(d) {
114
+ d.div.noticeme3
115
+ }
116
+ d.div.noticeme2
117
+ }
118
+ }
119
+ expect(elem.class).to eq(class1)
120
+ expect(elem.children.length).to eq(3)
121
+ expect(elem.children[1].class).to eq(class1)
122
+ expect(elem.children[1].children.length).to eq(1)
123
+ expect(elem.children[0].class).to eq(Browser::DOM::Element)
124
+ expect(elem.children[2].class).to eq(Browser::DOM::Element)
125
+ expect(elem.children[1].children[0].class).to eq(Browser::DOM::Element)
126
+ end
127
+
128
+ it 'works with Paggio, .create/.new, nested blocks and without DOM{}' do
129
+ elem = class1.new {
130
+ div.noticeme
131
+ class1.new(self) {
132
+ div.noticeme3
133
+ }
134
+ div.noticeme2
135
+ }
136
+ expect(elem.class).to eq(class1)
137
+ expect(elem.children.length).to eq(3)
138
+ expect(elem.children[1].class).to eq(class1)
139
+ expect(elem.children[1].children.length).to eq(1)
140
+ expect(elem.children[0].class).to eq(Browser::DOM::Element)
141
+ expect(elem.children[2].class).to eq(Browser::DOM::Element)
142
+ expect(elem.children[1].children[0].class).to eq(Browser::DOM::Element)
143
+ end
144
+ end