toodledo 1.0.2 → 1.1.0

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.
@@ -22,9 +22,8 @@ module Toodledo
22
22
  return "@[#{name}]"
23
23
  end
24
24
 
25
-
26
25
  #
27
- # Parses the context of an element.
26
+ # Parses the context of an REXML element.
28
27
  #
29
28
  def self.parse(session, el)
30
29
  id = el.attributes['id']
@@ -27,11 +27,8 @@ module Toodledo
27
27
  def archived?
28
28
  return @archived == 1
29
29
  end
30
-
31
- def to_s()
32
- return "*[#{name}]"
33
- end
34
-
30
+
31
+ # Creates a session object from an XML element.
35
32
  def self.parse(session, el)
36
33
  id = el.attributes['id']
37
34
  is_private = el.attributes['private']
@@ -46,5 +43,4 @@ module Toodledo
46
43
  end
47
44
  end
48
45
 
49
-
50
46
  end
data/lib/toodledo/goal.rb CHANGED
@@ -26,6 +26,7 @@ module Toodledo
26
26
  @id = id
27
27
  @level = level
28
28
  @contributes_id = contributes_id
29
+ @contributes = nil
29
30
  @name = name
30
31
  end
31
32
 
@@ -59,16 +60,9 @@ module Toodledo
59
60
  end
60
61
 
61
62
  def to_xml()
62
- return "<goal id=\"#{@id}\" level=\"#{@level}\" contributes=\"#{@contributes.server_id}\" name=\"#{@name}\">"
63
+ return "<goal id=\"#{@id}\" level=\"#{@level}\" contributes=\"#{@contributes_id}\" name=\"#{@name}\">"
63
64
  end
64
65
 
65
- def to_s()
66
- msg = "$[#{name}]"
67
- #if (contributes != NO_GOAL)
68
- # msg += " (Contributes to: #{contributes.name})"
69
- #end
70
- return msg
71
- end
72
66
  end
73
67
 
74
68
  end
@@ -0,0 +1,14 @@
1
+ #
2
+ #
3
+ #
4
+ module Toodledo
5
+
6
+ #
7
+ # Thrown when the session's configuration is invalid.
8
+ #
9
+ class InvalidConfigurationError < RuntimeError
10
+ def initialize(msg = nil)
11
+ super(msg)
12
+ end
13
+ end
14
+ end
@@ -30,22 +30,5 @@ module Toodledo
30
30
  return false
31
31
  end
32
32
 
33
- def self.convert(input)
34
- case input
35
- when 'negative'
36
- return Priority::NEGATIVE
37
- when 'low'
38
- return Priority::LOW
39
- when 'medium'
40
- return Priority::MEDIUM
41
- when 'high'
42
- return Priority::HIGH
43
- when 'top'
44
- return Priority::TOP
45
- else
46
- raise ArgumentError.new("Unknown priority: #{input}")
47
- end
48
- end
49
-
50
33
  end
51
34
  end
@@ -21,7 +21,9 @@ module Toodledo
21
21
  USER_AGENT = "Ruby/#{Toodledo::VERSION} (#{RUBY_PLATFORM})"
22
22
 
23
23
  HEADERS = {
24
- 'User-Agent' => USER_AGENT
24
+ 'User-Agent' => USER_AGENT,
25
+ 'Connection' => 'keep-alive',
26
+ 'Keep-Alive' => '300'
25
27
  }
26
28
 
27
29
  EXPIRATION_TIME_IN_SECS = 60 * 60
@@ -37,10 +39,10 @@ module Toodledo
37
39
  attr_reader :base_url, :user_id, :proxy
38
40
 
39
41
  # Creates a new session, using the given user name and password.
40
- # throws exception if user_id or password are nil.
42
+ # throws InvalidConfigurationError if user_id or password are nil.
41
43
  def initialize(user_id, password, logger = nil)
42
- raise "Nil user_id" if (user_id == nil)
43
- raise "Nil password" if (password == nil)
44
+ raise InvalidConfigurationError.new("Nil user_id") if (user_id == nil)
45
+ raise InvalidConfigurationError.new("Nil password") if (password == nil)
44
46
 
