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
@@ -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
@@ -1,14 +1,40 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Browser::DOM::Element do
4
+ DOM = Browser::DOM
5
+
4
6
  describe '#id' do
5
7
  html <<-HTML
6
- <div id="lol"></div>
8
+ <div id="lol"><div class="wut"></div></div>
7
9
  HTML
8
10
 
9
11
  it 'gets the proper id' do
10
12
  expect($document["lol"].id).to eq('lol')
11
13
  end
14
+
15
+ it 'returns nil when there is no id' do
16
+ expect($document["#lol .wut"].id).to be_nil
17
+ end
18
+ end
19
+
20
+ describe '#id=' do
21
+ html <<-HTML
22
+ <div id="lol"></div>
23
+ HTML
24
+
25
+ it 'sets the id' do
26
+ el = $document["lol"]
27
+ el.id = 'wut'
28
+
29
+ expect(el.id).to eq('wut')
30
+ end
31
+
32
+ it 'removes the id when the value is nil' do
33
+ el = $document["lol"]
34
+ el.id = nil
35
+
36
+ expect(el.id).to be_nil
37
+ end
12
38
  end
13
39
 
14
40
  describe '#class_names' do
@@ -28,7 +54,7 @@ describe Browser::DOM::Element do
28
54
  end
29
55
  end
30
56
 
31
- describe '#matches?' do
57
+ describe '#=~' do
32
58
  html <<-HTML
33
59
  <div id="matches" class="not me">
34
60
  <span class="yes me"></span>
@@ -36,11 +62,162 @@ describe Browser::DOM::Element do
36
62
  HTML
37
63
 
38
64
  it 'matches on class and id' do
39
- expect($document[:matches].matches?('#matches.not.me')).to be_truthy
65
+ expect($document[:matches] =~ '#matches.not.me').to be_truthy
40
66
  end
41
67
 
42
68
  it 'matches on class and name' do
