hyper-spec 1.0.alpha1.8 → 1.0.0.lap28

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 70e0d39ed642bc1a7d8215db2edcc4798d3229f0530d3a6c1a3355c452158630
4
- data.tar.gz: cbc96bac1e4e5378537364bea704afe27afecceab369920c281569622b59cbad
3
+ metadata.gz: 1b567b6e5e1eb4555bcf41ada038f247a2f83c346be6d21593f9777f9b73dfb8
4
+ data.tar.gz: c1691e64e39fad1442c94782f6e3094460b635bce026767b3ece63d757d0a24d
5
5
  SHA512:
6
- metadata.gz: ef7ed137034bf28dfcd5af3a72914ab8aa81734ef53006d0ce6287d767bca067b6417e5c86f699be4460dba3e7ba62b690d370f463690557e164647b604c8070
7
- data.tar.gz: dfbc57840b6ee1560080181e83d8cc391eafe18084613b48facfc7a566df815d4fbab8c29987a895df77bf8219a54323dec85393db1f8bbecb436152969e7a3c
6
+ metadata.gz: eeaa28e71f46802e74d4d2ecaf6405f8a9518e030d371c7397ede62976c66fe309be3a8f3a5b1434c5e56765ad73117e9660618bcc158830d9eb485a7fc157ea
7
+ data.tar.gz: 93fb42f8f0212cd415dddfd17e7d7ee235f1c2fb470edb1957bd8d8c4bf3b04a50f7290c450374fd5edd5c915a3e16848b314e79df13f4945d1a44801c3256a3
data/.gitignore CHANGED
@@ -13,6 +13,7 @@ capybara-*.html
13
13
  **.orig
14
14
  rerun.txt
15
15
  pickle-email-*.html
16
+ Gemfile.lock
16
17
 
17
18
  # TODO Comment out these rules if you are OK with secrets being uploaded to the repo
18
19
  config/initializers/secret_token.rb
@@ -52,7 +53,3 @@ bower.json
52
53
 
53
54
  # ignore Idea files
54
55
  .idea