45
47
  @user_id = user_id
46
48
  @password = password
@@ -72,11 +74,11 @@ module Toodledo
72
74
  # logger.debug("user_id = #{@user_id}, #{@email} #{@password}")
73
75
 
74
76
  if (@user_id == '1')
75
- raise "No matching user_id found"
77
+ raise InvalidConfigurationError.new("Invalid user_id")
76
78
  end
77
79
 
78
80
  if (@user_id == '0')
79
- raise "Server says we have a blank email or password"
81
+ raise InvalidConfigurationError.new("Invalid password")
80
82
  end
81
83
 
82
84
  # Set the base URL.
@@ -140,14 +142,6 @@ module Toodledo
140
142
  raise 'Must call connect() before this method'
141
143
  end
142
144
 
143
- # Break all the parameters down into key=value seperated by semi colons
144
- stringified_params = (key != nil) ? ';key=' + key : ''
145
-
146
- params.each { |k, v|
147
- stringified_params += ';' + k.to_s + '=' + escape_text(v)
148
- }
149
- url = make_uri(method, stringified_params)
150
-
151
145
  # If it's been more than an hour, then ask for a new key.
152
146
  if (@key != nil && expired?)
153
147
  logger.debug("call(#{method}) connection expired, reconnecting...") if logger
@@ -157,8 +151,21 @@ module Toodledo
157
151
  proxy = @proxy
158
152
  disconnect() # ensures that key == nil, which is crucial to avoid an endless loop...
159
153
  connect(base_url, proxy)
154
+
155
+ # swap out the key (if any) before we start assembling the request
156
+ if (key != nil)
157
+ key = @key
158
+ end
160
159
  end
161
160
 
161
+ # Break all the parameters down into key=value seperated by semi colons
162
+ stringified_params = (key != nil) ? ';key=' + key : ''
163
+
164
+ params.each { |k, v|
165
+ stringified_params += ';' + k.to_s + '=' + escape_text(v)
166
+ }
167
+ url = make_uri(method, stringified_params)
168
+
162
169
  # Establish the proxy
163
170
  if (@proxy != nil)
164
171
  logger.debug("call(#{method}) establishing proxy...") if logger
@@ -215,7 +222,7 @@ module Toodledo
215
222
 
216
223
  # Gets the token method, given the id.
217
224
  def get_token(user_id)
218
- raise "Nil user_id" if (user_id == nil)
225
+ raise "Nil user_id" if (user_id == nil || user_id.empty?)
219
226
 
220
227
  params = { :userid => user_id }
221
228
  result = call('getToken', params)
data/lib/toodledo/task.rb CHANGED
@@ -1,6 +1,7 @@
1
1
 
2
2
  require 'toodledo/repeat'
3
3
  require 'toodledo/priority'
4
+ require 'date'
4
5
 
5
6
  module Toodledo
6
7
 
@@ -83,88 +84,6 @@ module Toodledo
83
84
  return ! (@children == nil || @children == 0)
84
85
  end
85
86
 
