things-rb 0.3.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.
@@ -0,0 +1,59 @@
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, :scheduled].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
+
49
+ [Things, Things::Document].each do |klass|
50
+ test "should allow a block for #{klass}.new" do
51
+ block = false
52
+ klass.new(:database => DATABASE_FIXTURE_PATH) do |d|
53
+ block = true
54
+ assert_instance_of(Things::Document, d)
55
+ end
56
+ assert(block)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,96 @@
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
+ "today item with content (notes)"
15
+ ]
16
+ end
17
+
18
+ test 'should find the Today focus' do
19
+ assert_equal("z124", @things.focus(:today).id)
20
+ end
21
+
22
+ test "should find the focustype for Today" do
23
+ assert_equal("65536", @things.focus(:today).type_id)
24
+ end
25
+
26
+ test "should find the focuses" do
27
+ { :inbox => "z120",
28
+ :trash => "z138",
29
+ :logbook => "z127",
30
+ :nextactions => "z141"
31
+ }.each do |name, id|
32
+ assert_equal(id, @things.focus(name).id)
33
+ end
34
+ end
35
+
36
+ test 'should allow "next" as alias for NextActions focus' do
37
+ focus = Things::Focus.new(:next, stub(:at => ''))
38
+ assert_equal "FocusNextActions", focus.type_name
39
+ end
40
+
41
+ test 'should allow "nextactions" as alias for NextActions focus' do
42
+ focus = Things::Focus.new(:nextactions, stub(:at => ''))
43
+ assert_equal "FocusNextActions", focus.type_name
44
+ end
45
+
46
+ test 'should allow "someday" as alias for Maybe focus' do
47
+ focus = Things::Focus.new(:someday, stub(:at => ''))
48
+ assert_equal "FocusMaybe", focus.type_name
49
+ end
50
+
51
+ test "should raise FocusNotFound if the focus isn't found" do
52
+ assert_raise(Things::InvalidFocus) { @things.focus(:invalid_focus) }
53
+ end
54
+
55
+ test "should find the same number of tasks as in Today" do
56
+ tasks = @things.focus(:today).tasks
57
+ assert_instance_of(Array, tasks)
58
+ assert_equal(8, tasks.length)
59
+ end
60
+
61
+ test "should find the tasks' titles" do
62
+ assert_equal(@todays_tasks.sort, @things.today.map(&:title).sort)
63
+ end
64
+
65
+ test "should sort the tasks by their position" do
66
+ # TODO: tasks with projects/parent have other sorting order but need to
67
+ # figure out how Things handles that. Therefore skip these tasks for now
68
+ todays_tasks = @todays_tasks.reject { |e| e == 'email bar' }
69
+ assert_equal(todays_tasks, @things.today.reject { |e| e.parent? }.map(&:title))
70
+ end
71
+
72
+ test "should only find completed tasks when passing :completed => true" do
73
+ complete = @things.focus(:today).tasks(:completed => true)
74
+ assert complete.all? { |e| e.title.include?("complete") }
75
+ end
76
+
77
+ test "should not include completed tasks when passing :completed => false" do
78
+ complete = @things.focus(:today).tasks(:completed => false)
79
+ assert !complete.all? { |e| e.title.include?("complete") }
80
+ end
81
+
82
+ test "include canceled tasks when passing :canceled => true" do
83
+ canceled = @things.focus(:next).tasks(:canceled => true)
84
+ assert canceled.all? { |e| e.title.include?("cancel") }
85
+ end
86
+
87
+ test "dont include canceled tasks when passing :canceled => false" do
88
+ canceled = @things.focus(:next).tasks(:canceled => false)
89
+ assert !canceled.all? { |e| e.title.include?("cancel") }
90
+ end
91
+
92
+ test "should not include projects when listing tasks" do
93
+ with_children = @things.focus(:next).tasks.select(&:children?)
94
+ assert_equal 0, with_children.length
95
+ end
96
+ end
@@ -0,0 +1,26 @@
1
+ require "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,163 @@
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
+ :with_notes => 'today item with content (notes)',
14
+ }[name]
15
+ @things.today.detect { |t| t.title == title }
16
+ end
17
+
18
+ def task_with_children
19
+ task_by_id("z154")
20
+ end
21
+
22
+ def task_by_id(id)
23
+ node = @things.database.at("object[@type='TODO']##{id}")
24
+ Things::Task.new(node, @things.database)
25
+ end
26
+
27
+ test "should use the task's title for to_s" do
28
+ task = find_task(:basic)
29
+ assert_equal("today item", task.to_s)
30
+ end
31
+
32
+ test "should find the task's tag ids" do
33
+ task = find_task(:with_tags)
34
+ assert_instance_of Array, task.tag_ids
35
+ assert_equal %w[z151 z150].sort, task.tag_ids.sort
36
+ end
37
+
38
+ test "should not find any tags if there isnt any" do
39
+ assert_equal 0, find_task(:basic).tag_ids.length
40
+ end
41
+
42
+ test "should find the task's notes" do
43
+ task = find_task(:with_notes)
44
+ assert_equal %{Check wait times here: http://www.mass.gov/qrmv/boston.shtm}, task.notes
45
+ end
46
+
47
+ test "should know if there are notes" do
48
+ assert find_task(:with_notes).notes?
49
+ assert !find_task(:basic).notes?
50
+ end
51
+
52
+ test "should find the task's tag titles" do
53
+ task = find_task(:with_tags)
54
+ assert_equal(%w[Home City].sort, task.tags.sort)
55
+ end
56
+
57
+ test "should know if there are any tags" do
58
+ assert(find_task(:with_tags).tags?)
59
+ assert(!find_task(:basic).tags?)
60
+ end
61
+
62
+ test "if the task has a specific tag" do
63
+ task = find_task(:with_tags)
64
+ assert(task.tag?("Home"))
65
+ assert(!task.tag?("Errand"))
66
+ end
67
+
68
+ test "should find the tasks parent_id" do
69
+ task = find_task(:with_parent)
70
+ assert_equal("z154", task.parent_id)
71
+ end
72
+
73
+ test "should not find the task's parent project if it doesn't have any" do
74
+ task = find_task(:basic)
75
+ assert_equal(nil, task.parent_id)
76
+ end
77
+
78
+ test "should find the parent's title" do
79
+ task = find_task(:with_parent)
80
+ assert_equal "Make dinner", task.parent.title
81
+ end
82
+
83
+ test "should know if there is a parent project" do
84
+ assert(find_task(:with_parent).parent?)
85
+ assert(!find_task(:basic).parent?)
86
+ end
87
+
88
+ test "should know if the task is completed" do
89
+ @things.today.each do |task|
90
+ if task.title.include?('complete')
91
+ assert(task.complete?)
92
+ assert(!task.incompleted?)
93
+ else
94
+ assert(task.incompleted?)
95
+ assert(!task.completed?)
96
+ end
97
+ end
98
+ end
99
+
100
+ test "if a task is canceled" do
101
+ assert task_by_id("z189").canceled?
102
+ end
103
+
104
+ test "should find the task's order index" do
105
+ assert_equal(7, find_task(:basic).position.to_i)
106
+ end
107
+
108
+ test "list the tasks children" do
109
+ assert_instance_of(Array, task_with_children.children)
110
+ end
111
+
112
+ test "find the right number of children" do
113
+ assert_equal(9, task_with_children.children.length)
114
+ end
115
+
116
+ test "know if there are child tasks" do
117
+ assert task_with_children.children?
118
+ assert !find_task(:basic).children?
119
+ end
120
+
121
+ test "populate the children array with Task objects" do
122
+ assert task_with_children.children.all? { |c| c.class == Things::Task }
123
+ end
124
+
125
+ test "find the children_ids" do
126
+ ids = %w[z163 z161 z160 z157 z159 z156 z165 z158 z162].sort
127
+ assert_equal(ids, task_with_children.children_ids.sort)
128
+ end
129
+
130
+ test "should find the due date" do
131
+ task = task_by_id("z186")
132
+ assert_equal "2009-08-01", task.due_date.strftime("%Y-%m-%d")
133
+ end
134
+
135
+ test "should know that the task is due" do
136
+ assert task_by_id("z186").due?
137
+ end
138
+
139
+ test "should know that the task is not due" do
140
+ Time.stubs(:now).returns(Time.parse('2009-07-31'))
141
+ assert !task_by_id("z186").due?
142
+ end
143
+
144
+ test "should not be due for a task without due date" do
145
+ assert !find_task(:basic).due?
146
+ end
147
+
148
+ test "should find the schedule date" do
149
+ scheduled = task_by_id("z166")
150
+ assert_equal "2019-03-20", scheduled.scheduled_date.strftime("%Y-%m-%d")
151
+ end
152
+
153
+ test "should know if a task i scheduled" do
154
+ assert task_by_id("z166").scheduled?
155
+ assert !find_task(:basic).scheduled?
156
+ end
157
+
158
+ test "each state should have a bullet" do
159
+ assert_equal "✓", task_by_id("z173").bullet # complete
160
+ assert_equal "×", task_by_id("z189").bullet # canceled
161
+ assert_equal "-", find_task(:basic).bullet # regular
162
+ end
163
+ end
data/things-rb.gemspec ADDED
@@ -0,0 +1,66 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{things-rb}
8
+ s.version = "0.3.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Martin Str\303\266m"]
12
+ s.date = %q{2010-01-20}
13
+ s.default_executable = %q{things}
14
+ s.description = %q{Library and command-line tool for accessing Things.app databases}
15
+ s.email = %q{name@my-domain.se}
16
+ s.executables = ["things"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.markdown"
20
+ ]
21
+ s.files = [
22
+ ".gitignore",
23
+ "CHANGELOG",
24
+ "LICENSE",
25
+ "README.markdown",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bin/things",
29
+ "lib/things.rb",
30
+ "lib/things/document.rb",
31
+ "lib/things/focus.rb",
32
+ "lib/things/task.rb",
33
+ "lib/things/version.rb",
34
+ "test/fixtures/Database.xml",
35
+ "test/test_document.rb",
36
+ "test/test_focus.rb",
37
+ "test/test_helper.rb",
38
+ "test/test_task.rb",
39
+ "things-rb.gemspec"
40
+ ]
41
+ s.homepage = %q{http://github.com/haraldmartin/things-rb}
42
+ s.rdoc_options = ["--charset=UTF-8"]
43
+ s.require_paths = ["lib"]
44
+ s.rubygems_version = %q{1.3.5}
45
+ s.summary = %q{Library and command-line tool for accessing Things.app databases}
46
+ s.test_files = [
47
+ "test/test_document.rb",
48
+ "test/test_focus.rb",
49
+ "test/test_helper.rb",
50
+ "test/test_task.rb"
51
+ ]
52
+
53
+ if s.respond_to? :specification_version then
54
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
55
+ s.specification_version = 3
56
+
57
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
58
+ s.add_runtime_dependency(%q<hpricot>, [">= 0"])
59
+ else
60
+ s.add_dependency(%q<hpricot>, [">= 0"])
61
+ end
62
+ else
63
+ s.add_dependency(%q<hpricot>, [">= 0"])
64
+ end
65
+ end
66
+
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: things-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - "Martin Str\xC3\xB6m"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-20 00:00:00 +01:00
13
+ default_executable: things
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hpricot
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: Library and command-line tool for accessing Things.app databases
26
+ email: name@my-domain.se
27
+ executables:
28
+ - things
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.markdown
34
+ files:
35
+ - .gitignore
36
+ - CHANGELOG
37
+ - LICENSE
38
+ - README.markdown
39
+ - Rakefile
40
+ - VERSION
41
+ - bin/things
42
+ - lib/things.rb
43
+ - lib/things/document.rb
44
+ - lib/things/focus.rb
45
+ - lib/things/task.rb
46
+ - lib/things/version.rb
47
+ - test/fixtures/Database.xml
48
+ - test/test_document.rb
49
+ - test/test_focus.rb
50
+ - test/test_helper.rb
51
+ - test/test_task.rb
52
+ - things-rb.gemspec
53
+ has_rdoc: true
54
+ homepage: http://github.com/haraldmartin/things-rb
55
+ licenses: []
56
+
57
+ post_install_message:
58
+ rdoc_options:
59
+ - --charset=UTF-8
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: "0"
73
+ version:
74
+ requirements: []
75
+
76
+ rubyforge_project:
77
+ rubygems_version: 1.3.5
78
+ signing_key:
79
+ specification_version: 3
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