fsync-client 0.0.1.pre

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,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Vanderson Mota
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,18 @@
1
+ = fsync-client
2
+
3
+ Como usar:
4
+
5
+ require 'fsync-client'
6
+
7
+ Instancie a classe FinanceSync passando a url do servidor e a versão dos dados que
8
+ estão na máquina cliente;
9
+
10
+ @finance_sync = FinanceSync.new(:services_url=>"https://services.myfreecomm.com.br/, :version=>22)
11
+
12
+ Para sincronizar, você deve mandar um hash com os dados que você alterou desde a última versão:
13
+ @finance_sync.synchronize({:dados=>'alterados'})
14
+
15
+ Para maiores detalhes de como funciona a api do sync, veja em: git@github.com:myfreecomm/Snakepit.git
16
+
17
+
18
+ Copyright (c) 2010 Vanderson Mota. See LICENSE for details.
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "fsync-client"
8
+ gem.summary = "gem to communicate with financesync"
9
+ gem.description = "gem to communicate with financesync"
10
+ gem.email = "vanderson.mota@myfreecomm.com.br"
11
+ gem.homepage = "http://github.com/vandersonmota/fsync-client"
12
+ gem.authors = ["Vanderson Mota"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'spec/rake/spectask'
22
+ Spec::Rake::SpecTask.new(:spec) do |spec|
23
+ spec.libs << 'lib' << 'spec'
24
+ spec.spec_files = FileList['spec/**/*_spec.rb']
25
+ end
26
+
27
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.pattern = 'spec/**/*_spec.rb'
30
+ spec.rcov = true
31
+ end
32
+
33
+ task :spec => :check_dependencies
34
+
35
+ task :default => :spec
36
+
37
+ require 'rake/rdoctask'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+
41
+ rdoc.rdoc_dir = 'rdoc'
42
+ rdoc.title = "fsync-client #{version}"
43
+ rdoc.rdoc_files.include('README*')
44
+ rdoc.rdoc_files.include('lib/**/*.rb')
45
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1.pre
@@ -0,0 +1,62 @@
1
+ require 'rubygems'
2
+ require 'json'
3
+ require 'net/http'
4
+
5
+ class FinanceSync
6
+
7
+ attr_reader :version, :entities, :conflicts, :error
8
+
9
+ def initialize(params)
10
+ @services_url = params[:services_url]
11
+ @version = params[:version]
12
+ @user = params[:user]
13
+ @password = params[:password]
14
+ raise ArgumentError if @user.nil? or @password.nil?
15
+ raise TypeError unless @version.is_a? Fixnum
16
+
17
+ @error = nil
18
+ @conflicts = []
19
+ end
20
+
21
+ def synchronize(data)
22
+ data = request_sync(data)
23
+ return false if data == false
24
+ @version = data['version']
25
+ @entities = data['data']
26
+ @conflicts = data['conflicts']
27
+ return true
28
+ end
29
+
30
+ protected
31
+
32
+ def assemble_data(entities)
33
+ return {"version" => @version, "data" => entities}
34
+ end
35
+
36
+ def request_sync(entities)
37
+ data = assemble_data(entities)
38
+ errors = {"400"=>"bad data", "500"=>"sync server error",
39
+ "423"=>"locked", "401"=> "login error"}
40
+
41
+ put = Net::HTTP::Put.new("/financedesktop/sync/synchronize")
42
+ put.basic_auth(@user, @password)
43
+ put.content_type = 'application/json'
44
+ begin
45
+ response = Net::HTTP.start(@services_url) {|http|
46
+ http.request(put, data.to_json)
47
+ }
48
+ rescue SocketError, URI::InvalidURIError
49
+ @error = 'invalid url'
50
+ return false
51
+ end
52
+
53
+ case response
54
+ when Net::HTTPSuccess
55
+ return JSON.parse(response.body)
56
+ else
57
+ @error = errors[response.code]
58
+ return false
59
+ end
60
+ end
61
+ end
62
+
@@ -0,0 +1,325 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'fsync-client'
3
+
4
+ ENTITIES = [
5
+ {"entity"=>
6
+ {"currency"=> "BRL", "payee"=> nil, "amount"=> "100.00000000",
7
+ "imported"=> false, "description"=> "Novo lançamento",
8
+ "payer"=> "Rendimento aplicação", "base_date"=> "2010-03-16T11=>29=>02.354014",
9
+ "document_number"=> 1, "guid"=> "ffffffffffffffffffffffffffffffff"
10
+ }
11
+ }
12
+ ]
13
+
14
+
15
+ UPDATED_VERSION = '{"conflicts": [], "version": 49, "data": [{"entity": {"imported": "true",
16
+ "description": "roupa", "document-number": 111, "amount": "200.00000000",
17
+ "date": "2010-10-11", "guid": "22a648b0-2fe1-4888-96a4-caa27a4c27d7",
18
+ "type": "transaction"}}]}'
19
+
20
+ USER = 'jalim'
21
+ PASSWORD = 'habei'
22
+
23
+ describe "Finance Sync API wrapper" do
24
+
25
+ def fake_sync_response(response, user='', password='')
26
+ if not (user.empty? and password.empty?)
27
+ credentials = "#{user}:#{password}@"
28
+ else
29
+ credentials = ""
30
+ end
31
+
32
+ FakeWeb.register_uri(
33
+ :put,
34
+ "http://#{credentials}services.myfreecomm.com.br/financedesktop/sync/synchronize",
35
+ response)
36
+ end
37
+
38
+ before(:each) do
39
+ @services_url = "services.myfreecomm.com.br"
40
+ @finance_sync = FinanceSync.new(:services_url => @services_url, :version => 2,
41
+ :user=>USER, :password=>PASSWORD)
42
+ end
43
+
44
+ describe "initializer" do
45
+
46
+ it "should store version" do
47
+ @finance_sync.instance_variable_get(:@version).should == 2
48
+ end
49
+
50
+ it "should store services_url" do
51
+ @finance_sync.instance_variable_get(:@services_url).should == 'services.myfreecomm.com.br'
52
+ end
53
+
54
+ end
55
+
56
+ it "should have .version" do
57
+ @finance_sync = FinanceSync.new(:services_url=>@services_url, :version => 4,
58
+ :user=>USER, :password=>PASSWORD)
59
+ @finance_sync.version.should == 4
60
+ end
61
+
62
+ describe "synchronizer" do
63
+
64
+ it "should send the params formed correctly" do
65
+
66
+ @finance_sync = FinanceSync.new(:services_url => @services_url, :version => 48,
67
+ :user=>USER, :password=>PASSWORD)
68
+ correct_json = {"version"=>@finance_sync.version, "data"=>ENTITIES}.to_json
69
+
70
+ put = mock(Net::HTTP::Put)
71
+ Net::HTTP::Put.should_receive(:new).with("/financedesktop/sync/synchronize").once.and_return(put)
72
+ put.should_receive(:basic_auth).with(USER, PASSWORD)
73
+ put.should_receive(:content_type=).with('application/json')
74
+
75
+ http = mock()
76
+ http.should_receive(:request).with(put, correct_json)
77
+
78
+ http_success_mock = mock(Net::HTTPSuccess)
79
+ http_success_mock.stub!(:code).and_return("200")
80
+ http_success_mock.stub!(:body).and_return(UPDATED_VERSION)
81
+
82
+
83
+ Net::HTTP.should_receive(:start).with(@services_url).and_yield(http).and_return(http_success_mock)
84
+ @finance_sync.synchronize(ENTITIES)
85
+ end
86
+
87
+ describe "with not found url" do
88
+
89
+ before(:each) do
90
+ @invalid_url = 'invalid_url'
91
+ @finance_sync = FinanceSync.new(:services_url => @invalid_url, :version => 48,
92
+ :user=>USER, :password=>PASSWORD)
93
+ @correct_json = {"version"=>@finance_sync.version, "data"=>ENTITIES}.to_json
94
+
95
+ @put = mock(Net::HTTP::Put)
96
+ Net::HTTP::Put.should_receive(:new).with("/financedesktop/sync/synchronize").once.and_return(@put)
97
+ @put.should_receive(:basic_auth).with(USER, PASSWORD)
98
+ @put.should_receive(:content_type=).with('application/json')
99
+ http = mock()
100
+ Net::HTTP.should_receive(:start).with(@invalid_url).and_raise(SocketError)
101
+
102
+ end
103
+
104
+ it "should return false" do
105
+ @finance_sync.synchronize(ENTITIES).should be_false
106
+ end
107
+
108
+ it "should return set 'invalid url' error" do
109
+ @finance_sync.synchronize(ENTITIES)
110
+ @finance_sync.error.should == 'invalid url'
111
+ end
112
+
113
+
114
+ end
115
+
116
+ describe "with invalid url" do
117
+
118
+ before(:each) do
119
+ @finance_sync = FinanceSync.new(:services_url => nil, :version => 48,
120
+ :user=>USER, :password=>PASSWORD)
121
+ end
122
+
123
+ it "should return false" do
124
+ @finance_sync.synchronize(ENTITIES).should be_false
125
+ end
126
+
127
+ it "should set 'invalid url' error" do
128
+ @finance_sync.synchronize(ENTITIES)
129
+ @finance_sync.error.should == 'invalid url'
130
+ end
131
+
132
+ end
133
+
134
+ describe "with invalid version specified" do
135
+ it "should raise TypeError if a non integer is passed " do
136
+ wrong_params = {:services_url => "services.myfreecomm.com.br",
137
+ :version => "abcsd", :user=>USER, :password=>PASSWORD}
138
+ lambda {
139
+ FinanceSync.new(wrong_params)
140
+ }.should raise_exception(TypeError)
141
+
142
+ end
143
+ end
144
+
145
+ describe "with wrong credentials provided" do
146
+
147
+ before(:each) do
148
+ fake_sync_response({:status=>[401, "unauthorized"]}, 'wrong', 'credential' )
149
+ @finance_sync = FinanceSync.new(:services_url => @services_url, :version => 48,
150
+ :user=>'wrong', :password=>'credential')
151
+ end
152
+
153
+ it "should return false " do
154
+ @finance_sync.synchronize(ENTITIES).should be_false
155
+ end
156
+
157
+ it "should set 'login error'" do
158
+ @finance_sync.synchronize(ENTITIES).should be_false
159
+ @finance_sync.error.should == 'login error'
160
+ end
161
+
162
+ end
163
+
164
+ describe "with no credentials provided" do
165
+
166
+ it "should raise 'Argument Error'" do
167
+ lambda {
168
+ FinanceSync.new(:services_url => @services_url, :version => 48)
169
+ }.should raise_exception(ArgumentError)
170
+ end
171
+ end
172
+
173
+ describe "with no conflicts and no new data" do
174
+
175
+ before(:each) do
176
+ @finance_sync = FinanceSync.new(:services_url => "services.myfreecomm.com.br",
177
+ :version => 48, :user=>'wrong',
178
+ :password=>'credentials' )
179
+ fake_sync_response({:status=>[200, "OK"],
180
+ :body=>'{"conflicts": [], "version": 48, "data": []}'},
181
+ 'wrong', 'credentials')
182
+ end
183
+
184
+ it "should not update version" do
185
+ lambda {
186
+ @finance_sync.synchronize(ENTITIES)
187
+ }.should_not change(@finance_sync, :version)
188
+ end
189
+
190
+ it "should not populate conflicts" do
191
+ lambda {
192
+ @finance_sync.synchronize(ENTITIES)
193
+ }.should_not change(@finance_sync, :conflicts)
194
+
195
+ end
196
+
197
+ it "should return true" do
198
+ @finance_sync.synchronize(ENTITIES).should be_true
199
+ end
200
+
201
+ end
202
+
203
+ describe "with no conflicts and new data from sync server" do
204
+
205
+ before(:each) do
206
+
207
+ @finance_sync = FinanceSync.new(:services_url => "services.myfreecomm.com.br",
208
+ :version => 48, :user=>'wrong',
209
+ :password=>'credentials')
210
+ fake_sync_response({:status=>[200, "OK"], :body=>UPDATED_VERSION},
211
+ 'wrong', 'credentials')
212
+
213
+ end
214
+
215
+ it "should populate entities" do
216
+ @finance_sync.synchronize(ENTITIES)
217
+ @finance_sync.entities.should_not be_empty
218
+
219
+ end
220
+
221
+ it "should update version" do
222
+ @finance_sync.synchronize(ENTITIES)
223
+ @finance_sync.version.should == 49
224
+
225
+ end
226
+
227
+ it "should not have conflicts" do
228
+ @finance_sync.synchronize(ENTITIES)
229
+ @finance_sync.conflicts.should be_empty
230
+
231
+ end
232
+
233
+ it "should return true" do
234
+ @finance_sync.synchronize(@old_transaction).should be_true
235
+ end
236
+
237
+ end
238
+ end
239
+
240
+ describe "with bad data" do
241
+
242
+ before(:each) do
243
+ fake_sync_response({:status=>[400, "Bad request"], :body=>"invalid data"},
244
+ USER, PASSWORD)
245
+ @bad_data = '{"version": 47, "entity":}'
246
+ end
247
+
248
+ it "should set error 'bad data'" do
249
+ @finance_sync.synchronize(@bad_data)
250
+ @finance_sync.error.should == "bad data"
251
+ end
252
+
253
+ it "should return false" do
254
+ @finance_sync.synchronize(@bad_data).should be_false
255
+ end
256
+
257
+ end
258
+
259
+ describe "on sync server error" do
260
+
261
+ before(:each) do
262
+ fake_sync_response({:status=>[500, "Server Error"], :body=>"Server Error"},
263
+ USER, PASSWORD)
264
+ @valid_data = '{"valid": "data"}'
265
+ end
266
+
267
+ it "should set error 'sync server error'" do
268
+ @finance_sync.synchronize(@valid_data)
269
+ @finance_sync.error.should == "sync server error"
270
+ end
271
+
272
+ it "should return false" do
273
+ @finance_sync.synchronize(@valid_data).should be_false
274
+ end
275
+
276
+ end
277
+
278
+ describe "on sync server lock" do
279
+
280
+ before(:each) do
281
+ fake_sync_response({:status=>[423, "Locked"], :body=>"Locked"}, USER, PASSWORD)
282
+ @valid_data = '{"valid": "data"}'
283
+ end
284
+
285
+ it "should set error 'sync server error'" do
286
+ @finance_sync.synchronize(@valid_data)
287
+ @finance_sync.error.should == "locked"
288
+ end
289
+
290
+ it "should return false" do
291
+ @finance_sync.synchronize(@valid_data).should be_false
292
+ end
293
+
294
+ end
295
+
296
+ describe "with any error" do
297
+ before(:all) do
298
+ @finance_sync.stub!(:request_sync).and_return(false)
299
+ end
300
+
301
+ it "should not alter sync version" do
302
+ lambda {
303
+ @finance_sync.synchronize(@valid_data)
304
+ }.should_not change(@finance_sync, :version)
305
+ end
306
+
307
+ it "should not populate conflicts" do
308
+ lambda {
309
+ @finance_sync.synchronize(@valid_data)
310
+ }.should_not change(@finance_sync, :conflicts)
311
+ end
312
+
313
+ it "should not update entities" do
314
+ lambda {
315
+ @finance_sync.synchronize(@valid_data)
316
+ }.should_not change(@finance_sync, :entities)
317
+ end
318
+
319
+ it "should return false" do
320
+ @finance_sync.synchronize(@valid_data).should be_false
321
+ end
322
+
323
+ end
324
+
325
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,13 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'spec'
4
+ require 'spec/autorun'
5
+ require 'rubygems'
6
+ require 'fakeweb'
7
+
8
+
9
+ FakeWeb.allow_net_connect = false
10
+
11
+ Spec::Runner.configure do |config|
12
+
13
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fsync-client
3
+ version: !ruby/object:Gem::Version
4
+ hash: 961915968
5
+ prerelease: true
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ - pre
11
+ version: 0.0.1.pre
12
+ platform: ruby
13
+ authors:
14
+ - Vanderson Mota
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-12-03 00:00:00 -02:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: rspec
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 13
31
+ segments:
32
+ - 1
33
+ - 2
34
+ - 9
35
+ version: 1.2.9
36
+ type: :development
37
+ version_requirements: *id001
38
+ description: gem to communicate with financesync
39
+ email: vanderson.mota@myfreecomm.com.br
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files:
45
+ - LICENSE
46
+ - README.rdoc
47
+ files:
48
+ - .document
49
+ - .gitignore
50
+ - LICENSE
51
+ - README.rdoc
52
+ - Rakefile
53
+ - VERSION
54
+ - lib/fsync-client.rb
55
+ - spec/lib/fsync-client_spec.rb
56
+ - spec/spec.opts
57
+ - spec/spec_helper.rb
58
+ has_rdoc: true
59
+ homepage: http://github.com/vandersonmota/fsync-client
60
+ licenses: []
61
+
62
+ post_install_message:
63
+ rdoc_options:
64
+ - --charset=UTF-8
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ">"
80
+ - !ruby/object:Gem::Version
81
+ hash: 25
82
+ segments:
83
+ - 1
84
+ - 3
85
+ - 1
86
+ version: 1.3.1
87
+ requirements: []
88
+
89
+ rubyforge_project:
90
+ rubygems_version: 1.3.7
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: gem to communicate with financesync
94
+ test_files:
95
+ - spec/spec_helper.rb
96
+ - spec/lib/fsync-client_spec.rb