86
- def to_s()
87
- if (priority == Priority::NEGATIVE)
88
- fancyp = 'v'
89
- elsif (priority == Priority::LOW)
90
- fancyp = '~'
91
- else
92
- fancyp = '!' * priority
93
- end
94
-
95
- msg = "#{fancyp}"
96
-
97
- if (folder != Folder::NO_FOLDER)
98
- msg += " *[#{folder.name}]"
99
- end
100
-
101
- if (context != Context::NO_CONTEXT)
102
- msg += " @[#{context.name}]"
103
- end
104
-
105
- if (goal != Goal::NO_GOAL)
106
- msg += " $[#{goal.name}]"
107
- end
108
-
109
- if (duedate != nil)
110
- fmt = Session::DATE_FORMAT + ' ' + Session::TIME_FORMAT
111
- msg += " \#[#{duedatemodifier}#{duedate.strftime(fmt)}]"
112
- end
113
-
114
- if (repeat != Repeat::NONE)
115
- msg += " repeat[#{readable_repeat()}]"
116
- end
117
-
118
- if (tag != nil)
119
- msg += " tag[#{tag}]"
120
- end
121
-
122
- if (parent_id != nil)
123
- msg += " parent[#{parent_id}]"
124
- end
125
-
126
- if (length != nil)
127
- msg += " length[#{length}]"
128
- end
129
-
130
- if (timer != nil)
131
- msg += " timer[#{timer}]"
132
- end
133
-
134
- msg += " #{title}"
135
-
136
- if (note != nil)
137
- msg += "\n #{note}"
138
- end
139
-
140
- return msg
141
- end
142
-
143
- def readable_repeat()
144
- case repeat
145
- when Repeat::NONE
146
- ''
147
- when Repeat::WEEKLY
148
- "weekly"
149
- when Repeat::MONTHLY
150
- "monthly"
151
- when Repeat::YEARLY
152
- "yearly"
153
- when Repeat::DAILY
154
- "daily"
155
- when Repeat::BIWEEKLY
156
- "biweekly"
157
- when Repeat::BIMONTHLY
158
- "bimonthly"
159
- when Repeat::SEMIANNUALLY
160
- "semiannually"
161
- when Repeat::QUARTERLY
162
- "quarterly"
163
- else
164
- ''
165
- end
166
- end
167
-
168
87
  # Parses a task element and returns a new Task.
169
88
  def self.parse(session, el)
170
89
 
