Currently if you require your application with Onyx::HTTP.listen in it, the process hangs, because it starts a server in the main fiber. There should be a spec helper which would change the macros in the way that it does not hang.
require "onyx/http/spec"
require "../src/app.cr"
describe "App" do
it do
response = Onyx::HTTP::Spec.get("/")
response.assert(200, "Hello World!")
end
end
Pseudo implementation
```crystal
# onyx/http/spec.cr
class Onyx::HTTP
macro listen
# Spawn the server instead of running in the main fiber
end
end
class Onyx::HTTP::Spec
@client : ::HTTP::Client
def get(path) : WrappedResponse
wrap_response do
@client.get
end
end
class WrappedResponse
@response : ::HTTP::Client::Response
def assert(status_code : Int, body : String)
@response.status_code.should eq status_code
@response.body.should eq body
end
end
end
```
The main idea is that Onyx::HTTP.listen expands to a server spawned in a different fiber instead of the main thread. Also bring some singleton HTTP::Client wrappers like Onyx::HTTP::Spec.get("/").
To avoid explicitness, a spec server should bind to any free port. Should have default port other than 5000 for testing.
Websockets should be easily testable with the following syntax:
require "onyx/http/spec"
require "../src/app.cr"
describe "App" do
it do
socket = Onyx::HTTP::Spec.ws("/echo")
socket.assert_response("ping", "ping")
end
end
Pseudo implementation
```crystal
class Onyx::HTTP::Spec::WebSocketWrapper
@socket : WebSocket
def assert_response(request : String | Bytes, expected : String | Bytes, wait = 0.005.seconds)
@socket.send(request)
response = nil
if expected.is_a?(String)
@socket.on_message do |message|
response = message
end
else
@socket.on_bytes do |bytes|
response = bytes
end
end
sleep(wait)
response.should eq expected
end
end
```
Currently if you require your application with
Onyx::HTTP.listen
in it, the process hangs, because it starts a server in the main fiber. There should be a spec helper which would change the macros in the way that it does not hang.Pseudo implementation
```crystal # onyx/http/spec.cr class Onyx::HTTP macro listen # Spawn the server instead of running in the main fiber end end class Onyx::HTTP::Spec @client : ::HTTP::Client def get(path) : WrappedResponse wrap_response do @client.get end end class WrappedResponse @response : ::HTTP::Client::Response def assert(status_code : Int, body : String) @response.status_code.should eq status_code @response.body.should eq body end end end ```The main idea is that
Onyx::HTTP.listen
expands to a server spawned in a different fiber instead of the main thread. Also bring some singletonHTTP::Client
wrappers likeOnyx::HTTP::Spec.get("/")
.To avoid explicitness, a spec server should bind to any free port.Should have default port other than 5000 for testing.Websockets should be easily testable with the following syntax:
Pseudo implementation
```crystal class Onyx::HTTP::Spec::WebSocketWrapper @socket : WebSocket def assert_response(request : String | Bytes, expected : String | Bytes, wait = 0.005.seconds) @socket.send(request) response = nil if expected.is_a?(String) @socket.on_message do |message| response = message end else @socket.on_bytes do |bytes| response = bytes end end sleep(wait) response.should eq expected end end ```