haraldmartin-things-rb 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +3 -0
- data/LICENSE +19 -0
- data/README.markdown +115 -0
- data/Rakefile +13 -0
- data/bin/things +53 -0
- data/lib/things.rb +24 -0
- data/lib/things/document.rb +38 -0
- data/lib/things/focus.rb +63 -0
- data/lib/things/task.rb +129 -0
- data/lib/things/version.rb +9 -0
- data/test/fixtures/Database.xml +1318 -0
- data/test/test_document.rb +48 -0
- data/test/test_focus.rb +95 -0
- data/test/test_helper.rb +26 -0
- data/test/test_task.rb +118 -0
- data/things-rb.gemspec +34 -0
- metadata +85 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class DocumentTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@things = @@things ||= Things.new(:database => DATABASE_FIXTURE_PATH)
|
6
|
+
end
|
7
|
+
|
8
|
+
test "should use the specified database if any" do
|
9
|
+
IO.expects(:read).with('/path/to/database.xml').returns("foo").at_least_once
|
10
|
+
things = Things.new(:database => '/path/to/database.xml')
|
11
|
+
assert_equal('/path/to/database.xml', things.database_file)
|
12
|
+
end
|
13
|
+
|
14
|
+
test "should use default database unless other is specified" do
|
15
|
+
default_db = ENV['HOME'] + '/Library/Application Support/Cultured Code/Things/Database.xml'
|
16
|
+
IO.expects(:read).with(default_db).returns("foo").at_least_once
|
17
|
+
assert_equal(default_db, Things.new.database_file)
|
18
|
+
end
|
19
|
+
|
20
|
+
test "should return a parsed Hpricot document" do
|
21
|
+
IO.expects(:read).with('/my/db.xml').returns("foo").at_least_once
|
22
|
+
things = Things.new(:database => '/my/db.xml')
|
23
|
+
assert_equal("Hpricot::Doc", things.database.class.to_s)
|
24
|
+
assert_equal "foo", things.database.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
[:today, :inbox, :trash, :logbook, :next].each do |type|
|
28
|
+
test "should create a Focus instance for type #{type}" do
|
29
|
+
focus = @things.focus(type)
|
30
|
+
assert_instance_of(Things::Focus, focus)
|
31
|
+
end
|
32
|
+
|
33
|
+
test "should only create one Focus instance for #{type}" do
|
34
|
+
focus = @things.focus(type)
|
35
|
+
2.times { |i| assert_equal(focus, @things.focus(type)) }
|
36
|
+
end
|
37
|
+
|
38
|
+
test %Q{should have a shortcuts to the Focus "#{type}"} do
|
39
|
+
Things::Focus.any_instance.stubs(:tasks).returns(%[foo bar baz])
|
40
|
+
assert_equal(@things.focus(type).tasks, @things.send(type))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
test %Q{Should allow to send options to the focus today} do
|
45
|
+
completed = @things.today(:completed => true )
|
46
|
+
assert completed.all? { |e| e.title.include?("complete") }
|
47
|
+
end
|
48
|
+
end
|
data/test/test_focus.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class FocusTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@things = @@things ||= Things.new(:database => DATABASE_FIXTURE_PATH)
|
6
|
+
@todays_tasks = [
|
7
|
+
"complete today item",
|
8
|
+
"today item with notes",
|
9
|
+
"complete today item with notes",
|
10
|
+
"complete today item with a tag",
|
11
|
+
"today item with multiple tags",
|
12
|
+
"email bar",
|
13
|
+
"today item"
|
14
|
+
]
|
15
|
+
end
|
16
|
+
|
17
|
+
test 'should find the Today focus' do
|
18
|
+
assert_equal("z124", @things.focus(:today).id)
|
19
|
+
end
|
20
|
+
|
21
|
+
test "should find the focustype for Today" do
|
22
|
+
assert_equal("65536", @things.focus(:today).type_id)
|
23
|
+
end
|
24
|
+
|
25
|
+
test "should find the focuses" do
|
26
|
+
{ :inbox => "z120",
|
27
|
+
:trash => "z138",
|
28
|
+
:logbook => "z127",
|
29
|
+
:nextactions => "z141"
|
30
|
+
}.each do |name, id|
|
31
|
+
assert_equal(id, @things.focus(name).id)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
test 'should allow "next" as alias for NextActions focus' do
|
36
|
+
focus = Things::Focus.new(:next, stub(:at => ''))
|
37
|
+
assert_equal "FocusNextActions", focus.type_name
|
38
|
+
end
|
39
|
+
|
40
|
+
test 'should allow "nextactions" as alias for NextActions focus' do
|
41
|
+
focus = Things::Focus.new(:nextactions, stub(:at => ''))
|
42
|
+
assert_equal "FocusNextActions", focus.type_name
|
43
|
+
end
|
44
|
+
|
45
|
+
test 'should allow "someday" as alias for Maybe focus' do
|
46
|
+
focus = Things::Focus.new(:someday, stub(:at => ''))
|
47
|
+
assert_equal "FocusMaybe", focus.type_name
|
48
|
+
end
|
49
|
+
|
50
|
+
test "should raise FocusNotFound if the focus isn't found" do
|
51
|
+
assert_raise(Things::InvalidFocus) { @things.focus(:invalid_focus) }
|
52
|
+
end
|
53
|
+
|
54
|
+
test "should find the same number of tasks as in Today" do
|
55
|
+
tasks = @things.focus(:today).tasks
|
56
|
+
assert_instance_of(Array, tasks)
|
57
|
+
assert_equal(7, tasks.length)
|
58
|
+
end
|
59
|
+
|
60
|
+
test "should find the tasks' titles" do
|
61
|
+
assert_equal(@todays_tasks.sort, @things.today.map(&:title).sort)
|
62
|
+
end
|
63
|
+
|
64
|
+
test "should sort the tasks by their position" do
|
65
|
+
# TODO: tasks with projects/parent have other sorting order but need to
|
66
|
+
# figure out how Things handles that. Therefore skip these tasks for now
|
67
|
+
todays_tasks = @todays_tasks.reject { |e| e == 'email bar' }
|
68
|
+
assert_equal(todays_tasks, @things.today.reject { |e| e.parent? }.map(&:title))
|
69
|
+
end
|
70
|
+
|
71
|
+
test "should only find completed tasks when passing :completed => true" do
|
72
|
+
complete = @things.focus(:today).tasks(:completed => true)
|
73
|
+
assert complete.all? { |e| e.title.include?("complete") }
|
74
|
+
end
|
75
|
+
|
76
|
+
test "should not include completed tasks when passing :completed => false" do
|
77
|
+
complete = @things.focus(:today).tasks(:completed => false)
|
78
|
+
assert !complete.all? { |e| e.title.include?("complete") }
|
79
|
+
end
|
80
|
+
|
81
|
+
test "include canceled tasks when passing :canceled => true" do
|
82
|
+
canceled = @things.focus(:next).tasks(:canceled => true)
|
83
|
+
assert canceled.all? { |e| e.title.include?("cancel") }
|
84
|
+
end
|
85
|
+
|
86
|
+
test "dont include canceled tasks when passing :canceled => false" do
|
87
|
+
canceled = @things.focus(:next).tasks(:canceled => false)
|
88
|
+
assert !canceled.all? { |e| e.title.include?("cancel") }
|
89
|
+
end
|
90
|
+
|
91
|
+
test "should not include projects when listing tasks" do
|
92
|
+
with_children = @things.focus(:next).tasks.select(&:children?)
|
93
|
+
assert_equal 0, with_children.length
|
94
|
+
end
|
95
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w".. lib things")
|
2
|
+
require "test/unit"
|
3
|
+
require "mocha"
|
4
|
+
|
5
|
+
class Test::Unit::TestCase
|
6
|
+
FIXTURES_PATH = File.expand_path(File.join(File.dirname(__FILE__), "fixtures")) unless defined?(FIXTURES_PATH)
|
7
|
+
DATABASE_FIXTURE_PATH = File.join(FIXTURES_PATH, 'Database.xml') unless defined?(DATABASE_FIXTURE_PATH)
|
8
|
+
|
9
|
+
def database_content
|
10
|
+
IO.read(DATABASE_FIXTURE_PATH)
|
11
|
+
end
|
12
|
+
|
13
|
+
# From Rails ActiveSupport::Testing::Declarative
|
14
|
+
def self.test(name, &block)
|
15
|
+
test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
|
16
|
+
defined = instance_method(test_name) rescue false
|
17
|
+
raise "#{test_name} is already defined in #{self}" if defined
|
18
|
+
if block_given?
|
19
|
+
define_method(test_name, &block)
|
20
|
+
else
|
21
|
+
define_method(test_name) do
|
22
|
+
flunk "No implementation provided for #{name}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/test/test_task.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TaskTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@things = @@things ||= Things.new(:database => DATABASE_FIXTURE_PATH)
|
6
|
+
end
|
7
|
+
|
8
|
+
def find_task(name)
|
9
|
+
title = {
|
10
|
+
:with_tags => 'today item with multiple tags',
|
11
|
+
:basic => 'today item',
|
12
|
+
:with_parent => 'email bar'
|
13
|
+
}[name]
|
14
|
+
@things.today.detect { |t| t.title == title }
|
15
|
+
end
|
16
|
+
|
17
|
+
def task_with_children
|
18
|
+
task_by_id("z154")
|
19
|
+
end
|
20
|
+
|
21
|
+
def task_by_id(id)
|
22
|
+
node = @things.database.at("object[@type='TODO']##{id}")
|
23
|
+
Things::Task.new(node, @things.database)
|
24
|
+
end
|
25
|
+
|
26
|
+
test "should use the task's title for to_s" do
|
27
|
+
task = find_task(:basic)
|
28
|
+
assert_equal("today item", task.to_s)
|
29
|
+
end
|
30
|
+
|
31
|
+
test "should find the task's tag ids" do
|
32
|
+
task = find_task(:with_tags)
|
33
|
+
assert_instance_of Array, task.tag_ids
|
34
|
+
assert_equal %w[z151 z150].sort, task.tag_ids.sort
|
35
|
+
end
|
36
|
+
|
37
|
+
test "should not find any tags if there isnt any" do
|
38
|
+
assert_equal 0, find_task(:basic).tag_ids.length
|
39
|
+
end
|
40
|
+
|
41
|
+
test "should find the task's tag titles" do
|
42
|
+
task = find_task(:with_tags)
|
43
|
+
assert_equal(%w[Home City].sort, task.tags.sort)
|
44
|
+
end
|
45
|
+
|
46
|
+
test "should know if there are any tags" do
|
47
|
+
assert(find_task(:with_tags).tags?)
|
48
|
+
assert(!find_task(:basic).tags?)
|
49
|
+
end
|
50
|
+
|
51
|
+
test "if the task has a specific tag" do
|
52
|
+
task = find_task(:with_tags)
|
53
|
+
assert(task.tag?("Home"))
|
54
|
+
assert(!task.tag?("Errand"))
|
55
|
+
end
|
56
|
+
|
57
|
+
test "should find the tasks parent_id" do
|
58
|
+
task = find_task(:with_parent)
|
59
|
+
assert_equal("z154", task.parent_id)
|
60
|
+
end
|
61
|
+
|
62
|
+
test "should not find the task's parent project if it doesn't have any" do
|
63
|
+
task = find_task(:basic)
|
64
|
+
assert_equal(nil, task.parent_id)
|
65
|
+
end
|
66
|
+
|
67
|
+
test "should find the parent's title" do
|
68
|
+
task = find_task(:with_parent)
|
69
|
+
assert_equal "Make dinner", task.parent.title
|
70
|
+
end
|
71
|
+
|
72
|
+
test "should know if there is a parent project" do
|
73
|
+
assert(find_task(:with_parent).parent?)
|
74
|
+
assert(!find_task(:basic).parent?)
|
75
|
+
end
|
76
|
+
|
77
|
+
test "should know if the task is completed" do
|
78
|
+
@things.today.each do |task|
|
79
|
+
if task.title.include?('complete')
|
80
|
+
assert(task.complete?)
|
81
|
+
assert(!task.incompleted?)
|
82
|
+
else
|
83
|
+
assert(task.incompleted?)
|
84
|
+
assert(!task.completed?)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
test "if a task is canceled" do
|
90
|
+
assert task_by_id("z189").canceled?
|
91
|
+
end
|
92
|
+
|
93
|
+
test "should find the task's order index" do
|
94
|
+
assert_equal(7, find_task(:basic).position.to_i)
|
95
|
+
end
|
96
|
+
|
97
|
+
test "list the tasks children" do
|
98
|
+
assert_instance_of(Array, task_with_children.children)
|
99
|
+
end
|
100
|
+
|
101
|
+
test "find the right number of children" do
|
102
|
+
assert_equal(9, task_with_children.children.length)
|
103
|
+
end
|
104
|
+
|
105
|
+
test "know if there are child tasks" do
|
106
|
+
assert task_with_children.children?
|
107
|
+
assert !find_task(:basic).children?
|
108
|
+
end
|
109
|
+
|
110
|
+
test "populate the children array with Task objects" do
|
111
|
+
assert task_with_children.children.all? { |c| c.class == Things::Task }
|
112
|
+
end
|
113
|
+
|
114
|
+
test "find the children_ids" do
|
115
|
+
ids = %w[z163 z161 z160 z157 z159 z156 z165 z158 z162].sort
|
116
|
+
assert_equal(ids, task_with_children.children_ids.sort)
|
117
|
+
end
|
118
|
+
end
|
data/things-rb.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{things-rb}
|
5
|
+
s.version = "0.1.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Martin Str\303\266m"]
|
9
|
+
s.date = %q{2009-03-23}
|
10
|
+
s.default_executable = %q{things}
|
11
|
+
s.description = %q{Library and command-line tool for accessing Things.app databases}
|
12
|
+
s.email = %q{martin.strom@gmail.com}
|
13
|
+
s.executables = ["things"]
|
14
|
+
s.extra_rdoc_files = ["bin/things", "CHANGELOG", "lib/things/document.rb", "lib/things/focus.rb", "lib/things/task.rb", "lib/things/version.rb", "lib/things.rb", "LICENSE", "README.markdown"]
|
15
|
+
s.files = ["bin/things", "CHANGELOG", "lib/things/document.rb", "lib/things/focus.rb", "lib/things/task.rb", "lib/things/version.rb", "lib/things.rb", "LICENSE", "Manifest", "Rakefile", "README.markdown", "test/fixtures/Database.xml", "test/test_document.rb", "test/test_focus.rb", "test/test_helper.rb", "test/test_task.rb", "things-rb.gemspec"]
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.homepage = %q{http://github.com/haraldmartin/things-rb}
|
18
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Things-rb", "--main", "README.markdown"]
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.rubyforge_project = %q{things-rb}
|
21
|
+
s.rubygems_version = %q{1.3.1}
|
22
|
+
s.summary = %q{Library and command-line tool for accessing Things.app databases}
|
23
|
+
s.test_files = ["test/test_document.rb", "test/test_focus.rb", "test/test_helper.rb", "test/test_task.rb"]
|
24
|
+
|
25
|
+
if s.respond_to? :specification_version then
|
26
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
27
|
+
s.specification_version = 2
|
28
|
+
|
29
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
30
|
+
else
|
31
|
+
end
|
32
|
+
else
|
33
|
+
end
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: haraldmartin-things-rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "Martin Str\xC3\xB6m"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-03-23 00:00:00 -07:00
|
13
|
+
default_executable: things
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Library and command-line tool for accessing Things.app databases
|
17
|
+
email: martin.strom@gmail.com
|
18
|
+
executables:
|
19
|
+
- things
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- bin/things
|
24
|
+
- CHANGELOG
|
25
|
+
- lib/things/document.rb
|
26
|
+
- lib/things/focus.rb
|
27
|
+
- lib/things/task.rb
|
28
|
+
- lib/things/version.rb
|
29
|
+
- lib/things.rb
|
30
|
+
- LICENSE
|
31
|
+
- README.markdown
|
32
|
+
files:
|
33
|
+
- bin/things
|
34
|
+
- CHANGELOG
|
35
|
+
- lib/things/document.rb
|
36
|
+
- lib/things/focus.rb
|
37
|
+
- lib/things/task.rb
|
38
|
+
- lib/things/version.rb
|
39
|
+
- lib/things.rb
|
40
|
+
- LICENSE
|
41
|
+
- Manifest
|
42
|
+
- Rakefile
|
43
|
+
- README.markdown
|
44
|
+
- test/fixtures/Database.xml
|
45
|
+
- test/test_document.rb
|
46
|
+
- test/test_focus.rb
|
47
|
+
- test/test_helper.rb
|
48
|
+
- test/test_task.rb
|
49
|
+
- things-rb.gemspec
|
50
|
+
has_rdoc: true
|
51
|
+
homepage: http://github.com/haraldmartin/things-rb
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options:
|
54
|
+
- --line-numbers
|
55
|
+
- --inline-source
|
56
|
+
- --title
|
57
|
+
- Things-rb
|
58
|
+
- --main
|
59
|
+
- README.markdown
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
version:
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: "1.2"
|
73
|
+
version:
|
74
|
+
requirements: []
|
75
|
+
|
76
|
+
rubyforge_project: things-rb
|
77
|
+
rubygems_version: 1.2.0
|
78
|
+
signing_key:
|
79
|
+
specification_version: 2
|
80
|
+
summary: Library and command-line tool for accessing Things.app databases
|
81
|
+
test_files:
|
82
|
+
- test/test_document.rb
|
83
|
+
- test/test_focus.rb
|
84
|
+
- test/test_helper.rb
|
85
|
+
- test/test_task.rb
|