@@ -0,0 +1,192 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
+
3
+ require 'test/unit'
4
+ require 'toodledo/command_line/client'
5
+ require 'flexmock/test_unit'
6
+
7
+ module Toodledo
8
+ module CommandLine
9
+ class ClientTest < Test::Unit::TestCase
10
+
11
+ def setup()
12
+ client = Client.new()
13
+
14
+ # Set up a partial mock so we can override :print
15
+ @client = flexmock(client)
16
+ @session = flexmock('session')
17
+ end
18
+
19
+ def test_set_filter()
20
+ # We don't want an error message printed out here.
21
+ @client.should_receive(:print).never
22
+ @client.set_filter(@session, '!top')
23
+ end
24
+
25
+ def test_add_task_with_no_args()
26
+
27
+ input = 'This is a test'
28
+ args = {}
29
+
30
+ @session.should_receive(:add_task).with(input, args).and_return 1
31
+ @client.should_receive(:print).with('Task 1 added.')
32
+ @client.add_task(@session, input)
33
+ end
34
+
35
+ def test_add_task_with_folder()
36
+
37
+ input = '*Inbasket This is a test'
38
+
39
+ args = { :folder => "Inbasket" }
40
+
41
+ @session.should_receive(:add_task).with('This is a test', args).and_return(1)
42
+ @client.should_receive(:print).with('Task 1 added.')
43
+ @client.add_task(@session, input)
44
+ end
45
+
46
+ def test_add_task_with_context()
47
+
48
+ input = '@Home This is a test'
49
+
50
+ args = { :context => "Home" }
51
+
52
+ @session.should_receive(:add_task).with('This is a test', args).and_return(1)
53
+ @client.should_receive(:print).with('Task 1 added.')
54
+
55
+ @client.add_task(@session, input)
56
+ end
57
+
58
+ def test_add_task_with_goal()
59
+
60
+ input = '^Goal This is a test'
61
+
62
+ args = { :goal => "Goal" }
63
+
64
+ @session.should_receive(:add_task).with('This is a test', args).and_return(1)
65
+ @client.should_receive(:print).with('Task 1 added.')
66
+
67
+ @client.add_task(@session, input)
68
+ end
69
+
70
+ def test_add_task_with_priority()
71
+
72
+ input = '!top This is a test'
73
+
74
+ args = { :priority => Priority::TOP }
75
+
76
+ @session.should_receive(:add_task).with('This is a test', args).and_return(1)
77
+ @client.should_receive(:print).with('Task 1 added.')
78
+
79
+ @client.add_task(@session, input)
80
+ end
81
+
82
+ def test_add_folder()
83
+ input = 'name'
84
+
85
+ id = '1234'
86
+ @session.should_receive(:add_folder).with(input).and_return(id)
87
+ @client.should_receive(:print).with('Folder 1234 added.')
88
+
89
+ @client.add_folder(@session, input)
90
+ end
91
+
92
+ def test_add_context()
93
+ input = 'name'
94
+
95
+ id = '1234'
96
+ @session.should_receive(:add_context).with(input).and_return(id)
97
+ @client.should_receive(:print).with('Context 1234 added.')
98
+
99
+ @client.add_context(@session, input)
100
+ end
101
+
102
+ def test_add_goal()
103
+ input = 'name'
104
+
105
+ id = '1234'
106
+ level = Goal::SHORT_LEVEL
107
+ @session.should_receive(:add_goal).with(input, level).and_return(id)
108
+ @client.should_receive(:print).with('Goal 1234 added.')
109
+
110
+ @client.add_goal(@session, input)
111
+ end
112
+
113
+ def test_list_tasks_with_nothing()
114
+
115
+ params = {
116
+ :priority => Priority::LOW,
117
+ :title => 'foo',
118
+ :folder => Folder::NO_FOLDER,
119
+ :context => Context::NO_CONTEXT,
120
+ :goal => Goal::NO_GOAL,
121
+ :repeat => Repeat::NONE
122
+ }
123
+ task = Task.new(1234, params)
124
+ tasks = [ task ]
125
+ @session.should_receive(:get_tasks).and_return(tasks)
126
+ @client.should_receive(:print).with('<1234> -- !low foo')
127
+
128
+ input = ''
129
+ @client.list_tasks(@session, input)
130
+ end
131
+
132
+
133
+ def test_list_tasks_with_everything()
134
+
135
+ params = {
136
+ :priority => Priority::LOW,
137
+ :title => 'foo',
138
+ :folder => Folder.new(1234, 0, 0, 'test folder'),
139
+ :context => Context.new(345, 'test context'),
140
+ :goal => Goal.new(342341, 0, 0, 'test goal'),
141
+ :repeat => Repeat::BIWEEKLY,
142
+ :tag => 'some tag'
143
+ }
144
+ task = Task.new(1234, params)
145
+ tasks = [ task ]
146
+ @session.should_receive(:get_tasks).and_return(tasks)
147
+ @client.should_receive(:print).with('<1234> -- !low *[test folder] @[test context] ^[test goal] repeat[biweekly] tag[some tag] foo')
148
+
149
+ input = ''
150
+ @client.list_tasks(@session, input)
151
+ end
152
+
153
+ def test_list_contexts()
154
+ context = Context.new(1234, 'Context')
155
+ contexts = [ context ]
156
+ @session.should_receive(:get_contexts).and_return(contexts)
157
+ @client.should_receive(:print).with('<1234> -- @[Context]')
158
+
159
+ input = ''
160
+ @client.list_contexts(@session, input)
161
+ end
162
+
163
+ def test_list_goals()
164
+ goals = [ Goal.new(1234, Goal::LIFE_LEVEL, 0, 'Name') ]
165
+ @session.should_receive(:get_goals).and_return(goals)
166
+ @client.should_receive(:print).with('<1234> -- life ^[Name]')
167
+
168
+ input = ''
169
+ @client.list_goals(@session, input)
170
+ end
171
+
172
+ def test_list_folders()
173
+ folders = [ Folder.new(1234, 0, 0, 'Name') ]
174
+ @session.should_receive(:get_folders).and_return(folders)
175
+ @client.should_receive(:print).with('<1234> -- *[Name]')
176
+
177
+ input = ''
178
+ @client.list_folders(@session, input)
179
+ end
180
+
181
+ def test_archive_folder()
182
+
183
+ @session.should_receive(:edit_folder).and_return(true)
184
+ @client.should_receive(:print).with('Folder 234 archived.')
185
+
186
+ input = '234'
187
+ @client.archive_folder(@session, input)
188
+ end
189
+
190
+ end
191
+ end
192
+ end