43
- expect($document[:matches].first_element_child.matches?('span.yes')).to be_truthy
69
+ expect($document[:matches].first_element_child =~ 'span.yes').to be_truthy
70
+ end
71
+ end
72
+
73
+ describe '#inner_dom' do
74
+ html <<-HTML
75
+ <div id="lol">
76
+ <div id="wut"></div>
77
+ </div>
78
+ HTML
79
+
80
+ it 'builds the DOM and inserts it' do
81
+ $document["lol"].inner_dom {
82
+ div.omg!
83
+ }
84
+
85
+ expect($document["#lol #omg"]).to be_truthy
86
+ expect($document["#lol #wut"]).to be_falsy
87
+ end
88
+ end
89
+
90
+ describe '#inspect' do
91
+ it 'uses the node name' do
92
+ el = $document.create_element('div')
93
+
94
+ expect(el.inspect).to match(/: div>/)
95
+ end
96
+
97
+ it 'uses the id' do
98
+ el = $document.create_element('div')
99
+ el.id = 'lol'
100
+
101
+ expect(el.inspect).to match(/: div.lol!>/)
102
+ end
103
+
104
+ it 'uses the classes' do
105
+ el = $document.create_element('div')
106
+ el.add_class 'lol', 'wut'
107
+
108
+ expect(el.inspect).to match(/: div.lol.wut>/)
109
+ end
110
+
111
+ it 'uses the id and the classes' do
112
+ el = $document.create_element('div')
113
+ el.id = 'omg'
114
+ el.add_class 'lol', 'wut'
115
+
116
+ expect(el.inspect).to match(/: div.omg!.lol.wut>/)
117
+ end
118
+ end
119
+
120
+ describe '#[]' do
121
+ html <<-HTML
122
+ <label id="lol" class="name" for="hue"></label>
123
+ HTML
124
+
125
+ it 'gets an attribute' do
126
+ expect($document[:lol][:id]).to eq(:lol)
127
+ end
128
+
129
+ it 'gets the class attribute' do
130
+ expect($document[:lol][:class]).to eq(:name)
131
+ end
132
+
133
+ it 'gets the for attribute' do
134
+ expect($document[:lol][:for]).to eq(:hue)
135
+ end
136
+ end
137
+
138
+ describe '#[]=' do
139
+ html <<-HTML
140
+ <label id="lol" class="name" for="hue"></label>
141
+ HTML
142
+
143
+ it 'sets an attribute' do
144
+ $document[:lol][:a] = :foo
145
+
146
+ expect($document[:lol][:a]).to eq(:foo)
147
+ end
148
+
149
+ it 'sets the class attribute' do
150
+ $document[:lol][:class] = :bar
151
+
152
+ expect($document[:lol][:class]).to eq(:bar)
153
+ end
154
+
155
+ it 'sets the for attribute' do
156
+ $document[:lol][:for] = :baz
157
+
158
+ expect($document[:lol][:for]).to eq(:baz)
159
+ end
160
+ end
161
+
162
+ describe '#at_css' do
163
+ html <<-HTML
164
+ <label id="lol" class="name" for="hue"></label>
165
+ HTML
166
+
167
+ it 'checks for all the selectors' do
168
+ expect($document.at_css('div', 'span', '#lol')).to be_a(DOM::Element)
169
+ end
170
+ end
171
+
172
+ describe '#at_xpath' do
173
+ html <<-HTML
174
+ <label id="lol" class="name" for="hue"></label>
175
+ HTML
176
+
177
+ it 'checks for all the paths' do
178
+ expect($document.at_xpath('//div', '//span', '//[@id="lol"]')).to be_a(DOM::Element)
179
+ end
180
+ end
181
+
182
+ describe '#shadow' do
183
+ html <<-HTML
184
+ <div id="shadowtest"></div>
185
+ HTML
186
+
187
+ it 'creates a shadow root' do
188
+ expect($document[:shadowtest].shadow?).to be(false)
189
+ expect($document[:shadowtest].shadow).to be_a(DOM::ShadowRoot)
190
+ expect($document[:shadowtest].shadow?).to be(true)
191
+ end
192
+
193
+ it 'accesses a shadow root' do
194
+ $document[:shadowtest].shadow # Create one
195
+ expect($document[:shadowtest].shadow?).to be(true)
196
+ expect($document[:shadowtest].shadow).to be_a(DOM::ShadowRoot)
197
+ end
198
+
199
+ it 'works like a typical opal-browser DOM tree' do
200
+ DOM {
201
+ div.shadow_item "Hello world!"
202
+ }.append_to($document[:shadowtest].shadow)
203
+
204
+ expect($document[:shadowtest].at_css(".shadow_item")).to be_nil
205
+ expect($document[:shadowtest].shadow.at_css(".shadow_item").text).to be("Hello world!")
206
+ end
207
+
208
+ it 'supports stylesheets' do
209
+ $document[:shadowtest].shadow << CSS {
210
+ rule("p") {
211
+ color "rgb(255, 0, 0)"
212
+ }
213
+ rule(":host") {
214
+ color "rgb(0, 0, 255)"
215
+ }
216
+ } << DOM { p }
217
+
218
+ expect($document[:shadowtest].shadow.at_css("p").style!.color).to be("rgb(255, 0, 0)")
219
+ expect($document[:shadowtest].style!.color).to be("rgb(0, 0, 255)")
220
+ expect($document[:shadowtest].shadow.stylesheets.count).to be(1)
44
221
  end
45
222
  end
46
223
  end
@@ -7,11 +7,11 @@ describe Browser::DOM::MutationObserver do
7
7
  </div>
8
8
  HTML
9
9
 
10
- async 'notifies additions' do
10
+ it 'notifies additions' do
11
+ promise = Browser::Promise.new
11
12
  obs = Browser::DOM::MutationObserver.new {|mutations|
12
- async {
13
- expect(mutations.first.added.first.name).to eq('DIV')
14
- }
13
+ expect(mutations.first.added.first.name).to eq('DIV')
14
+ promise.resolve
15
15
 
16
16
  obs.disconnect
17
17
  }
@@ -19,13 +19,15 @@ describe Browser::DOM::MutationObserver do
19
19
  obs.observe $document[:mutate]
20
20
 
21
21
  $document[:mutate].add_child $document.create_element('div')
22
+
23
+ promise.for_rspec
22
24
  end
23
25
 
24
- async 'notifies removals' do
26
+ it 'notifies removals' do
27
+ promise = Browser::Promise.new
25
28
  obs = Browser::DOM::MutationObserver.new {|mutations|
26
- async {
27
- expect(mutations.first.removed.first.name).to eq('SPAN')
28
- }
29
+ expect(mutations.first.removed.first.name).to eq('SPAN')
30
+ promise.resolve
29
31
 
30
32
  obs.disconnect
31
33
  }
@@ -33,5 +35,7 @@ describe Browser::DOM::MutationObserver do
33
35
  obs.observe $document[:mutate]
34
36
 
35
37
  $document[:mutate].first_element_child.remove
38
+
39
+ promise.for_rspec
36
40
  end