55
-
56
- # ignore Gemfile.locks https://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/
57
- /spec/test_app/Gemfile.lock
58
- /Gemfile.lock
data/.rubocop.yml ADDED
@@ -0,0 +1,107 @@
1
+ Style/BlockDelimiters:
2
+ EnforcedStyle: line_count_based
3
+ SupportedStyles:
4
+ # The `line_count_based` style enforces braces around single line blocks and
5
+ # do..end around multi-line blocks.
6
+ - line_count_based
7
+ # The `semantic` style enforces braces around functional blocks, where the
8
+ # primary purpose of the block is to return a value and do..end for
9
+ # procedural blocks, where the primary purpose of the block is its
10
+ # side-effects.
11
+ #
12
+ # This looks at the usage of a block's method to determine its type (e.g. is
13
+ # the result of a `map` assigned to a variable or passed to another
14
+ # method) but exceptions are permitted in the `ProceduralMethods`,
15
+ # `FunctionalMethods` and `IgnoredMethods` sections below.
16
+ - semantic
17
+ # The `braces_for_chaining` style enforces braces around single line blocks
18
+ # and do..end around multi-line blocks, except for multi-line blocks whose
19
+ # return value is being chained with another method (in which case braces
20
+ # are enforced).
21
+ - braces_for_chaining
22
+ ProceduralMethods:
23
+ # Methods that are known to be procedural in nature but look functional from
24
+ # their usage, e.g.
25
+ #
26
+ # time = Benchmark.realtime do
27
+ # foo.bar
28
+ # end
29
+ #
30
+ # Here, the return value of the block is discarded but the return value of
31
+ # `Benchmark.realtime` is used.
32
+ - benchmark
33
+ - bm
34
+ - bmbm
35
+ - create
36
+ - each_with_object
37
+ - measure
38
+ - new
39
+ - realtime
40
+ - tap
41
+ - with_object
42
+ FunctionalMethods:
43
+ # Methods that are known to be functional in nature but look procedural from
44
+ # their usage, e.g.
45
+ #
46
+ # let(:foo) { Foo.new }
47
+ #
48
+ # Here, the return value of `Foo.new` is used to define a `foo` helper but
49
+ # doesn't appear to be used from the return value of `let`.
50
+ - let
51
+ - let!
52
+ - subject
53
+ - watch
54
+ IgnoredMethods:
55
+ # Methods that can be either procedural or functional and cannot be
56
+ # categorised from their usage alone, e.g.
57
+ #
58
+ # foo = lambda do |x|
59
+ # puts "Hello, #{x}"
60
+ # end
61
+ #
62
+ # foo = lambda do |x|
63
+ # x * 100
64
+ # end
65
+ #
66
+ # Here, it is impossible to tell from the return value of `lambda` whether
67
+ # the inner block's return value is significant.
68
+ - lambda
69
+ - proc
70
+ - it
71
+
72
+ Style/Documentation:
73
+ Description: 'Document classes and non-namespace modules.'
74
+ Enabled: false
75
+ Exclude:
76
+ - 'spec/**/*'
77
+ - 'test/**/*'
78
+
79
+ # Multi-line method chaining should be done with trailing dots.
80
+ Style/DotPosition:
81
+ EnforcedStyle: leading
82
+ SupportedStyles:
83
+ - leading
84
+ - trailing
85
+
86
+ Style/FrozenStringLiteralComment:
87
+ Description: >-
88
+ Add the frozen_string_literal comment to the top of files
89
+ to help transition from Ruby 2.3.0 to Ruby 3.0.
90
+ Enabled: false
91
+
92
+ Style/MultilineBlockChain:
93
+ Description: 'Avoid multi-line chains of blocks.'
94
+ StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#single-line-blocks'
95
+ Enabled: false
96
+
97
+ Style/MutableConstant:
98
+ Description: 'Do not assign mutable objects to constants.'
99
+ Enabled: false
100
+
101
+ Metrics/AbcSize:
102
+ # The ABC size is a calculated magnitude, so this number can be a Fixnum or
103
+ # a Float.
104
+ Max: 20
105
+
106
+ Metrics/LineLength:
107
+ Max: 100
data/.travis.yml CHANGED
@@ -1,26 +1,21 @@
1
- dist: trusty
2
1
  language: ruby
3
- cache: bundler
4
2
  rvm:
5
- - 2.4.4
6
- - 2.5.1
7
- - ruby-head
3
+ - ruby
8
4
  env:
9
- - DRIVER=google-chrome TZ=Europe/Berlin
10
- matrix:
11
- fast_finish: true
12
- allow_failures:
13
- - rvm: ruby-head
5
+ - DRIVER=travis HYPER_DEV_GEM_SOURCE="https://gems.ruby-hyperloop.org" TZ=Europe/Berlin
14
6
  before_install:
15
- - if [[ "$DRIVER" == "google-chrome" ]]; then wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -; fi
16
- - if [[ "$DRIVER" == "google-chrome" ]]; then echo "deb http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee /etc/apt/sources.list.d/google-chrome.list; fi
17
- - if [[ "$DRIVER" == "google-chrome" ]]; then sudo apt-get update -qq && sudo apt-get install -qq -y google-chrome-stable; fi
7
+ - sudo apt-get install -y fonts-liberation
8
+ - wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
9
+ - sudo dpkg -i google-chrome*.deb
18
10
  - gem install bundler
19
11
  before_script:
20
- - bundle install --jobs=3 --retry=3
21
- - if [[ "$DRIVER" == "google-chrome" ]]; then bundle exec chromedriver-update; fi
22
- - if [[ "$DRIVER" == "google-chrome" ]]; then ls -lR ~/.chromedriver-helper/; fi
23
- - if [[ "$DRIVER" == "google-chrome" ]]; then bundle exec chromedriver --version; fi
24
- - if [[ "$DRIVER" == "google-chrome" ]]; then google-chrome --version; fi
25
- - if [[ "$DRIVER" == "google-chrome" ]]; then which google-chrome; fi
26
- script: bundle exec rspec
12
+ - cd spec/test_app
13
+ - bundle update
14
+ - cd ../../
15
+ - chromedriver-update
16
+ - ls -lR ~/.chromedriver-helper/
17
+ script:
18
+ - bundle exec rake spec
19
+ gemfile:
20
+ - gemfiles/opal_0_11_react-rails_2_4.gemfile
21
+
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at mitch@catprint.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile CHANGED
@@ -1,7 +1,3 @@
1
1
  source 'https://rubygems.org'
