envoy / ambassador Goto Github PK
View Code? Open in Web Editor NEWSuper lightweight web framework in Swift based on SWSGI
License: MIT License
Super lightweight web framework in Swift based on SWSGI
License: MIT License
Hi,
As Router
implements WebApp
protocol, I assumed I could nest routers as follows:
let userRouter = Router()
userRouter["/create"] = ...
userRouter["/list"] = ...
let rootRouter = Router()
router["/user"] = userRouter
That doesn't seem to work. Whenever I hit /user
path, the WebApp
assigned to /create
always gets run, regardless of the subpath.
Is this a known limitation? Is there interest in getting contributors implementing this?
Thanks,
Maz
Hi,
is there a way to switch the response data and response code on every request?
I have ui test which should return a 401 status code in the first two requests and in the third request it should return a 200 response. Is there a way to get this working?
Is it possible to get request headers using Ambassador? I can't seem to find them in the environ variable alongside the other information.
I expected to find custom headers or most common ones inside a environ field.
I run a http server for my ui test. In order to check the app's request, I defined a route and tried to read the request body with DataReader
as described.
Everything works fine except reading the body. Most time the body is empty.
The following should demonstrate the problem:
mockServer.router["/test"] = JSONResponse() { requestInfo -> Any in
let bodyStream = requestInfo["swsgi.input"] as! SWSGIInput
DataReader.read(bodyStream) { data in
let text = String(data: data, encoding: .utf8)
print(text)
}
print("return response")
return []
}
var request = URLRequest(url: URL(string: "http://localhost:8080/test")!, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 10)
request.httpMethod = "POST"
request.httpBody = "test value".data(using: .utf8)
URLSession(configuration: URLSessionConfiguration.default).dataTask(with: request).resume()
print("request sent")
Most time the read text is empty and I get the following output:
request sent
return response
Optional("")
Sometimes the text is correct and I get the following output:
request sent
Optional("test value")
return response
As you can see, the data is read after the response was returned here.
Please help me to solve this problem. Without this problem the library would be great.
I think it's also interesting that it works this way, without a router:
server = DefaultHTTPServer(eventLoop: eventLoop, port: 8080) {
(
environ: [String: Any],
startResponse: ((String, [(String, String)]) -> Void),
sendBody: ((Data) -> Void)
) in
// Start HTTP response
let pathInfo = environ["PATH_INFO"]! as! String
let bodyStream = environ["swsgi.input"] as! SWSGIInput
DataReader.read(bodyStream) { data in
let text = String(data: data, encoding: .utf8)
print(text)
}
startResponse("200 OK", [])
}
Do you have an example of running your DefaultHTTPServer asynchronously in the background using Swift 3.0 or greater? I would like to use Ambassador in an XCTest ( i.e. NOT XCUITest) to build a lightweight mock REST server for unit testing an API that I'm building.
Thanks in advance,
Rowland
Using the exact example code, after running the server..the app freezes, but the server is still accessible. Any ideas as to what may be going wrong? If I comment out loop.runForever()
it doesn't happen..but the server doesn't work. using Xcode 9 on iOS 11 Swift 3.
import Embassy
import EnvoyAmbassador
let loop = try! SelectorEventLoop(selector: try! KqueueSelector())
let router = Router()
let server = DefaultHTTPServer(eventLoop: loop, port: 8080, app: router.app)
router["/api/v2/users"] = DelayResponse(JSONResponse(handler: { _ -> Any in
return [
["id": "01", "name": "john"],
["id": "02", "name": "tom"]
]
}))
// Start HTTP server to listen on the port
try! server.start()
// Run event loop
loop.runForever()```
Has anyone seen on occasion that multiple tests to the same endpoint with different responses sometimes causes the test to fail on high memory load?
I ensure that between tests the server is stopped and cleaned up, however, if two tests run one after the other sometimes the previous response is returned. This happens mostly when the machine is under high memory load.
Using a mixture of both DelayResponse and DataResponse to return expected JSON payloads and DataResponses such as 400 Bad Request.
This causes a lot of confusion when installing via pod install
.
Release a new version 4.0.5
that is tagged correctly to a matching podspec.
Instead of providing the JSON format structure after return
, is there a way to point Ambassador to the .json
file located in the project of the app we want to test?
instead of
router["/api/v2/users"] = JSONResponse() { _ -> Any in
return [
["id": "01", "name": "john"],
["id": "02", "name": "tom"]
]
}
something like:
router["/api/v2/users"] = JSONResponse() { _ -> Any in
return [
path/to/file/users.json
]
}
When I ran this code from Router class in Playgrounds always print "matches" for similar endpoints. In my case, Ambassador is returning the same JSON response to both endpoints and I don't know why...Is there a chance that similar endpoints make Ambassador confused? (Sometimes work sometimes don't)
`
let path = "foo/bar/10/xyz"
let searchPath = "foo/bar/10/xyz/asd"
let regex = try! NSRegularExpression(pattern: path, options: [])
let matches = regex.matches(in: searchPath, options: [], range: NSRange(location: 0, length: searchPath.count))
if !matches.isEmpty {
print("match")
} else {
print("no match")
}
`
As readme says to read request data we can use DataRead.read(input) { data in ... }
in request handler. This does not work for me as reading block is called asynchronously after request handler returns, so I can not use it to build data to send back. If I try to wait for this block without exiting handler connections is getting stuck.
What I want to accomplish is to redirect all requests that are not stubbed to real server (because it's just insane to stub every request in the flow when you need to test one particular case on the screen that is deep inside navigation and app needs to make dozen of requests before reaching it). Here is my code:
struct RedirectResponse: WebApp {
// where to redirect
let host: String
let scheme: String
func urlRequest(_ environ: [String: Any]) -> URLRequest {
//reading environment variables and transforming header keys to their initial values....
return request
}
public func app(_ environ: [String : Any], startResponse: @escaping ((String, [(String, String)]) -> Swift.Void), sendBody: @escaping ((Data) -> Swift.Void)) {
var request = urlRequest(environ)
let input = environ["swsgi.input"] as! SWSGIInput
DataReader.read(input) { data in
// this block is called only after method returns, which is too late as request was already fired.
// Waiting for this block to be called before firing request keeps connection stuck and block is never called
request.httpBody = data
}
// makes request and wait for response in synchronous manner, using `group.wait()`
let (data, statusCode, contentType, headers) = URLSession.shared.data(with: request)
//send data from real server back
DataResponse(statusCode: statusCode, statusMessage: "", contentType: contentType, headers: headers, handler: { (_, sendData) in
sendData(data)
}).app(environ, startResponse: startResponse, sendBody: sendBody)
}
}
Then I set this response as notFoundResponse
for the router.
With that I receive such logs:
2017-02-03 13:03:58 +0000 [info] - DefaultHTTPServer: New connection 87A6CC41-5E67-4585-944D-C409FDC9D16A from [::1]:58322
2017-02-03 13:03:58 +0000 [info] - HTTPConnection: [87A6CC41-5E67-4585-944D-C409FDC9D16A] Header parsed, method=Optional("POST"), path="/auth/oauth2/client/access_token", version="HTTP/1.1", headers=[("Host", "localhost:8080"), ("Accept-Encoding", "gzip;q=1.0, compress;q=0.5"), ("mobile-app", "IOS-838"), ("Accept-Language", "en-US;q=1.0, en;q=0.9"), ("Content-Length", "177"), ("Content-Type", "application/json"), ("Accept", "*/*"), ("Connection", "keep-alive"), ("User-Agent", "Alamofire/4.2.0")]
2017-02-03 13:03:58 +0000 [info] - HTTPConnection: [87A6CC41-5E67-4585-944D-C409FDC9D16A] Resume reading
2017-02-03 13:03:58 +0000 [info] - HTTPConnection: [87A6CC41-5E67-4585-944D-C409FDC9D16A] Finish response
2017-02-03 13:03:58 +0000 [info] - HTTPConnection: [87A6CC41-5E67-4585-944D-C409FDC9D16A] Connection closed, reason=byLocal
Request fails as it does not contain required body data.
When trying to wait for read data block:
2017-02-03 13:01:35 +0000 [info] - DefaultHTTPServer: New connection 6DB9C3DF-02E3-49F5-8801-22EB0CE58AF5 from [::1]:58286
2017-02-03 13:01:35 +0000 [info] - HTTPConnection: [6DB9C3DF-02E3-49F5-8801-22EB0CE58AF5] Header parsed, method=Optional("POST"), path="/auth/oauth2/client/access_token", version="HTTP/1.1", headers=[("Host", "localhost:8080"), ("Accept-Encoding", "gzip;q=1.0, compress;q=0.5"), ("mobile-app", "IOS-838"), ("Accept-Language", "en-US;q=1.0, en;q=0.9"), ("Content-Length", "177"), ("Content-Type", "application/json"), ("Accept", "*/*"), ("Connection", "keep-alive"), ("User-Agent", "Alamofire/4.2.0")]
2017-02-03 13:01:35 +0000 [info] - HTTPConnection: [6DB9C3DF-02E3-49F5-8801-22EB0CE58AF5] Resume reading
and then request fails with timeout.
Here is the request that app makes:
curl -i \
-X POST \
-H "mobile-app: IOS-838" \
-H "Content-Type: application/json" \
-H "Accept-Encoding: gzip;q=1.0, compress;q=0.5" \
-H "Accept-Language: en-US;q=1.0, en;q=0.9" \
-H "User-Agent: Alamofire/4.2.0" \
-d "{\"country\":\"us\",\"locale\":\"en-US\",\"grant_type\":\"client_credentials\",\"client_id\":\"...\",\"client_secret\":\"...\",\"scope\":\"public\"}" \
"http://localhost:8080/auth/oauth2/client/access_token"
I noticed that stubbing requests with redirect responses makes server to "hang" with these stubs making it impossible to override this stub with another response. That does not happen for simple responses though. I was able to override it only after I deleted UI tests target from simulator.
Here is how I stub request with redirect (the reset of the code is taken from the blog article):
let response = DataResponse(statusCode: 301, statusMessage: "Moved Permanently", headers: [("Location", "http://www.example.org/")])
router[DefaultRouter.fetchUsersPath] = DelayResponse(response)
Even if I comment out these lines and run the test again I keep receiving redirect response.
Hey guys,
just wondering because I didn't find a doc about this, but what we have a case of doing a mock to different states of the same response.
for example:
/welcome api will return "Hi World" and then on subsequent /welcome needs to be returned like “Hi Globe”
is there a way to play around this that could enable me to mock the response in states
because my issue now is that the UI test just continue without waiting the response to be fully mocked (same response) or it just override everything to the latest mock
Thanks so much guys for your support that I really need because I am stuck in this for quite some time :)
Hey @victorlin,
I am writing UI tests using Envoy/Ambassy. I have a test case that makes a second API call when the first one is successfull. I receive the response data from the Ambassy after the first API call, but it fails to respond for the second API call. It waits for the response forever, and finally the test quits with the UI test timeout.
I am setting up the router for each API path as in the following:
func testUserRegistrationSuccess() {
router[DefaultRouter.fetchActivationPath] = DataResponse(
statusCode: 200,
statusMessage: "created",
contentType: "application/json",
headers: [("Link", app.launchEnvironment["ENVOY_BASEURL"]! + DefaultRouter.fetchConfigApiPath), ("X-SubscriptionID","0000001"), ("X-DeviceAuthorizationToken", "oue97twieurgsljdfh")]
) { (environ, sendData) in
sendData([])
}
router[DefaultRouter.fetchConfigApiPath] = DelayResponse(JSONResponse(
statusCode: 200,
statusMessage: "Configs updated",
contentType: "application/json",
headers: [("X-SubscriptionID","0000002"), ("X-DeviceAuthorizationToken", "oue97twieurgsljdfh")],
handler: { _ in
return ["trip_url" : "return-tripLink", "trip_key" : "return-tripKey", "host_page" : "return-hostPage", "ruleset_uri" : "return-autoStartRulesetURL"]
}), delay: .Delay(seconds: 4) )
app.launch()
// here goes the UI test.
RegistrationHelper.registerSuccessfull(app)
}
This is the output log of the App side :
2016-10-11 16:58:25.560 App[37875:30667532] request authorization succeeded!
2016-10-11 16:58:39.915 App[37875:30667260] AccountActivationRequest, url=http://localhost:8080/activate
2016-10-11 16:58:41.571 App[37875:30667260] AccountActivationRequest - request: http://localhost:8080/activate
2016-10-11 16:58:47.928 App[37875:30667260] AccountActivationRequest - response: <NSHTTPURLResponse: 0x6100004264e0> { URL: http://localhost:8080/activate } { status code: 200, headers {
Connection = close;
"Content-Length" = 0;
"Content-Type" = "application/json";
Link = "http://localhost:8080/configsApi";
Server = Embassy;
"X-DeviceAuthorizationToken" = oue97twieurgsljdfh;
"X-SubscriptionID" = 0000001;
} }
2016-10-11 16:58:47.932 App[37875:30667260] Config Request urlStr=http://localhost:8080/configsApi
and the output of the UI test is as in the following:
t = 92.21s Tap Button
t = 92.21s Wait for app to idle
t = 92.26s Find the Button
t = 92.26s Snapshot accessibility hierarchy for com.mydrivesolutions.mydriveapp.debug
t = 92.50s Find: Descendants matching type Table
t = 92.50s Find: Descendants matching type Cell
t = 92.51s Find: Element at index 5
t = 92.51s Find: Children matching type Button
t = 92.51s Wait for app to idle
t = 92.56s Synthesize event
t = 92.81s Wait for app to idle
t = 106.25s Tap "OK" Button
t = 106.25s Wait for app to idle
t = 108.22s Find the "OK" Button
t = 108.22s Snapshot accessibility hierarchy for com.mydrivesolutions.mydriveapp.debug
t = 112.42s Find: Descendants matching type Button
t = 127.80s Assertion Failure: <unknown>:0: UI Testing Failure - Failure fetching attributes for element <XCAccessibilityElement: 0x61800045ca40> Device element: Error Domain=XCTestManagerErrorDomain Code=13 "Error copying attributes -25204" UserInfo={NSLocalizedDescription=Error copying attributes -25204}
t = 127.80s Assertion Failure: RegistrationHelper.swift:97: UI Testing Failure - Failed to get attributes within 15.0s: (
3003
)
t = 127.80s Tear Down
t = 127.80s Terminate <XCUIApplicationProcess: 0x6000000b08c0 com.test.testapp.debug (54231)>
Test Case '-[mainUITests.MyUITests testUserRegistrationSuccess]' failed (127.840 seconds).
Test Suite 'MyUITests' failed at 2016-10-12 10:34:10.745.
Executed 1 test, with 2 failures (0 unexpected) in 127.840 (127.843) seconds
Test Suite 'mainUITests.xctest' failed at 2016-10-12 10:34:10.745.
Executed 1 test, with 2 failures (0 unexpected) in 127.840 (127.843) seconds
Test Suite 'Selected tests' failed at 2016-10-12 10:34:10.746.
Executed 1 test, with 2 failures (0 unexpected) in 127.840 (127.845) seconds
2016-10-12 10:34:11.043 XCTRunner[54203:31284087] no more background tasks running
I am using the UITestBase
class, which you have posted in the article about how to use EnvoyAmbassador and Embassy, at https://envoy.engineering/embedded-web-server-for-ios-ui-testing-8ff3cef513df#.9vlx7so14
What would be the best approach to mock two consecutive API calls using Ambassy?
I am able to connect to the local server on port 8080, but it does not respond to requests. Here is what it looks like when I curl:
I used the code from your medium post to setup and tear down the local server:
`private extension UITests {
func startHTTPServer() {
self.eventLoop = try! SelectorEventLoop(selector: try! KqueueSelector())
self.router = DefaultRouter()
self.server = HTTPServer(eventLoop: self.eventLoop, app: self.router.app, port: self.port)
try! self.server.start()
self.eventLoopThreadCondition = NSCondition()
self.eventLoopThread = NSThread(target: self, selector: #selector(self.runEventLoop), object: nil)
self.eventLoopThread.start()
}
func stopHTTPServer() {
self.server.stopAndWait()
self.eventLoopThreadCondition.lock()
self.eventLoop.stop()
while self.eventLoop.running {
if !self.eventLoopThreadCondition.waitUntilDate(NSDate().dateByAddingTimeInterval(10)) {
fatalError("Join eventLoopThread timeout")
}
}
}
@objc func runEventLoop() {
self.eventLoop.runForever()
self.eventLoopThreadCondition.lock()
self.eventLoopThreadCondition.signal()
self.eventLoopThreadCondition.unlock()
}
}`
Let me know if you have any questions that I can answer.
Hey @victorlin ,
We have started some work with Xcode UI test framework and interested in exploring this library to support mocking for our network calls during test execution.I went through the details on Github page of Embassy and Ambassador and their integration for XCUI* APIs seems seamless.Could you provide some details on the current support status of the framework and plan for maintaining this framework in future? Are there any areas of improvement where you are looking for any contribution (e.g Swift 2.3 support, Carthage )?
Thanks,
Sushant
Can you publish a new release for Embassy. It has fixes for target not found
issue in SPM but there is no release for the fix.
Possible bug in Router, we have an api with two very similar paths /api/GetDevices and /api/GetDevice, while trying to ui test in iOS after setting up a response for each endpoint some times we're getting GetDevice's response for a call to GetDevices which makes the tests crash as the response is different and cannot be parsed by our app. I think the problem is in the matcher that sometimes is mixing responses in case of similar routes like ours.
First of all, thanks for the help you already gave me, it really helped me a lot. But I have another one.
I wonder if it possible to completely move server to run on background. I know that we move an event loop to run on a different thread, than the testrunner, but the thing is when, for example, I want to have a breakpoint inside a test, the server itself does also stop responding. Also I noticed, that the testrunner thread is too busy doing queries and other stuff leaving the server too little bandwidth, so I see the response time is increasing to the great extent. If that's not possible, I wonder if we can somehow prioritize server over the testrunner stuff.
Aloha Envoy team!
The cocoapods version is still a tiny bit behind, it doesn't include @fangpenlin's PR #28.
Since my project uses cocoapods I still get a warning during builds (that's the only one, so kinda prominent).
I had actually already forked the repo and wanted to fix the deprecated call to characters
, I was really confused when master already had the latest Swift syntax. 😸
Maybe one of you can quickly do a tag, version bump etc. and push to the cocoapods spec repo?
Thanks a lot, your Embassy & Ambassador have really helped me a lot in testing (and since it's all swift I can keep my repo nice and clean!).
Can someone give an example of how to handle POST requests where we are uploading files/photos (multipart/form-data).
I tried to use DataReader(input)
snippet but that always gives me an empty data back. Does environ need to have another key set ? Looking at python's uwsgi definitions, they advise to use cgi.FieldStorage.
d = cgi.FieldStorage(environ=environ, fp=environ['wsgi.input'], keep_blank_values=True)
Could you provide an example of how do we handle this case ?
DataReader.read(input) { d in print(d) }
In this case, when using
curl -v -X POST -F '[email protected]' http://localhost:8080/image
, the d
variable declared above is nil.
I'm trying to get the query string arguments from an URL similar to: /v2/users?direction=past&limit=20
. Is there a way to get those parameters and their values inside a router to form response based on those parameters? I did try to use URLParametersReader, but it returns an empty object every time.
When trying to get all the data from response body with DataReader it works fine when receiving small amount of data, but when trying to get a bigger body response, it doesn’t return the whole data, but only a part of it. I could fix it by increasing recvChunkSize to the size bigger that I was trying to read. But seems like the problem is in chunking itself, but I wasn’t able to debug it more deeply.
Has anyone encountered this kind of problem?
I have the following test in my XCTestCase
, which should demonstrate the problem.
let mockServer = MockServer()
mockServer.start()
mockServer.router["/test"] = JSONResponse() { _ -> NSDictionary in
print("request received")
return [:]
}
print("Send request")
URLSession(configuration: URLSessionConfiguration.default)
.dataTask(with: URL(string: "http://localhost:8080/test")!)
.resume()
sleep(3) // Any action or tear down delay.
print("stop mock server")
mockServer.stop() // Never ends
print("mock server stopped")
MockServer
is a wrapper I have made, which handles starting and stopping the server.
I followed your gist about running the server.
class MockServer {
let router = Router()
private let server: HTTPServer
private let serverDispatchQueue = DispatchQueue(label: "com.timr.uitest.serverDispatchQueue", qos: .background)
private let eventLoop: EventLoop
private var eventLoopThreadCondition = NSCondition()
init() {
eventLoop = try! SelectorEventLoop(selector: try! KqueueSelector())
server = DefaultHTTPServer(
eventLoop: eventLoop,
port: 8080,
app: router.app
)
}
func start() {
try! server.start()
eventLoopThreadCondition = NSCondition()
serverDispatchQueue.async() {
self.eventLoop.runForever()
self.eventLoopThreadCondition.lock()
self.eventLoopThreadCondition.signal()
self.eventLoopThreadCondition.unlock()
}
}
func stop() {
server.stopAndWait()
eventLoopThreadCondition.lock()
eventLoop.stop()
let stopEventLoopTimeout = 10.0
while eventLoop.running {
if !eventLoopThreadCondition.wait(until: Date(timeIntervalSinceNow: stopEventLoopTimeout)) {
fatalError("Join eventLoopThread timeout")
}
}
}
}
The problem is that the test never ends because it gets stuck at server.stopAndWait()
.
I get this output:
Send request
request received
stop mock server
As I digged a bit deeper I found out that the last event loop round does not finish. So the action awaited in stopAndWait
, which is passed to eventLoop.call
never gets called.
runOnce
in EventLoop
gets stuck at events = try selector.select(timeout: timeout)
.
Would be great if you could take a look on this issue @fangpenlin. This problem is a bit too deep for me.
Getting the following error:
Thread 1: Fatal error: self must be a properly aligned pointer for types Pointee and T
in TCPSocket
pointing to withMemoryRebound
:
func bind(port: Int, interface: String = "::", addressReusable: Bool = true) throws {
// make address reusable
if addressReusable {
var reuse = Int32(1)
guard setsockopt(
fileDescriptor,
SOL_SOCKET,
SO_REUSEADDR,
&reuse,
socklen_t(MemoryLayout<Int32>.size)
) >= 0 else {
throw OSError.lastIOError()
}
}
// create IPv6 socket address
var address = sockaddr_in6()
#if !os(Linux)
address.sin6_len = UInt8(MemoryLayout<sockaddr_in6>.stride)
#endif
address.sin6_family = sa_family_t(AF_INET6)
address.sin6_port = UInt16(port).bigEndian
address.sin6_flowinfo = 0
address.sin6_addr = try ipAddressToStruct(address: interface)
address.sin6_scope_id = 0
let size = socklen_t(MemoryLayout<sockaddr_in6>.size)
// bind the address and port on socket
guard withUnsafePointer(to: &address, { pointer in
return pointer.withMemoryRebound(to: sockaddr.self, capacity: Int(size)) { pointer in
return SystemLibrary.bind(fileDescriptor, pointer, size) >= 0
}
}) else {
throw OSError.lastIOError()
}
}
Adding some related context:
https://forums.swift.org/t/on-properly-aligned-pointer-for-types-pointee-and-t/61325/4
Cheers
I'm using EnvoyAmbassador in unit tests to mock my API server. In order to validate the JSON body that the software under test sends, I'm using DataReader.read(input) like below. This works fine most of the time, but sometimes it fails. When it does fail, it looks like there's no data read by the DataReader(input) method. In the case below, the buffer
has length 0.
Give the sporadic nature of the error, it feels like it might be a race condition? Any clues as to why this might fail once in a while?
if let input = environ["swsgi.input"] as? SWSGIInput {
let buffer = NSMutableData()
DataReader.read(input) { data in
for var d in data { // data is list of UInt8
buffer.appendData(NSData(bytes: &d, length: sizeof(UInt8)))
}
}
swiftyJson = JSON(data: buffer)
if (buffer.length == 0) {
XCTFail("Found zero length buffer parsing JSON")
}
The DelayResponse class is not included in the Mac target. I built my local copy with the class included without issue.
Ambassador is a great project - I've been using it for testing and I love it.
Is it possible to serve JSON directly from a file, similar to how json-server works?
When I'm trying to run some UI tests on parallel with a local server on every simulator, those servers are responding very slowly, sometimes response time can be 2-3 seconds, sometimes even more. I'm wondering what can cause such a delay when running tests on parallel, because when running on one simulator, server gives response quickly enough.
Hello guys,
I noticed that when I use delay response in ui test, and in this response I return some value to assert in UI test, delayed response sometimes come after I made assertion.
So, first I mock response with delay like this router["/api/v2/users"] = DelayResponse(JSONResponse(......))
, and after I assert value I got from response file, or assert ui element that I enabled in this mocked response. So this kind of tests are flaky, because depending on delay time, it gives back response after assertion.
Deleting delay response solves this flakiness. But why it happens with DelayResponse?
Hi all, after upgrading to xcode 14 we are getting a error on both M1 rossetta and intel:
Embassy/SelectorEventLoop.swift:88: Fatal error: 'try!' expression unexpectedly raised an error: Embassy.OSError.ioError(number: 9, message: "Bad file descriptor")
This happens after trying to restart (teardown-setup) a local server
testing with multiple iOS versions, testing with other xcode versions later.
Anyone else run into this?
I'm not sure if I have missed the documentation for this but is it possible to run separate instances of DefaultHTTPServer
on the individual clones while parallel testing?
Is there any plans for implementing websocket support? Or is there any available extensions? I googled it and failed to find any neither for Ambassador no for embassy.
Thanks.
Hey Guys,
wondering is there an example how to use DataResponse
with URLParametersReader
I am having an API with parameters and I need to router it with DataResponse
router["someAPI?WithParam1&Param2"]
and I am using the DataResponse()
Your help is so much needed and appreciated!
Hello.
Is there any way to support many states API responses such as:
router["/api/v2/login"] = DelayResponse(JSONStringResponse(handler: { _ -> Any in
return """
{
"acess_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}
"""
}))
router["/api/v2/login"] = DelayResponse(JSONStringResponse(handler: { _ -> Any in
return """
{
"message": "incorrect password"
}
"""
}))
I mean I want to test a feature (login) with many cases as many API responses. Seem to now only one state can setup before a test.
Thank you so much.
Is there someone working on swift 3.0 support ?
I would love to use this library, but would really appreciate a working example in swift 4 of ui testing / unit testing using Ambassador. The current steps listed appear to freeze the app on Xcode 9.
Just curious, is this supposed to call sendBody
with an empty Data
? I don't see any comments around it why it would do that.
https://github.com/envoy/Ambassador/blob/master/Ambassador/Responses/DataResponse.swift#L81
if !data.isEmpty {
sendBody(data)
}
--> sendBody(Data())
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.