37
41
  end if Browser::DOM::MutationObserver.supported?
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Browser::DOM::NodeSet do
4
+ NodeSet = Browser::DOM::NodeSet
5
+
6
+ html <<-HTML
7
+ <div id="lol">
8
+ <div class="a">
9
+ <div class="a-a"></div>
10
+ </div>
11
+
12
+ <div class="b"></div>
13
+ <div class="c"></div>
14
+
15
+ <div class="d">
16
+ <div class="d-a"></div>
17
+ </div>
18
+ </div>
19
+ HTML
20
+
21
+ describe '.[]' do
22
+ it 'flattens the nodes' do
23
+ set = NodeSet[[[$document["#lol .a"]]], [[$document["#lol .c"]]]]
24
+
25
+ expect(set[0]).to eq($document["#lol .a"])
26
+ expect(set[1]).to eq($document["#lol .c"])
27
+ end
28
+
29
+ it 'converts the items to DOM' do
30
+ set = NodeSet[`document.getElementById("lol")`]
31
+
32
+ expect(set[0]).to eq($document["#lol"])
33
+ end
34
+ end
35
+
36
+ describe '#filter' do
37
+ it 'filters the set with the given expression' do
38
+ set = $document["lol"].children.filter('.a, .c')
39
+
40
+ expect(set[0]).to eq($document["#lol .a"])
41
+ expect(set[1]).to eq($document["#lol .c"])
42
+ end
43
+ end
44
+ end
@@ -18,6 +18,54 @@ describe Browser::DOM::Node do
18
18
  end
19
19
  end
20
20
 
21
+ describe "#clone" do
22
+ html '<div class="waht"><ul><li>1</li></ul></div>'
23
+
24
+ it 'should clone a DOM node with an object' do
25
+ obj = $document['.waht']
26
+ new_obj = obj.clone
27
+
28
+ expect(obj).not_to eq(new_obj) # Equality is defined as equality of DOM nodes
29
+ expect(obj.at_css('li')).not_to eq(new_obj.at_css('li'))
30
+ end
31
+
32
+ it 'should dup a DOM node with an object' do
33
+ obj = $document['.waht']
34
+ new_obj = obj.dup
35
+
36
+ expect(obj).not_to eq(new_obj) # Equality is defined as equality of DOM nodes
37
+ expect(obj.at_css('li')).not_to eq(new_obj.at_css('li'))
38
+ end
39
+
40
+ it 'should produce an object which adheres to DOM semantics' do
41
+ obj = $document['.waht'].clone
42
+ xobj = obj.clone
43
+ 5.times do
44
+ obj << xobj.clone
45
+ end
46
+ expect(obj.css('li').count).to eq(6)
47
+ end
48
+
49
+ it 'should integrate well with NativeCachedWrapper' do
50
+ obj = $document['.waht'].clone
51
+ native = obj.to_n
52
+ expect(DOM(native).hash).to eq(obj.hash)
53
+ end
54
+ end
55
+
56
+ describe "#document=" do
57
+ html '<iframe id="diframe" src="about:blank"></iframe><div id="ddiv">hah</div>'
58
+
59
+ it 'should detach a DOM node and attach it to a new document' do
60
+ obj = $document['ddiv']
61
+ ifr = $document['diframe']
62
+
63
+ obj.document = ifr.content_document
64
+ expect($document['ddiv']).to eq(nil)
65
+ expect(obj.document).to eq(ifr.content_document)
66
+ end
67
+ end
68
+
21
69
  describe "#document?" do
22
70
  it "should be true for document" do
23
71
  expect($document.document?).to be_truthy
data/spec/dom_spec.rb CHANGED
@@ -11,5 +11,13 @@ describe 'Kernel' do
11
11
  expect($document['.spec'].element?).to be_truthy
12
12
  expect($document['.sock'].element?).to be_truthy
13
13
  end
14
+
15
+ it "appends classes correctly" do
16
+ elem = DOM {
17
+ div.class1.class2(class: "class-3 class-4", classes: %w[class-5 class-6])
18
+ }
19
+
20
+ expect(elem =~ ".class1.class2.class-3.class-4.class-5.class-6").to eq(true)
21
+ end
14
22
  end
15
23
  end
@@ -2,41 +2,44 @@ require 'spec_helper'
2
2
  require 'browser/event_source'
3
3
 
4
4
  describe Browser::EventSource do
5
- async 'creates it' do
5
+ it 'creates it' do
6
+ promise = Browser::Promise.new
6
7
  Browser::EventSource.new '/events' do |es|
7
8
  es.on :open do |e|
8
9
  es.close
