elevate 0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,40 @@
1
+ describe Elevate::Dispatcher do
2
+ DELAY = 0.2
3
+
4
+ before do
5
+ @dispatcher = Elevate::Dispatcher.new
6
+ end
7
+
8
+ describe "#on_started=" do
9
+ before do
10
+ @dispatcher.on_started = lambda { @thread = NSThread.currentThread }
11
+ end
12
+
13
+ after do
14
+ @thread = nil
15
+ end
16
+
17
+ it "invokes the callback on the main thread" do
18
+ wait DELAY do
19
+ @thread.should == NSThread.currentThread
20
+ end
21
+ end
22
+
23
+ it "does not invoke the callback immediately" do
24
+ @thread.should.be.nil
25
+ end
26
+ end
27
+
28
+ describe "#on_finished=" do
29
+ before do
30
+ @dispatcher.on_finished = lambda { @thread = NSThread.currentThread }
31
+ @dispatcher.invoke_finished_callback()
32
+ end
33
+
34
+ it "invokes the callback on the main thread" do
35
+ wait DELAY do
36
+ @thread.should == NSThread.currentThread
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ describe Elevate::DSL do
2
+ describe "#on_started" do
3
+ it "stores the provided block" do
4
+ i = Elevate::DSL.new do
5
+ on_started { |operation| puts 'hi' }
6
+ end
7
+
8
+ i.started_callback.should.not.be.nil
9
+ end
10
+ end
11
+
12
+ describe "#on_completed" do
13
+ it "stores the passed block" do
14
+ i = Elevate::DSL.new do
15
+ on_completed { |o| puts 'hi' }
16
+ end
17
+
18
+ i.finished_callback.should.not.be.nil
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ class Target
2
+ attr_reader :called
3
+ attr_reader :io_coordinator
4
+ attr_accessor :exception
5
+ attr_accessor :result
6
+
7
+ def initialize
8
+ @called = 0
9
+ @result = true
10
+ end
11
+
12
+ def execute
13
+ @io_coordinator = Thread.current[:io_coordinator]
14
+
15
+ @called += 1
16
+
17
+ if @exception
18
+ raise @exception
19
+ end
20
+
21
+ @result
22
+ end
23
+ end
@@ -0,0 +1,40 @@
1
+ describe Elevate::HTTP::HTTPClient do
2
+ extend WebStub::SpecHelpers
3
+
4
+ before do
5
+ disable_network_access!
6
+
7
+ @base_url = "http://www.example.com"
8
+ @path = "/resource/action"
9
+ @url = @base_url + @path
10
+
11
+ @client = Elevate::HTTP::HTTPClient.new(@base_url)
12
+ end
13
+
14
+ it "issues requests to the complete URL" do
15
+ stub_request(:get, @url).to_return(status_code: 201)
16
+
17
+ @client.get(@path).status_code.should == 201
18
+ end
19
+
20
+ it "appends query parameters to the URL" do
21
+ stub_request(:get, @url + "?q=help&page=2").to_return(json: { result: 0 })
22
+
23
+ @client.get(@path, q: "help", page: 2).body.should == { "result" => 0 }
24
+ end
25
+
26
+ it "decodes JSON responses" do
27
+ result = { "int" => 42, "string" => "hi", "dict" => { "boolean" => true }, "array" => [1,2,3] }
28
+ stub_request(:get, @url).to_return(json: result)
29
+
30
+ @client.get(@path).body.should == result
31
+ end
32
+
33
+ it "encodes JSON bodies" do
34
+ stub_request(:post, @url).
35
+ with(json: { string: "hello", array: [1,2,3] }).
36
+ to_return(json: { result: true })
37
+
38
+ @client.post(@path, { string: "hello", array: [1,2,3] }).body.should == { "result" => true }
39
+ end
40
+ end
@@ -0,0 +1,103 @@
1
+ describe Elevate::HTTP::HTTPRequest do
2
+ extend WebStub::SpecHelpers
3
+
4
+ before do
5
+ disable_network_access!
6
+ end
7
+
8
+ before do
9
+ @url = "http://www.example.com/"
10
+ @body = "hello"
11
+ end
12
+
13
+ it "requires a valid HTTP method" do
14
+ lambda { Elevate::HTTP::HTTPRequest.new(:invalid, @url) }.should.raise(ArgumentError)
15
+ end
16
+
17
+ it "requires a URL starting with http" do
18
+ lambda { Elevate::HTTP::HTTPRequest.new(:get, "asdf") }.should.raise(ArgumentError)
19
+ end
20
+
21
+ it "requires the body to be an instance of NSData" do
22
+ lambda { Elevate::HTTP::HTTPRequest.new(:get, @url, body: @body) }.should.raise(ArgumentError)
23
+ end
24
+
25
+ describe "fulfilling a GET request" do
26
+ before do
27
+ stub_request(:get, @url).
28
+ to_return(body: @body, headers: {"Content-Type" => "text/plain"}, status_code: 201)
29
+
30
+ @request = Elevate::HTTP::HTTPRequest.new(:get, @url)
31
+ @response = @request.response
32
+ end
33
+
34
+ it "response has the correct status code" do
35
+ @response.status_code.should == 201
36
+ end
37
+
38
+ it "response has the right body" do
39
+ NSString.alloc.initWithData(@response.body, encoding:NSUTF8StringEncoding).should == @body
40
+ end
41
+
42
+ it "response has the correct headers" do
43
+ @response.headers.should == { "Content-Type" => "text/plain" }
44
+ end
45
+
46
+ it "response has no errors" do
47
+ @response.error.should.be.nil
48
+ end
49
+ end
50
+
51
+ describe "fulfilling a GET request with headers" do
52
+ before do
53
+ stub_request(:get, @url).with(headers: { "API-Token" => "abc123" }).to_return(body: @body)
54
+
55
+ @request = Elevate::HTTP::HTTPRequest.new(:get, @url, headers: {})
56
+ @response = @request.response
57
+ end
58
+
59
+ it "includes the headers in the request" do
60
+ @response.body.should.not.be.nil
61
+ end
62
+ end
63
+
64
+ describe "fulfilling a POST request with a body" do
65
+ before do
66
+ stub_request(:post, @url).with(body: @body).to_return(body: @body)
67
+ end
68
+
69
+ it "sends the body as part of the request" do
70
+ request = Elevate::HTTP::HTTPRequest.new(:post, @url, body: @body.dataUsingEncoding(NSUTF8StringEncoding))
71
+ response = request.response
72
+
73
+ NSString.alloc.initWithData(response.body, encoding:NSUTF8StringEncoding).should == @body
74
+ end
75
+ end
76
+
77
+ describe "cancelling a request" do
78
+ before do
79
+ stub_request(:get, @url).to_return(body: @body, delay: 1.0)
80
+ end
81
+
82
+ it "aborts the request" do
83
+ start = Time.now
84
+
85
+ request = Elevate::HTTP::HTTPRequest.new(:get, @url)
86
+ request.start()
87
+ request.cancel()
88
+
89
+ response = request.response # simulate blocking
90
+ finish = Time.now
91
+
92
+ (finish - start).should < 1.0
93
+ end
94
+
95
+ it "sets the response to nil" do
96
+ request = Elevate::HTTP::HTTPRequest.new(:get, @url)
97
+ request.start()
98
+ request.cancel()
99
+
100
+ request.response.should.be.nil
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,44 @@
1
+ describe Elevate::IOCoordinator do
2
+ before do
3
+ @coordinator = Elevate::IOCoordinator.new
4
+ end
5
+
6
+ it "is not cancelled" do
7
+ @coordinator.should.not.be.cancelled
8
+ end
9
+
10
+ describe "#install" do
11
+ it "stores the coordinator in a thread-local variable" do
12
+ @coordinator.install()
13
+
14
+ Thread.current[:io_coordinator].should == @coordinator
15
+ end
16
+ end
17
+
18
+ [:signal_blocked, :signal_unblocked].each do |method|
19
+ describe method.to_s do
20
+ describe "when IO has not been cancelled" do
21
+ it "does not raise CancelledError" do
22
+ lambda { @coordinator.send(method, 42) }.should.not.raise
23
+ end
24
+ end
25
+
26
+ describe "when IO was cancelled" do
27
+ it "raises CancelledError" do
28
+ @coordinator.cancel()
29
+
30
+ lambda { @coordinator.send(method, "hello") }.should.raise(Elevate::CancelledError)
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ describe "#uninstall" do
37
+ it "removes the coordinator from a thread-local variable" do
38
+ @coordinator.install()
39
+ @coordinator.uninstall()
40
+
41
+ Thread.current[:io_coordinator].should.be.nil
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,133 @@
1
+ describe Elevate::ElevateOperation do
2
+ before do
3
+ @target = Target.new
4
+ @operation = Elevate::ElevateOperation.alloc.initWithTarget(@target)
5
+ @queue = NSOperationQueue.alloc.init
6
+ end
7
+
8
+ after do
9
+ @queue.waitUntilAllOperationsAreFinished()
10
+ end
11
+
12
+ it "subclasses NSOperation" do
13
+ @operation.class.ancestors.should.include NSOperation
14
+ end
15
+
16
+ describe "#on_finished" do
17
+ it "invokes it after #on_started" do
18
+ @lock = NSLock.alloc.init
19
+ @value = []
20
+
21
+ @operation.on_started = lambda do
22
+ @lock.lock()
23
+ if @value == []
24
+ @value << 1
25
+ end
26
+ @lock.unlock()
27
+ end
28
+
29
+ @operation.on_finished = lambda do
30
+ @lock.lock()
31
+ if @value == [1]
32
+ @value << 2
33
+ end
34
+ @lock.unlock()
35
+
36
+ resume
37
+ end
38
+
39
+ @queue.addOperation(@operation)
40
+
41
+ wait_max 1.0 do
42
+ @lock.lock()
43
+ @value.should == [1,2]
44
+ @lock.unlock()
45
+ end
46
+ end
47
+ end
48
+
49
+ describe "#exception" do
50
+ describe "when no exception is raised" do
51
+ it "returns nil" do
52
+ @queue.addOperation(@operation)
53
+ @operation.waitUntilFinished()
54
+
55
+ @operation.exception.should.be.nil
56
+ end
57
+ end
58
+
59
+ describe "when an exception is raised" do
60
+ it "returns the exception" do
61
+ @target.exception = IndexError.new
62
+
63
+ @queue.addOperation(@operation)
64
+ @operation.waitUntilFinished()
65
+
66
+ @operation.exception.should == @target.exception
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "#main" do
72
+ describe "when the operation has not been run" do
73
+ it "invokes the target" do
74
+ @queue.addOperation(@operation)
75
+ @operation.waitUntilFinished()
76
+
77
+ @target.called.should == 1
78
+ end
79
+ end
80
+
81
+ describe "when the operation has been cancelled prior to starting" do
82
+ it "does not invoke the target" do
83
+ @operation.cancel()
84
+
85
+ @queue.addOperation(@operation)
86
+ @operation.waitUntilFinished()
87
+
88
+ @target.called.should == 0
89
+ end
90
+ end
91
+
92
+ describe "when the operation is running" do
93
+ it "allows IO to be cancelled" do
94
+ @queue.addOperation(@operation)
95
+ @operation.waitUntilFinished()
96
+
97
+ @target.io_coordinator.should.not.be.nil
98
+ end
99
+ end
100
+ end
101
+
102
+ describe "#result" do
103
+ before do
104
+ @target.result = 42
105
+ end
106
+
107
+ describe "before starting the operation" do
108
+ it "returns nil" do
109
+ @operation.result.should.be.nil
110
+ end
111
+ end
112
+
113
+ describe "when the operation has been cancelled" do
114
+ it "returns nil" do
115
+ @operation.cancel()
116
+
117
+ @queue.addOperation(@operation)
118
+ @operation.waitUntilFinished()
119
+
120
+ @operation.result.should.be.nil
121
+ end
122
+ end
123
+
124
+ describe "when the operation has finished" do
125
+ it "returns the result of the target's #execute method" do
126
+ @queue.addOperation(@operation)
127
+ @operation.waitUntilFinished()
128
+
129
+ @operation.result.should == 42
130
+ end
131
+ end
132
+ end
133
+ end
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: elevate
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.3'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Matt Green
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.9.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.9.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: guard-motion
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.1.1
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.1.1
46
+ - !ruby/object:Gem::Dependency
47
+ name: rb-fsevent
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.1
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.1
62
+ - !ruby/object:Gem::Dependency
63
+ name: webstub
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 0.3.3
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.3.3
78
+ description: Distill the essence of your RubyMotion app
79
+ email:
80
+ - mattgreenrocks@gmail.com
81
+ executables: []
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - .gitignore
86
+ - .rvmrc
87
+ - Gemfile
88
+ - Gemfile.lock
89
+ - Guardfile
90
+ - LICENSE
91
+ - README.md
92
+ - Rakefile
93
+ - app/app_delegate.rb
94
+ - elevate.gemspec
95
+ - lib/elevate.rb
96
+ - lib/elevate/api.rb
97
+ - lib/elevate/callback.rb
98
+ - lib/elevate/dispatcher.rb
99
+ - lib/elevate/dsl.rb
100
+ - lib/elevate/http/base64.rb
101
+ - lib/elevate/http/http_client.rb
102
+ - lib/elevate/http/request.rb
103
+ - lib/elevate/http/response.rb
104
+ - lib/elevate/http/uri.rb
105
+ - lib/elevate/io_coordinator.rb
106
+ - lib/elevate/operation.rb
107
+ - lib/elevate/promise.rb
108
+ - lib/elevate/version.rb
109
+ - spec/api_spec.rb
110
+ - spec/callback_spec.rb
111
+ - spec/dispatcher_spec.rb
112
+ - spec/dsl_spec.rb
113
+ - spec/helpers/target.rb
114
+ - spec/http/http_client_spec.rb
115
+ - spec/http/http_request_spec.rb
116
+ - spec/io_coordinator_spec.rb
117
+ - spec/operation_spec.rb
118
+ homepage: http://github.com/mattgreen/elevate
119
+ licenses: []
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ! '>='
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ segments:
131
+ - 0
132
+ hash: 1532692712045252370
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ! '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ segments:
140
+ - 0
141
+ hash: 1532692712045252370
142
+ requirements: []
143
+ rubyforge_project:
144
+ rubygems_version: 1.8.24
145
+ signing_key:
146
+ specification_version: 3
147
+ summary: Distill the essence of your RubyMotion app
148
+ test_files:
149
+ - spec/api_spec.rb
150
+ - spec/callback_spec.rb
151
+ - spec/dispatcher_spec.rb
152
+ - spec/dsl_spec.rb
153
+ - spec/helpers/target.rb
154
+ - spec/http/http_client_spec.rb
155
+ - spec/http/http_request_spec.rb
156
+ - spec/io_coordinator_spec.rb
157
+ - spec/operation_spec.rb