Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

adds 'BW::NetworkIndicator' #349

Merged
merged 9 commits into from

3 participants

@colinta
Owner

Regarding #263 and #171, I agree w/ @clayallsopp that UIApplication.sharedApplication.networkActivityIndicatorVisible should be controlled by a centralized module.

I didn't call it BW::HTTP::NetworkIndicator, because I think it could be used as a standalone module (maybe they're not using BW::HTTP).

methods available:

  • BW::NetworkIndicator.show
  • BW::NetworkIndicator.hide
  • BW::NetworkIndicator.visible?
  • BW::NetworkIndicator.reset!

Specs included.

@clayallsopp
Owner

Sweet, and I think it would also make a lot of sense to integrate with BW::HTTP

In this case, thread safety is a realistic consideration - did you check out @bogardon's implementation or other iOS network indicator implementations? (SDNetworkActivityIndicator, AFNetworkingActivityIndicatorManager, etc)

Also the tests failed on Travis?

@colinta
Owner

Ah, those failures are from the HTTP integration actually. I'll check it out.

I'll see what needs to be done about thread safety, too. Thanks Clay!

@clayallsopp
Owner

Ah gotcha. Yeah, I think the networking indicator should be included by default w/ bubble-wrap/http (https://github.com/rubymotion/BubbleWrap/blob/master/lib/bubble-wrap/http.rb), instead of making the remember to require it manually

@colinta
Owner

Man, turns out all the queries that get created in query_spec kind of throw a wrench in things; they all have to be properly cancel-ed at the end of each test, otherwise the indicator 'counter' is thrown off.

I've added a warning message to query_spec.rb that should detect if a query wasn't canceled, and ask the dev to fix the spec.

@colinta
Owner

Dang it. Specs pass locally, I'll see what's up.

@markrickert
Owner

@colinta It could be that the iOS version is passing and the mac version is not. See @clayallsopp's recommendation for me that helped the specs pass: #335 (comment)

@colinta
Owner

Yeah i think you're right; getting 'cancel called on nil' when running on osx. thanks for the heads up! :smiley:

@colinta
Owner

I'm still getting a 'failure' on osx, but it's in the NSIndexPathWrap methods.

NSIndexPathWrap
  - should be able to use an array like accessor
 [ERROR: NoMethodError - undefined method `indexAtPosition' for 826:Fixnum]
  - should support the each iterator
 [ERROR: NoMethodError - undefined method `length' for 826:Fixnum]
@colinta
Owner

Strange behavior on my machine, but specs are passing on travis. :-/

@colinta
Owner

Can someone run

rake spec osx=1 files=spec/motion/core/ns_index_path_spec.rb

and see what it says?

@clayallsopp
Owner

This is interesting, and broken for me on master. Adding some logging, I see @index: #<ImmediateRef:0x7fcd4bd07560>, self: 0+826i

Travis runs 10.8, which could be making a difference. Sounds like a rubymotion bug @colinta? I've opened #351 and submitted a motion support ticket (#1668)

that aside, I'm down for merging this if it's okay with you @colinta?

@colinta
Owner

Yeah, the error isn't related to the NetworkIndicator stuff, so makes sense to me! I'll keep tabs on the NSIndexPath stuff.

@clayallsopp clayallsopp merged commit bec9c64 into from
@clayallsopp clayallsopp referenced this pull request from a commit
@clayallsopp clayallsopp 1.6.0.rc1
- 'bubble-wrap/http' is now deprecated and will be removed in 2.0, see #308

+ `BW::UIActivityViewController` wrapper added, see #335

+ `BW::NetworkIndicator` added, see #349

 + `BW::Location.get_compass` & `BW::Location.get_compass_once`see #348

+ `NSString#to_color` ARGB support, see #350

+ `Object#method` support for `BW::Reactor`, see #359

* Prevented a possible exception when stopping `BW::Location`, see #358

* Fixed a bug when requiring just 'bubble-wrap/ui'
239f91c
@colinta colinta deleted the branch
@tutuming tutuming referenced this pull request from a commit in tutuming/BubbleWrap
@clayallsopp clayallsopp 1.6.0.rc1
- 'bubble-wrap/http' is now deprecated and will be removed in 2.0, see rubymotion#308

+ `BW::UIActivityViewController` wrapper added, see rubymotion#335

+ `BW::NetworkIndicator` added, see rubymotion#349

 + `BW::Location.get_compass` & `BW::Location.get_compass_once`see rubymotion#348

+ `NSString#to_color` ARGB support, see rubymotion#350

+ `Object#method` support for `BW::Reactor`, see rubymotion#359

* Prevented a possible exception when stopping `BW::Location`, see rubymotion#358

* Fixed a bug when requiring just 'bubble-wrap/ui'
7ad7c1a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 6, 2014
  1. @colinta
  2. @colinta

    updated README

    colinta authored
  3. @colinta

    don't need this block

    colinta authored
Commits on Mar 7, 2014
  1. @colinta

    models the spinner behavior after AFNetworking; hiding the spinner is…

    colinta authored
    … delayed (avoids flickering), thread support (all updates are on the main thread)
  2. @colinta
  3. @colinta

    only alloy one 'error'

    colinta authored
  4. @colinta
  5. @colinta
  6. @colinta

    fixes for osx

    colinta authored
This page is out of date. Refresh to see the latest.
View
37 README.md
@@ -93,6 +93,12 @@ If you wish to only include the `SMS` wrapper:
require 'bubble-wrap/sms'
```
+If you wish to only include the `NetworkIndicator` wrapper:
+
+```ruby
+require 'bubble-wrap/network-indicator'
+```
+
If you want to include everything (ie kitchen sink mode) you can save time and do:
```ruby
@@ -452,7 +458,36 @@ Wrapper for showing an in-app message (SMS) composer view.
result.canceled? # => boolean
result.failed? # => boolean
error # => NSError
- }
+ }
+```
+
+## NetworkIndicator
+
+Wrapper for showing and hiding the network indicator (the status bar spinner).
+
+```ruby
+ BW::NetworkIndicator.show # starts the spinner
+ BW::NetworkIndicator.hide # stops it
+
+ # the nice thing is if you call 'show' multiple times, the 'hide' method will
+ # not have any effect until you've called it the same number of times.
+ BW::NetworkIndicator.show
+ # ...somewhere else
+ BW::NetworkIndicator.show
+
+ # ...down the line
+ BW::NetworkIndicator.hide
+ # indicator is still visible
+
+ BW::NetworkIndicator.hide
+ # NOW the indicator is hidden!
+
+ # If you *really* want to hide the indicator immediately, you can call `reset!`
+ # but this is in no way encouraged.
+ BW::NetworkIndicator.reset!
+
+ # and for completeness, a check to see if the indicator is visible
+ BW::NetworkIndicator.visible?
```
## UI
View
2  Rakefile
@@ -28,7 +28,7 @@ Motion::Project::App.setup do |app|
app.spec_files
if Motion::Project::App.osx?
app.spec_files -= Dir.glob("./spec/motion/**/ios/**.rb")
- ["font", "location", "media", "ui", "mail", "sms"].each do |package|
+ ["font", "location", "media", "ui", "mail", "sms", "network-indicator"].each do |package|
app.spec_files -= Dir.glob("./spec/motion/#{package}/**/*.rb")
end
else
View
2  lib/bubble-wrap/all.rb
@@ -1,4 +1,4 @@
require File.expand_path('../loader', __FILE__)
-['core', 'http', 'reactor', 'rss_parser', 'ui', 'location', 'media', 'font', 'mail','sms'].each { |sub|
+['core', 'http', 'reactor', 'rss_parser', 'ui', 'location', 'media', 'font', 'mail','sms', 'network-indicator'].each { |sub|
require File.expand_path("../#{sub}", __FILE__)
}
View
1  lib/bubble-wrap/http.rb
@@ -1,5 +1,6 @@
require 'bubble-wrap/version' unless defined?(BubbleWrap::VERSION)
require 'bubble-wrap/loader'
+require 'bubble-wrap/network-indicator'
BubbleWrap.require('motion/core/ns_url_request.rb')
BubbleWrap.require('motion/core.rb')
BubbleWrap.require('motion/http.rb')
View
6 lib/bubble-wrap/network-indicator.rb
@@ -0,0 +1,6 @@
+require 'bubble-wrap/loader'
+
+BubbleWrap.require_ios("network-indicator") do
+ BubbleWrap.require('motion/core/app.rb')
+ BubbleWrap.require('motion/network-indicator/**/*.rb')
+end
View
33 motion/http/query.rb
@@ -69,6 +69,10 @@ def to_s
end
alias description to_s
+ def done?
+ @did_fail_error || @did_finish_loading || @canceled
+ end
+
def connection(connection, didReceiveResponse:response)
# On OSX, if using an FTP connection, this method will fire *immediately* after creating an
# NSURLConnection, even if the connection has not yet started. The `response`
@@ -99,13 +103,10 @@ def connection(connection, willSendRequest:request, redirectResponse:redirect_re
log "##{@redirect_count} HTTP redirect_count: #{request.inspect} - #{self.description}"
if @redirect_count >= 30
- @response.error = NSError.errorWithDomain('BubbleWrap::HTTP', code:NSURLErrorHTTPTooManyRedirects,
+ error = NSError.errorWithDomain('BubbleWrap::HTTP', code:NSURLErrorHTTPTooManyRedirects,
userInfo:NSDictionary.dictionaryWithObject("Too many redirections",
forKey: NSLocalizedDescriptionKey))
- @response.error_message = @response.error.localizedDescription
- show_status_indicator false
- @request.done_loading!
- call_delegator_with_response
+ self.connection(connection, didFailWithError: error)
nil
else
@url = request.URL if @follow_urls
@@ -114,6 +115,9 @@ def connection(connection, willSendRequest:request, redirectResponse:redirect_re
end
def connection(connection, didFailWithError: error)
+ return if done?
+
+ @did_fail_error = error
log "HTTP Connection to #{@url.absoluteString} failed #{error.localizedDescription}"
show_status_indicator false
@request.done_loading!
@@ -129,6 +133,9 @@ def connection(connection, didSendBodyData:sending, totalBytesWritten:written, t
end
def connectionDidFinishLoading(connection)
+ return if done?
+ @did_finish_loading = true
+
show_status_indicator false
@request.done_loading!
response_body = NSData.dataWithData(@received_data) if @received_data
@@ -156,6 +163,9 @@ def connection(connection, didReceiveAuthenticationChallenge:challenge)
end
def cancel
+ return if done?
+ @canceled = true
+
@connection.cancel
show_status_indicator false
@request.done_loading!
@@ -170,8 +180,13 @@ def did_receive_response(response)
end
def show_status_indicator(show)
- if App.ios?
- UIApplication.sharedApplication.networkActivityIndicatorVisible = show
+ if App.ios? && (@status.nil? || @status != !!show)
+ @status = !!show
+ if show
+ BW::NetworkIndicator.show
+ else
+ BW::NetworkIndicator.hide
+ end
end
end
@@ -276,8 +291,8 @@ def append_auth_header
def parse_file(key, value)
value = {data: value} unless value.is_a?(Hash)
raise(InvalidFileError, "You need to supply a `:data` entry in #{value} for file '#{key}' in your HTTP `:files`") if value[:data].nil?
- {
- data: value[:data],
+ {
+ data: value[:data],
filename: value.fetch(:filename, key),
content_type: value.fetch(:content_type, "application/octet-stream")
}
View
67 motion/network-indicator/network-indicator.rb
@@ -0,0 +1,67 @@
+module BubbleWrap
+ module NetworkIndicator
+ DELAY = 0.2
+
+ module_function
+
+ def counter
+ @counter ||= 0
+ end
+
+ def show
+ if Dispatch::Queue.current.to_s == 'com.apple.main-thread'
+ @counter = self.counter + 1
+ self.update_spinner
+ else
+ Dispatch::Queue.main.async do
+ self.show
+ end
+ end
+ end
+
+ def hide
+ if Dispatch::Queue.current.to_s == 'com.apple.main-thread'
+ @counter = [self.counter - 1, 0].max
+ if self.counter == 0
+ if @hide_indicator_timer
+ @hide_indicator_timer.invalidate
+ end
+ @hide_indicator_timer = NSTimer.timerWithTimeInterval(DELAY - 0.01, target: self, selector: :update_spinner_timer, userInfo: nil, repeats: false)
+ NSRunLoop.mainRunLoop.addTimer(@hide_indicator_timer, forMode:NSRunLoopCommonModes)
+ end
+ else
+ Dispatch::Queue.main.async do
+ self.hide
+ end
+ end
+ end
+
+ def update_spinner_timer
+ update_spinner
+ end
+
+ def update_spinner
+ if Dispatch::Queue.current.to_s == 'com.apple.main-thread'
+ if @hide_indicator_timer
+ @hide_indicator_timer.invalidate
+ @hide_indicator_timer = nil
+ end
+ UIApplication.sharedApplication.networkActivityIndicatorVisible = (@counter > 0)
+ else
+ Dispatch::Queue.main.async do
+ self.update_spinner
+ end
+ end
+ end
+
+ def visible?
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?
+ end
+
+ def reset!
+ @counter = 0
+ self.update_spinner
+ end
+
+ end
+end
View
92 spec/motion/http/query_spec.rb
@@ -11,6 +11,10 @@
@json_query = BubbleWrap::HTTP::Query.new( "http://localhost:3000" , :post, @json_options )
end
+ after do
+ @json_query.cancel
+ end
+
it "should generate json body" do
BW::JSON.parse(@json_query.request.HTTPBody).should == @json_payload
end
@@ -21,6 +25,10 @@
@query = BubbleWrap::HTTP::Query.new("http://www.google.com", :get, {payload: {following: false}})
end
+ after do
+ @query.cancel
+ end
+
it "should have right url" do
@query.request.URL.absoluteString.should == "http://www.google.com?following=false"
end
@@ -59,9 +67,14 @@
leftover_option: @leftover_option,
format: @format
}
+
@query = BubbleWrap::HTTP::Query.new( @localhost_url , :get, @options )
end
+ after do
+ @query.cancel
+ end
+
it "has appropriate attributes" do
@query.should.respond_to :request=
@query.should.respond_to :connection=
@@ -84,6 +97,7 @@
}
query = BubbleWrap::HTTP::Query.new( @localhost_url , :get, @options )
query.should.not.be.nil
+ query.cancel
end
describe "When initialized" do
@@ -95,7 +109,8 @@
it "throws an error for invalid/missing URL schemes" do
%w(http https file ftp).each do |scheme|
lambda {
- BW::HTTP::Query.new("#{scheme}://example.com", :get) { |r| p r.body.to_str }
+ q = BW::HTTP::Query.new("#{scheme}://example.com", :get) { |r| p r.body.to_str }
+ q.cancel
}.should.not.raise InvalidURLError
end
@@ -122,6 +137,7 @@
it "should set self as the delegator if action was not passed in" do
new_query = BubbleWrap::HTTP::Query.new( 'http://localhost', :get, {})
new_query.instance_variable_get(:@delegator).should.equal new_query
+ new_query.cancel
end
it "should merge :username and :password in loaded credentials" do
@@ -129,6 +145,7 @@
options = { credentials: {} }
new_query = BubbleWrap::HTTP::Query.new( @localhost_url, :get, options)
+ new_query.cancel
generated_credentials = { :username => nil, :password => nil }
new_query.credentials.should.equal generated_credentials
@@ -155,11 +172,13 @@ def sample_data
it "should check if @payload is a hash before generating GET params" do
query_string_payload = BubbleWrap::HTTP::Query.new( @fake_url , :get, { payload: "name=apple&model=macbook"} )
query_string_payload.instance_variable_get(:@payload).should.equal 'name=apple&model=macbook'
+ query_string_payload.cancel
end
it "should check if payload is nil" do
lambda{
- BubbleWrap::HTTP::Query.new( @fake_url , :post, {} )
+ q = BubbleWrap::HTTP::Query.new( @fake_url , :post, {} )
+ q.cancel
}.should.not.raise NoMethodError
end
@@ -167,12 +186,14 @@ def sample_data
[:post, :put, :delete, :patch].each do |method|
query = BubbleWrap::HTTP::Query.new( @localhost_url , method, { payload: @payload } )
query.instance_variable_get(:@url).description.should.equal @localhost_url
+ query.cancel
end
payload = {name: 'marin'}
[:get, :head, :options].each do |method|
query = BubbleWrap::HTTP::Query.new( @localhost_url , method, { payload: payload } )
query.instance_variable_get(:@url).description.should.equal "#{@localhost_url}?name=marin"
+ query.cancel
end
end
@@ -184,6 +205,7 @@ def sample_data
uuid = query.instance_variable_get(:@boundary)
real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
real_payload.should.equal "--#{uuid}\r\nContent-Disposition: attachment; name=\"upload\"; filename=\"test.txt\"\r\nContent-Type: application/octet-stream\r\n\r\ntwitter:@mneorr\r\n--#{uuid}--\r\n"
+ query.cancel
end
it "processes filenames from file hashes, using the name when the filename is missing" do
@@ -194,6 +216,7 @@ def sample_data
uuid = query.instance_variable_get(:@boundary)
real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
real_payload.should.equal "--#{uuid}\r\nContent-Disposition: attachment; name=\"upload\"; filename=\"upload\"\r\nContent-Type: application/octet-stream\r\n\r\ntwitter:@mneorr\r\n--#{uuid}--\r\n"
+ query.cancel
end
it "throws an error for invalid file parameters" do
@@ -215,6 +238,7 @@ def sample_data
uuid = query.instance_variable_get(:@boundary)
real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
real_payload.should.equal "--#{uuid}\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\napple\r\n--#{uuid}\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nmacbook\r\n--#{uuid}\r\nContent-Disposition: attachment; name=\"twitter\"; filename=\"twitter\"\r\nContent-Type: application/octet-stream\r\n\r\ntwitter:@mneorr\r\n--#{uuid}\r\nContent-Disposition: attachment; name=\"site\"; filename=\"site\"\r\nContent-Type: application/octet-stream\r\n\r\nmneorr.com\r\n--#{uuid}--\r\n"
+ query.cancel
end
[:get, :head, :options].each do |method|
@@ -222,12 +246,16 @@ def sample_data
query = BubbleWrap::HTTP::Query.new( @fake_url , method, { payload: payload } )
real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
real_payload.should.be.empty
+ query.cancel
end
end
it "sets the payload without conversion to-from NSString if the payload was NSData" do
data = sample_data
- lambda { create_query(data, nil) }.should.not.raise NoMethodError
+ lambda {
+ q = create_query(data, nil)
+ q.cancel
+ }.should.not.raise NoMethodError
end
it "sets the payload as a string if JSON" do
@@ -237,6 +265,7 @@ def sample_data
query = BubbleWrap::HTTP::Query.new( @fake_url , method, { payload: json } )
set_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
set_payload.should.equal json
+ query.cancel
end
end
@@ -246,6 +275,7 @@ def sample_data
uuid = query.instance_variable_get(:@boundary)
real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:NSUTF8StringEncoding)
real_payload.should.equal "--#{uuid}\r\nContent-Disposition: form-data; name=\"computer[name]\"\r\n\r\napple\r\n--#{uuid}\r\nContent-Disposition: form-data; name=\"computer[model]\"\r\n\r\nmacbook\r\n--#{uuid}--\r\n"
+ query.cancel
end
[["NSUTF8StringEncoding", NSUTF8StringEncoding],
@@ -258,6 +288,7 @@ def sample_data
uuid = query.instance_variable_get(:@boundary)
real_payload = NSString.alloc.initWithData(query.request.HTTPBody, encoding:encoding)
real_payload.should.equal "--#{uuid}\r\nContent-Disposition: form-data; name=\"computer[name]\"\r\n\r\n#{payload[:computer][:name]}\r\n--#{uuid}\r\nContent-Disposition: form-data; name=\"computer[model]\"\r\n\r\n#{payload[:computer][:model]}\r\n--#{uuid}--\r\n"
+ query.cancel
end
end
@@ -271,6 +302,7 @@ def sample_data
new_query.instance_variable_get(:@timeout).should == 10
options.should.be.empty
+ new_query.cancel
end
it "should delete :headers from options and escape Line Feeds" do
@@ -286,6 +318,7 @@ def sample_data
new_query = BubbleWrap::HTTP::Query.new( @localhost_url, :get, {})
new_query.instance_variable_get(:@cache_policy).should.equal NSURLRequestUseProtocolCachePolicy
+ new_query.cancel
end
it "should delete :credential_persistence or set NSURLCredentialPersistenceForSession" do
@@ -294,6 +327,7 @@ def sample_data
new_query = BubbleWrap::HTTP::Query.new( @localhost_url, :get, {})
new_query.instance_variable_get(:@credential_persistence).should.equal NSURLCredentialPersistenceForSession
+ new_query.cancel
end
it "should present base64-encoded credentials in Authorization header when provided" do
@@ -307,6 +341,7 @@ def sample_data
headers = query.instance_variable_get(:@headers)
headers.should.equal nil
+ query.cancel
end
@@ -347,6 +382,11 @@ def sample_data
@get_query = BubbleWrap::HTTP::Query.new( @url_string , :get, { headers: @headers } )
end
+ after do
+ @query.cancel
+ @get_query.cancel
+ end
+
it "should create a new request with HTTP method & header fields" do
@query.request.HTTPMethod.should.equal @query.method
@get_query.request.allHTTPHeaderFields.should.equal @headers
@@ -381,9 +421,14 @@ def sample_data
@post_query = BubbleWrap::HTTP::Query.new(@url_string, :post, {headers: @headers, payload: @payload})
end
+ after do
+ @post_query.cancel
+ end
+
it "should add default Content Type if no payload is given" do
query_without_payload = BubbleWrap::HTTP::Query.new(@url_string, :post, {headers: @headers})
query_without_payload.request.allHTTPHeaderFields.should.include? 'Content-Type'
+ query_without_payload.cancel
end
it "should automatically provide Content-Type if a payload is provided" do
@@ -393,6 +438,7 @@ def sample_data
it "should use the format parameter to decide the Content-Type" do
json_query = BubbleWrap::HTTP::Query.new(@url_string, :post, {headers: @headers, format: :json, payload: "{\"key\":\"abc1234\"}"})
json_query.request.allHTTPHeaderFields['Content-Type'].should.equal "application/json"
+ json_query.cancel
end
it "should default to multipart/form-data for payloads with a hash" do
@@ -403,13 +449,15 @@ def sample_data
it "should default to application/x-www-form-urlencoded for non-hash payloads" do
string_query = BubbleWrap::HTTP::Query.new(@url_string, :post, {headers: @headers, payload: "{\"key\":\"abc1234\"}"})
string_query.request.allHTTPHeaderFields['Content-Type'].should.equal "application/x-www-form-urlencoded"
+ string_query.cancel
end
it "should not add Content-Type if you provide one yourself" do
# also ensures check is case insenstive
@headers = { fake: 'headers', 'CONTENT-TYPE' => 'x-banana' }
- @post_query = BubbleWrap::HTTP::Query.new(@url_string, :post, {headers: @headers, payload: @payload})
- @post_query.request.allHTTPHeaderFields['CONTENT-TYPE'].should.equal @headers['CONTENT-TYPE']
+ post_query = BubbleWrap::HTTP::Query.new(@url_string, :post, {headers: @headers, payload: @payload})
+ post_query.request.allHTTPHeaderFields['CONTENT-TYPE'].should.equal @headers['CONTENT-TYPE']
+ post_query.cancel
end
end
@@ -500,7 +548,9 @@ def query_received_data
it "should turn off network indicator" do
UIApplication.sharedApplication.isNetworkActivityIndicatorVisible.should == true
@query.connection(nil, didFailWithError:@fake_error)
- UIApplication.sharedApplication.isNetworkActivityIndicatorVisible.should == false
+ wait BW::NetworkIndicator::DELAY do
+ UIApplication.sharedApplication.isNetworkActivityIndicatorVisible.should == false
+ end
end
end
@@ -540,10 +590,10 @@ def query_received_data
if App.ios?
it "should turn off the network indicator" do
- UIApplication.sharedApplication.isNetworkActivityIndicatorVisible.should == true
-
@query.connectionDidFinishLoading(nil)
- UIApplication.sharedApplication.isNetworkActivityIndicatorVisible.should == false
+ wait BW::NetworkIndicator::DELAY do
+ UIApplication.sharedApplication.isNetworkActivityIndicatorVisible.should == false
+ end
end
end
@@ -681,6 +731,7 @@ def query_received_data
query = BubbleWrap::HTTP::Query.new( @localhost_url , :get, @options )
query.connection(nil, didReceiveAuthenticationChallenge:@challenge)
@challenge.sender.continue_without_credential.should.equal true
+ query.cancel
end
end
@@ -697,7 +748,9 @@ def query_received_data
if App.ios?
it "should turn off the network indicator" do
- UIApplication.sharedApplication.isNetworkActivityIndicatorVisible.should.equal false
+ wait BW::NetworkIndicator::DELAY do
+ UIApplication.sharedApplication.isNetworkActivityIndicatorVisible.should.equal false
+ end
end
end
end
@@ -710,6 +763,10 @@ def query_received_data
@get_query = BubbleWrap::HTTP::Query.new(@url_string, :get, :payload => @payload)
end
+ after do
+ @get_query.cancel
+ end
+
it "should not append a ? to the end of the URL" do
@get_query.instance_variable_get(:@url).description.should.equal('http://fake.url/method')
end
@@ -725,6 +782,10 @@ def query_received_data
@escaped_url = "http://fake.url/method?we%20love=%23%3D%3DRock%26Roll%3D%3D%23&radio=Ga%20Ga&qual=3.0&incr=-1&RFC3986=%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%25%23%5B%5D"
end
+ after do
+ @get_query.cancel
+ end
+
it "should escape !*'();:@&=+$,/?%#[] characters only in keys and values" do
@get_query.instance_variable_get(:@url).description.should.equal @escaped_url
end
@@ -738,6 +799,11 @@ def query_received_data
@cookie_query = BubbleWrap::HTTP::Query.new("http://haz-cookiez.url", :get, :payload => {:something => "else"})
end
+ after do
+ @no_cookie_query.cancel
+ @cookie_query.cancel
+ end
+
it 'should disabled cookie-usage on nsurlrequest' do
@no_cookie_query.instance_variable_get(:@request).HTTPShouldHandleCookies.should.equal false
end
@@ -746,7 +812,13 @@ def query_received_data
@cookie_query.instance_variable_get(:@request).HTTPShouldHandleCookies.should.equal true
end
+ end
+ after do
+ if App.ios?
+ sleep(BW::NetworkIndicator::DELAY) if BW::NetworkIndicator.counter > 0
+ raise "I think you forgot to 'cancel' a query (in order for BW::NetworkIndicator to be tested properly, all queries must be canceled)" if BW::NetworkIndicator.counter > 0
+ end
end
class FakeSender
View
112 spec/motion/network-indicator/network_indicator_spec.rb
@@ -0,0 +1,112 @@
+describe BW::NetworkIndicator do
+
+ before do
+ BW::NetworkIndicator.reset!
+ end
+
+ after do
+ BW::NetworkIndicator.instance_variable_set(:@counter, 0)
+ UIApplication.sharedApplication.networkActivityIndicatorVisible = false
+ end
+
+ it 'should show the indicator immediately' do
+ BW::NetworkIndicator.show
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?.should == true
+ end
+
+ it 'should have a counter' do
+ BW::NetworkIndicator.show
+ BW::NetworkIndicator.counter.should == 1
+ BW::NetworkIndicator.hide
+ BW::NetworkIndicator.counter.should == 0
+ end
+
+ it 'should show the indicator from any thread' do
+ Dispatch::Queue.concurrent.async do
+ BW::NetworkIndicator.show
+ end
+ wait BW::NetworkIndicator::DELAY do
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?.should == true
+ end
+ end
+
+ it 'should hide the indicator' do
+ BW::NetworkIndicator.show
+ BW::NetworkIndicator.hide
+ wait BW::NetworkIndicator::DELAY do
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?.should == false
+ end
+ end
+
+ it 'should hide the indicator after a delay' do
+ BW::NetworkIndicator.show
+ BW::NetworkIndicator.hide
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?.should == true
+ wait BW::NetworkIndicator::DELAY do
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?.should == false
+ end
+ end
+
+ it 'should not hide the indicator if show/hide/show is called quickly' do
+ BW::NetworkIndicator.show
+ BW::NetworkIndicator.hide
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?.should == true
+ wait BW::NetworkIndicator::DELAY/2 do
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?.should == true
+ BW::NetworkIndicator.show
+ wait BW::NetworkIndicator::DELAY do
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?.should == true
+ end
+ end
+ end
+
+ it 'should keep track of how many times `show` was called' do
+ BW::NetworkIndicator.show
+ BW::NetworkIndicator.show
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?.should == true
+ BW::NetworkIndicator.hide
+ wait BW::NetworkIndicator::DELAY do
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?.should == true
+ BW::NetworkIndicator.hide
+ wait BW::NetworkIndicator::DELAY do
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?.should == false
+ end
+ end
+ end
+
+ it 'should allow `hide` to be called too many times' do
+ BW::NetworkIndicator.show
+ BW::NetworkIndicator.show
+ BW::NetworkIndicator.hide
+ BW::NetworkIndicator.hide
+ wait BW::NetworkIndicator::DELAY do
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?.should == false
+
+ BW::NetworkIndicator.hide
+ BW::NetworkIndicator.hide
+ wait BW::NetworkIndicator::DELAY do
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?.should == false
+
+ BW::NetworkIndicator.show
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?.should == true
+ end
+ end
+ end
+
+ it 'should reset the counter when `reset!` is called' do
+ BW::NetworkIndicator.show
+ BW::NetworkIndicator.show
+ BW::NetworkIndicator.reset!
+ UIApplication.sharedApplication.networkActivityIndicatorVisible?.should == false
+ end
+
+ it 'should have `visible?` method' do
+ BW::NetworkIndicator.show
+ BW::NetworkIndicator.visible?.should == true
+ BW::NetworkIndicator.hide
+ wait BW::NetworkIndicator::DELAY do
+ BW::NetworkIndicator.visible?.should == false
+ end
+ end
+
+end
Something went wrong with that request. Please try again.