9
10
 
10
- async {
11
- expect(e.target).to be_a(Browser::EventSource)
12
- }
11
+ expect(e.target).to be_a(Browser::EventSource)
12
+ promise.resolve
13
13
  end
14
14
  end
15
+ promise.for_rspec
15
16
  end
16
17
 
17
- async 'receives an unnamed event' do
18
+ it 'receives an unnamed event' do
19
+ promise = Browser::Promise.new
18
20
  Browser::EventSource.new '/events' do |es|
19
21
  es.on :message do |e|
20
22
  e.off
21
23
  es.close
22
24
 
23
- async {
24
- expect(e.data).to eq('lol')
25
- }
25
+ expect(e.data).to eq('lol')
26
+ promise.resolve
26
27
  end
27
28
  end
29
+ promise.for_rspec
28
30
  end
29
31
 
30
- async 'receives a named event' do
32
+ it 'receives a named event' do
33
+ promise = Browser::Promise.new
31
34
  Browser::EventSource.new '/events' do |es|
32
35
  es.on :custom do |e|
33
36
  e.off
34
37
  es.close
35
38
 
36
- async {
37
- expect(e.data).to eq('omg')
38
- }
39
+ expect(e.data).to eq('omg')
40
+ promise.resolve
39
41
  end
40
42
  end
43
+ promise.for_rspec
41
44
  end
42
45
  end if Browser::EventSource.supported?
@@ -1,6 +1,7 @@
1
1
  require 'spec_helper'
2
+ require 'browser/event'
2
3
 
3
- describe Browser::DOM::Event do
4
+ describe Browser::Event do
4
5
  html <<-HTML
5
6
  <div id="event-spec">
6
7
  u wot m8
@@ -40,39 +41,46 @@ describe Browser::DOM::Event do
40
41
  expect(count).to eq(2)
41
42
  end
42
43
 
43
- async "passes an event to the handler" do
44
+ it "passes an event to the handler" do
44
45
  elem = $document["event-spec"]
45
46
 
47
+ promise = Browser::Promise.new
48
+
46
49
  elem.on :click do |event|
47
- async {
48
- expect(event).to be_a(Browser::DOM::Event)
49
- }
50
+ expect(event).to be_a(Browser::Event)
51
+ promise.resolve
50
52
  end
51
53
 
52
54
  elem.trigger :click
55
+
56
+ promise.for_rspec
53
57
  end
54
58
 
55
- async "passes additional arguments to the handler" do
59
+ it "passes additional arguments to the handler" do
56
60
  elem = $document["event-spec"]
57
61
 
62
+ promise = Browser::Promise.new
63
+
58
64
  elem.on :bazinga do |event, foo, bar, baz|
59
- async {
60
- expect(foo).to eq(1)
61
- expect(bar).to eq(2)
62
- expect(baz).to eq(3)
63
- }
65
+ expect(foo).to eq(1)
66
+ expect(bar).to eq(2)
67
+ expect(baz).to eq(3)
68
+ promise.resolve
64
69
  end
65
70
 
66
71
  elem.trigger :bazinga, 1, 2, 3
72
+
73
+ promise.for_rspec
67
74
  end
68
75
 
69
- async "works with delegated events" do
76
+ it "works with delegated events" do
70
77
  elem = $document["event-spec"]
71
78
 
79
+ promise = Browser::Promise.new
80
+
72
81
  elem.on :bazinga, 'span.nami' do
73
- async {
74
- expect(true).to be_truthy
75
- }
82
+ expect(true).to be_truthy
83
+ promise.resolve
76
84
  end
77
85
 
78
86
  elem.add_child DOM { span.nami }
@@ -80,6 +88,27 @@ describe Browser::DOM::Event do
80
88
  after 0.01 do
81
89
  elem.first_element_child.trigger :bazinga
82
90
  end
91
+
92
+ promise.for_rspec
93
+ end
94
+ end
95
+
96
+ describe "#one" do
97
+ it "fires once, passes arguments, works with custom events" do
98
+ count = 0
99
+ elem = $document["event-spec"]
100
+
101
+ elem.one :testone do |event, a, b, c|
102
+ count += a + b*c
103
+ end
104
+
105
+ expect(count).to eq(0)
106
+ elem.trigger :testone, 1, 2, 3
107
+ expect(count).to eq(7)
108
+ elem.trigger :testone, 2, 3, 4
109
+ expect(count).to eq(7)
110
+ elem.trigger :testone, 3, 4, 5
111
+ expect(count).to eq(7)
83
112
  end
84
113
  end
85
114