Module: Opal::RSpec::AsyncHelpers

Included in:
AsyncExample
Defined in:
opal/opal/rspec/async.rb

Overview

AsyncHelpers is automatically included in all example groups to add support for running specs async. Usually, rspec runners expect all examples to run synchronously, but this is not ideal in the case for Opal where a lot of underlying libraries expect the ability to run code in an asynchronous manner.

This module defines an ClassMethods#async method which can be used instead of it inside an example group, which marks the example as being async. This makes the runner wait for the example to complete.

describe "Some examples" do
  it "normal example" do
    # normal test code
  end

  async "async example" do
    # this will wait until completion before moving on
  end
end

Marking an example as being async is only half the task. Examples will also have an instance #async method defined which is then used to complete the example. Any code run inside this block will run inside the context of the example.

describe "HTTP requests" do
  async "might take a while" do
    HTTP.get("/url/to/get") do |res|
      async { expect(res).to be_ok }
    end
  end
end

As soon as async is run inside the block, the example completes. This means that only 1 async call is allowed. However, you can use async multiple times aslong as it is only called once:

describe "HTTP requests" do
  async "should work" do
    HTTP.get("/users/1").then |res|
      async { expect(res).to be_ok }
    end.fail do
      async { raise "this should not be called" }
    end
  end
end

Here, a promise will either be accepted or rejected, so an async block can be used in each case as only 1 will be called.

Another helper, #delay can also be used to run a block of code after a given time in seconds. This is useful to wait for animations or time restricted operations to occur.

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



83
84
85
# File 'opal/opal/rspec/async.rb', line 83

def self.included(base)
  base.extend ClassMethods
end

Instance Method Details

#async(&block) ⇒ Object

Must be used with Opal::RSpec::AsyncHelpers::ClassMethods#async to finish the async action. If this is not called inside the body then the spec runner will time out or the error might give a false positive as it is not caught inside the current example.

Examples:

Complete expectation after HTTP request

describe "HTTP calls" do
  async "complete eventually" do
    HTTP.get("/some_url") do |response|
      async { expect(response).to be_ok }
    end
  end
end


101
102
103
# File 'opal/opal/rspec/async.rb', line 101

def async(&block)
  @example.continue_async(block)
end

#delay(duration, &block) ⇒ Object

Runs the given block after a given duration. You are still required to use a #async block inside the delayed callback. This helper can be used to simulate IO delays, or just to wait for animations/other behaviour to finish.

The duaration should be given in seconds, i.e. 1 means 1 second, or 0.3 means 300ms. The given block is just run after the time delay.

Examples:

describe "Some interaction" do
  async "takes a while to complete" do
    task = start_long_task!

    delay(1) do
      async { expect(task).to be_completed }
    end
  end
end

Parameters:

  • duration (Integer, Float)

    time in seconds to wait



125
126
127
128
# File 'opal/opal/rspec/async.rb', line 125

def delay(duration, &block)
  `setTimeout(block, duration * 1000)`
  self
end

#run_async(&block) ⇒ Object

Deprecated.

Use #async instead.



133
134
135
# File 'opal/opal/rspec/async.rb', line 133

def run_async(&block)
  async(&block)
end

#set_timeout(*args, &block) ⇒ Object

Deprecated.

Use #delay instead.



140
141
142
# File 'opal/opal/rspec/async.rb', line 140

def set_timeout(*args, &block)
  delay(*args, &block)
end