2
- gem 'hyper-component', path: '../hyper-component'
3
- gem 'hyper-store', path: '../hyper-store'
4
- gem 'hyper-state', path: '../hyper-state'
5
- gem 'hyperstack-config', path: '../hyperstack-config'
6
- #gem 'unparser', path: '../../../unparser'
2
+ gem "opal-jquery", git: "https://github.com/opal/opal-jquery.git", branch: "master"
7
3
  gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 catmando
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,380 @@
1
+ # HyperSpec
2
+
3
+ [![Build Status](https://travis-ci.org/ruby-hyperloop/hyper-spec.svg?branch=master)](https://travis-ci.org/ruby-hyperloop/hyper-spec)
4
+
5
+ With HyperSpec you can run *isomorphic* specs for all your Hyperloop code using RSpec. Everything runs as standard RSpec test specs.
6
+
7
+ For example if you have a component like this:
8
+
9
+ ```ruby
10
+ class SayHello < React::Component::Base
11
+ param :name
12
+ render(DIV) do
13
+ "Hello there #{params.name}"
14
+ end
15
+ end
16
+ ```
17
+
18
+ Your test spec would look like this:
19
+
20
+ ```ruby
21
+ describe 'SayHello', js: true do
22
+ it 'has the correct content' do
23
+ mount "SayHello", name: 'Fred'
24
+ expect(page).to have_content('Hello there Fred')
25
+ end
26
+ end
27
+ ```
28
+
29
+ The `mount` method will setup a blank client window, and *mount* the named component in the window, passing any parameters.
30
+
31
+ Notice that the spec will need a client environment so we must set `js: true`.
32
+
33
+ The `mount` method can also take a block which will be recompiled and set to the client before mounting the component. You can place any client side code in the mount block including the definition of components.
34
+
35
+ ```ruby
36
+ describe "the mount's code block", js: true do
37
+ it 'will be recompiled on the client' do
38
+ mount 'ShowOff' do
39
+ class ShowOff < React::Component::Base
40
+ render(DIV) { 'Now how cool is that???' }
41
+ end
42
+ end
43
+ expect(page).to have_content('Now how cool is that???' )
44
+ end
45
+ end
46
+ ```
47
+
48
+ ## Why?
49
+
50
+ Hyperloop wants to make the server-client divide as transparent to the developer as practical. Given this, it makes sense that the testing should also be done with as little concern for client versus server.
51
+
52
+ HyperSpec allows you to directly use tools like FactoryBot (or Hyperloop Operations) to setup some test data, then run a spec to make sure that a component correctly displays, or modifies that data. You can use Timecop to manipulate time and keep in sync between the server and client. This makes testing easier and more realistic without writing a lot of redundant code.
53
+
54
+
55
+ ## Installation
56
+
57
+ Add this line to your application's Gemfile in the test section:
58
+
59
+ ```ruby
60
+ gem 'hyper-spec'
61
+ ```
62
+
63
+ Execute:
64
+
65
+ $ bundle install
66
+
67
+ and then in your spec_helper.rb file
68
+
69
+ ```ruby
70
+ require 'hyper-spec'
71
+ ```
72
+
73
+ You will also need to install selenium, poltergeist and firefox version **46.0.1** (ff latest still does not play well with selenium).
74
+
75
+ Sadly at this time the selenium chrome driver does not play nicely with Opal, so you can't use Chrome. We are working on getting rid of the whole selenium business. Stay tuned.
76
+
77
+ ## Environment Variables
78
+
79
+ You can set `DRIVER` to `ff` to run the client in Firefox and see what is going on. By default tests will run in poltergeist which is quicker, but harder to debug problems.
80
+
81
+ ```
82
+ DRIVER=ff bundle exec rspec
83
+ ```
84
+
85
+ ## Spec Helpers
86
+
87
+ HyperSpec adds the following spec helpers to your test environment
88
+
89
+ + `mount`
90
+ + `client_option` and `client_options`
91
+ + `on_client`
92
+ + `isomorphic`
93
+ + `evaluate_ruby`
94
+ + `expect_evaluate_ruby`
95
+ + `expect_promise`
96
+ + call back and event history methods
97
+ + `pause`
98
+ + `attributes_on_client`
99
+ + `size_window`
100
+ + `add_class`
101
+
102
+ #### The `mount` Method
103
+
104
+ `mount` takes the name of a component, prepares an empty test window, and mounts the named component in the window.
105
+ You may give a block to `mount` which will be recompiled on the client, and run *before* mounting. This means that the component
106
+ mounted may be actually defined in the block, which is useful for setting up top level wrapper components, which will invoke your component under test. You can also modify existing components for white box testing, or local fixture data, constants, etc.
107
+
108
+ `mount` may also be given a hash of the parameters to be passed to the component.
109
+
110
+ ```ruby
111
+ mount 'Display', test: 123 do
112
+ class Display < React::Component::Base
113
+ param :test
114
+ render(DIV) { params.test.to_s }
115
+ end
116
+ end
117
+ ```
118
+
119
+ #### The `client_option` Method
120
+
121
+ There are several options that control the mounting process. Use `client_option` (or `client_options`) before accessing any client side to set any of these options:
122
+
123
+ + `render_on`: `:server_only`, `:client_only`, or `:both`, default is client_only.
124
+ + `layout`: specify the layout to be used. Default is :none.
125
+ + `style_sheet`: specify the name of the style sheet to be loaded. Defaults to the application stylesheet.
126
+ + `javascript`: specify the name of the javascript asset file to be loaded. Defaults to the application js file.
127
+
128
+ For example:
129
+
130
+ ```ruby
131
+ it "can be rendered server side only" do
132
+ client_option render_on: :server_only
133
+ mount 'SayHello', name: 'George'
134
+ expect(page).to have_content('Hello there George')
135
+ # Server only means no code is downloaded to the client
136
+ expect(evaluate_script('typeof React')).to eq('undefined')
137
+ end
138
+ ```
139
+
140
+ If you need to pull in alternative style sheets and javascript files, the recommended way to do this is to
141
+
142
+ 1. Add them to a `specs/assets/stylesheets` and `specs/assets/javascripts` directory and
143
+ 2. Add the following line to your `config/environment/test.rb` file:
144
+ ```ruby
145
+ config.assets.paths << ::Rails.root.join('spec', 'assets', 'stylesheets').to_s
146
+ config.assets.paths << ::Rails.root.join('spec', 'assets', 'javascripts').to_s
147
+ ```
148
+
149
+ This way you will not pollute your application with these 'test only' files.
150
+
151
+ *The javascript spec asset files can be `.rb` files and contain ruby code as well. See the specs for examples!*
152
+
153
+ #### The `on_client` Method
154
+
155
+ `on_client` takes a block and compiles and runs it on the client. This is useful in setting up test constants and client only fixtures.
156
+
157
+ Note that `on_client` needs to *proceed* any calls to `mount`, `evaluate_ruby`, `expect_evaluate_ruby` or `expect_promise` as these methods will initiate the client load process.
158
+
159
+ #### The `isomorphic` Method
160
+
161
+ Similar to `on_client` but the block is *also* run on the server. This is useful for setting constants shared by both client and server, and modifying behavior of isomorphic classes such as ActiveRecord models, and HyperOperations.
162
+
163
+ ```ruby
164
+ isomorphic do
165
+ class SomeModel < ActiveRecord::Base
166
+ def fake_attribute
167
+ 12
168
+ end
169
+ end
170
+ end
171
+ ```
172
+
173
+ #### The `evaluate_ruby` Method
174
+
175
+ Takes either a string or a block, dynamically compiles it, downloads it to the client and runs it.
176
+
177
+ ```ruby
178
+ evaluate_ruby do
179
+ i = 12
180
+ i * 2
181
+ end
182
+ # returns 24
183
+
184
+ isomorphic do
185
+ def factorial(n)
186
+ n == 1 ? 1 : n * factorial(n-1)
187
+ end
188
+ end
189
+
190
+ expect(evaluate_ruby("factorial(5)")).to eq(factorial(5))
191
+ ```
192
+
193
+ `evaluate_ruby` can also be very useful for debug. Set a breakpoint in your test, then use `evaluate_ruby` to interrogate the state of the client.
194
+
195
+ #### The `expect_evaluate_ruby` Method
196
+
197
+ Combines expect and evaluate methods:
198
+
199
+ ```ruby
200
+ expect_evaluate_ruby do
201
+ i = 1
202
+ 5.times { |n| i = i*n }
203
+ i
204
+ end.to eq(120)
205
+ ```
206
+
207
+ #### The `expect_promise` Method
208
+
209
+ Works like `expect_evaluate_ruby` but is used with promises. `expect_promise` will hang until the promise resolves and then return to the results.
210
+
211
+ ```ruby
212
+ expect_promise do
213
+ Promise.new.tap do |p|
214
+ after(2) { p.resolve('hello') }
215
+ end
216
+ end.to eq('hello')
217
+ ```
218
+
219
+ #### Call Back and Event History Methods
220
+
221
+ HyperReact components can *generate* events and perform callbacks. HyperSpec provides methods to test if an event or callback was made.
222
+
223
+ ```ruby
224
+ mount 'CallBackOnEveryThirdClick' do
225
+ class CallBackOnEveryThirdClick < React::Component::Base
226
+ param :click3, type: Proc
227
+ def increment_click
228
+ @clicks ||= 0
229
+ @clicks = (@clicks + 1)
230
+ params.click3(@clicks) if @clicks % 3 == 0
231
+ end
232
+ render do
233
+ DIV(class: :tp_clicker) { "click me" }
234
+ .on(:click) { increment_click }
235
+ end
236
+ end
237
+ end
238
+
239
+ 7.times { page.click('#tp_clicker') }
240
+ expect(callback_history_for(:click3)).to eq([[3], [6]])
241
+ ```
242
+
243
+ Note that for things to work, the param must be declared as a `type: Proc`.
244
+
245
+ + `callback_history_for`: the entire history given as an array of arrays
246
+ + `last_callback_for`: same as `callback_history_for(xxx).last`
247
+ + `clear_callback_history_for`: clears the array (userful for repeating test variations without remounting)
248
+ + `event_history_for, last_event_for, clear_event_history_for`: same but for events.
249
+
250
+ #### The `pause` Method
251
+
252
+ For debugging. Everything stops, until you type `go()` in the client console. Running binding.pry also has this effect, and is often sufficient, however it will also block the server from responding unless you have a multithreaded server.
253
+
254
+ #### The `attributes_on_client` Method
255
+
256
+ *This feature is currently untested - use at your own risk.*
257
+
258
+ This reads the value of active record model attributes on the client.
259
+
260
+ In other words the method `attributes_on_client` is added to all ActiveRecord models. You then take a model you have instance of on the server, and by passing the Capybara page object, you get back the attributes for that same model instance, currently on the client.
261
+
262
+ ```ruby
263
+ expect(some_record_on_server.attributes_on_client(page)[:fred]).to eq(12)
264
+ ```
265
+
266
+ Note that after persisting a record the client and server will be synced so this is mainly useful for debug or in rare cases where it is important to interrogate the value on the client before its persisted.
267
+
268
+ #### The `size_window` Method
269
+
270
+ Sets the size of the test window. You can say:
271
+ `size_window(width, height)` or pass one of the following standard sizes: to one of the following standard sizes:
272
+
273
+ + small: 480 X 320
274
+ + mobile: 640 X 480
275
+ + tablet: 960 X 640
276
+ + large: 1920 X 6000
277
+ + default: 1024 X 768
278
+
279
+ example: `size_window(:mobile)`
280
+
281
+ You can also modify the standard sizes with `:portrait`
282
+
283
+ example: `size_window(:table, :portrait)`
284
+
285
+ You can also specify the size by providing the width and height.
286
+
287
+ example: `size_window(600, 600)`
288
+
289
+ size_window with no parameters is the same as `size_window(:default)`
290
+
291
+ Typically you will use this in a `before(:each)` or `before(:step)` block
292
+
293
+ #### The `add_class` Method
294
+
295
+ Sometimes it's useful to change styles during testing (mainly for debug so that changes on screen are visible.)
296
+
297
+ The `add_class` method takes a class name (as a symbol or string), and hash representing the style.
298
+
299
+ ```ruby
300
+ it "can add classes during testing" do
301
+ add_class :some_class, borderStyle: :solid
302
+ mount 'StyledDiv' do
303
+ class StyledDiv < React::Component::Base
304
+ render(DIV, id: 'hello', class: 'some_class') do
305
+ 'Hello!'
306
+ end
307
+ end
308
+ end
309
+ expect(page.find('#hello').native.css_value('border-right-style')).to eq('solid')
310
+ end
311
+ ```
312
+
313
+ ## Integration with the Steps gem
314
+
315
+ The [rspec-steps gem](https://github.com/LRDesign/rspec-steps) can be useful in doing client side testing. Without rspec-steps, each test spec will cause a reload of the browser window. While this insures that each test runs in a clean environment, it is typically not necessary and can really slow down testing.
316
+
317
+ The rspec-steps gem will run each test without reloading the window, which is usually fine.
318
+
319
+ Checkout the rspec-steps example in the `hyper_spec.rb` file for an example.
320
+
321
+ *Note that hopefully in the near future we are going to build a custom capybara driver that will just directly talk to Hyperloop on the client side. Once this is in place these troubles should go away! - Volunteers welcome to help!*
322
+
323
+ ## Timecop Integration
324
+
325
+ HyperSpec is integrated with [Timecop](https://github.com/travisjeffery/timecop) to freeze, move and speed up time. The client and server times will be kept in sync when you use any these Timecop methods:
326
+
327
+ + `freeze`: Freezes time at the specified point in time (default is Time.now)
328
+ + `travel`: Time runs normally forward from the point specified.
329
+ + `scale`: Like travel but times runs faster.
330
+ + `return`: Return to normal system time.
331
+
332
+ For example:
333
+ ```ruby
334
+ Timecop.freeze # freeze time at current time
335
+ # ... test some stuff
336
+ Timecop.freeze Time.now+10.minutes # move time forward 10 minutes
337
+ # ... check to see if expected events happened etc
338
+ Timecop.return
339
+ ```
340
+
341
+ ```ruby
342
+ Timecop.scale 60, Time.now-1.year do
343
+ # Time will begin 1 year ago but advance 60 times faster than normal
344
+ sleep 10
345
+ # still sleeps for 10 seconds YOUR time, but server and client will
346
+ # think 10 minutes have passed
347
+ end
348
+ # no need for Timecop.return if using the block style
349
+ ```
350
+
351
+ See the Timecop [README](https://github.com/travisjeffery/timecop/blob/master/README.markdown) for more details.
352
+
353
+ There is one confusing thing to note: On the server if you `sleep` then you will sleep for the specified number of seconds when viewed *outside* of the test. However inside the test environment if you look at Time.now, you will see it advancing according to the scale factor. Likewise if you have a `after` or `every` block on the client, you will wait according to *simulated* time.
354
+
355
+ ## Common Problems
356
+
357
+ If you are getting failures on Poltergeist but not Firefox, make sure you are not requiring `browser` in your components.rb.
358
+ Requiring `browser/interval` or `browser/delay` is okay.
359
+
360
+ ## Development
361
+
362
+ After checking out the repo, run bundle install and you should be good to go.
363
+
364
+ Tests are run either by running `rake` or for more control:
365
+
366
+ ```
367
+ DRIVER=ff bundle exec rspec spec/hyper_spec.rb
368
+ ```
369
+
370
+ where DRIVER can be either `ff` (firefox) or `pg` (poltergeist - default).
371
+
372
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
373
+
374
+ ## Contributing
375
+
376
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/hyper-spec. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
377
+
378
+ ## License
379
+
380
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).