twdeps 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.travis.yml +15 -0
- data/Gemfile +4 -0
- data/Guardfile +12 -0
- data/LICENSE +22 -0
- data/README.md +56 -0
- data/Rakefile +10 -0
- data/bin/twdeps +59 -0
- data/examples/party.png +0 -0
- data/lib/twdeps/graph.rb +111 -0
- data/lib/twdeps/priority_mapper.rb +9 -0
- data/lib/twdeps/project.rb +33 -0
- data/lib/twdeps/project_presenter.rb +20 -0
- data/lib/twdeps/tag.rb +48 -0
- data/lib/twdeps/task.rb +52 -0
- data/lib/twdeps/task_mapper.rb +30 -0
- data/lib/twdeps/task_presenter.rb +28 -0
- data/lib/twdeps/task_repository.rb +77 -0
- data/lib/twdeps/version.rb +5 -0
- data/lib/twdeps.rb +22 -0
- data/test/fixtures/no_deps.json +7 -0
- data/test/fixtures/party.json +7 -0
- data/test/fixtures/party2.json +7 -0
- data/test/fixtures/party_taxes.json +10 -0
- data/test/helpers/plain_graph_parser.rb +68 -0
- data/test/integration/test_dependencies.rb +17 -0
- data/test/test_helper.rb +29 -0
- data/test/unit/test_graph.rb +51 -0
- data/test/unit/test_priority_mapper.rb +27 -0
- data/test/unit/test_project.rb +55 -0
- data/test/unit/test_repository.rb +64 -0
- data/test/unit/test_tag.rb +57 -0
- data/test/unit/test_tag_habtm.rb +69 -0
- data/test/unit/test_task.rb +121 -0
- data/twdeps.gemspec +28 -0
- metadata +240 -0
@@ -0,0 +1,7 @@
|
|
1
|
+
[{"id":1,"description":"Select a free weekend in November","entry":"20120629T191421Z","priority":"H","project":"party","status":"pending","uuid":"6fd0ba4a-ab67-49cd-ac69-64aa999aff8a","annotations":[{"entry":"20120629T191534Z","description":"the 13th looks good"}]},
|
2
|
+
{"id":2,"depends":["6fd0ba4a-ab67-49cd-ac69-64aa999aff8a"],"description":"Select and book a venue","entry":"20120629T191634Z","priority":"H","project":"party","status":"pending","uuid":"c992448a-f1ea-4982-8461-47f0705ff509"},
|
3
|
+
{"id":3,"depends":["9f6f3738-1c08-4f45-8eb4-1e90864c7588"],"description":"Mail invitations","entry":"20120629T191919Z","project":"party","status":"pending","uuid":"3b53178e-d5a4-45e0-afc2-1292db58a59a"},
|
4
|
+
{"id":4,"depends":["6fd0ba4a-ab67-49cd-ac69-64aa999aff8a","c992448a-f1ea-4982-8461-47f0705ff509"],"description":"Select a caterer","entry":"20120629T191919Z","project":"party","status":"pending","uuid":"c590941b-eb10-4569-bdc9-0e339f79305e"},
|
5
|
+
{"id":5,"depends":["c992448a-f1ea-4982-8461-47f0705ff509"],"description":"Design invitations","entry":"20120629T191919Z","priority":"H","project":"party","status":"pending","tags":["mall"],"uuid":"e5a867b7-0116-457d-ba43-9ac2bee6ad2a"},
|
6
|
+
{"id":6,"depends":["e5a867b7-0116-457d-ba43-9ac2bee6ad2a"],"description":"Print invitations","entry":"20120629T191920Z","project":"party","status":"pending","tags":["mall"],"uuid":"9f6f3738-1c08-4f45-8eb4-1e90864c7588"}
|
7
|
+
]
|
@@ -0,0 +1,10 @@
|
|
1
|
+
[{"id":1,"description":"Select a free weekend in November","entry":"20120629T191421Z","priority":"H","project":"party","status":"pending","uuid":"6fd0ba4a-ab67-49cd-ac69-64aa999aff8a","annotations":[{"entry":"20120629T191534Z","description":"the 13th looks good"}]},
|
2
|
+
{"id":2,"depends":"6fd0ba4a-ab67-49cd-ac69-64aa999aff8a","description":"Select and book a venue","entry":"20120629T191634Z","priority":"H","project":"party","status":"pending","uuid":"c992448a-f1ea-4982-8461-47f0705ff509"},
|
3
|
+
{"id":3,"depends":"9f6f3738-1c08-4f45-8eb4-1e90864c7588","description":"Mail invitations","entry":"20120629T191919Z","project":"party","status":"pending","uuid":"3b53178e-d5a4-45e0-afc2-1292db58a59a"},
|
4
|
+
{"id":4,"depends":"6fd0ba4a-ab67-49cd-ac69-64aa999aff8a,c992448a-f1ea-4982-8461-47f0705ff509","description":"Select a caterer","entry":"20120629T191919Z","project":"party","status":"pending","uuid":"c590941b-eb10-4569-bdc9-0e339f79305e"},
|
5
|
+
{"id":5,"depends":"c992448a-f1ea-4982-8461-47f0705ff509","description":"Design invitations","entry":"20120629T191919Z","priority":"H","project":"party","status":"pending","tags":["mall"],"uuid":"e5a867b7-0116-457d-ba43-9ac2bee6ad2a"},
|
6
|
+
{"id":6,"depends":"e5a867b7-0116-457d-ba43-9ac2bee6ad2a","description":"Print invitations","entry":"20120629T191920Z","project":"party","status":"pending","tags":["mall"],"uuid":"9f6f3738-1c08-4f45-8eb4-1e90864c7588"},
|
7
|
+
{"id":7,"description":"Pay taxes","due":"20130429T220000Z","entry":"20120630T092759Z","mask":"-","recur":"yearly","status":"recurring","uuid":"b587f364-c68e-4438-b4d6-f2af6ad62518"},
|
8
|
+
{"id":8,"description":"Pay taxes","due":"20130429T220000Z","entry":"20120630T092800Z","imask":"0","parent":"b587f364-c68e-4438-b4d6-f2af6ad62518","recur":"yearly","status":"pending","tags":["finance"],"uuid":"99c9e1bb-ed75-4525-b05d-cf153a7ee1a1"},
|
9
|
+
{"id":9,"description":"Get cash from ATM","entry":"20120702T130056Z","status":"pending","tags":["finance","mall"],"uuid":"67aafe0b-ddd7-482b-9cfa-ac42c43e7559"}
|
10
|
+
]
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module TaskWarrior
|
4
|
+
module Test
|
5
|
+
class Entry
|
6
|
+
def initialize(fields)
|
7
|
+
@fields = fields
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
attr_reader :fields
|
12
|
+
end
|
13
|
+
|
14
|
+
class Graph < Entry; end
|
15
|
+
class Stop < Entry; end
|
16
|
+
|
17
|
+
class Node < Entry
|
18
|
+
attr_reader :id
|
19
|
+
|
20
|
+
def initialize(fields)
|
21
|
+
@id = fields.shift
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
def label
|
26
|
+
fields[4]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Edge < Entry
|
31
|
+
attr_reader :from, :to
|
32
|
+
|
33
|
+
def initialize(fields)
|
34
|
+
@from = fields.shift
|
35
|
+
@to = fields.shift
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class PlainGraphParser
|
40
|
+
def initialize(lines)
|
41
|
+
@bucket = Hash.new{|hash, key| hash[key] = Array.new}
|
42
|
+
|
43
|
+
lines.each_line{|line|
|
44
|
+
CSV.parse(line, :quote_char => '"', :col_sep => ' ') do |fields|
|
45
|
+
o = TaskWarrior::Test.const_get(fields.shift.capitalize).new(fields)
|
46
|
+
@bucket[o.class] << o
|
47
|
+
end
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def edges
|
52
|
+
@bucket[Edge]
|
53
|
+
end
|
54
|
+
|
55
|
+
def nodes
|
56
|
+
@bucket[Node]
|
57
|
+
end
|
58
|
+
|
59
|
+
def node(id)
|
60
|
+
@bucket[Node].select{|node| id == node.id}.first
|
61
|
+
end
|
62
|
+
|
63
|
+
def edge(from, to)
|
64
|
+
@bucket[Edge].select{|edge| from == edge.from && to == edge.to}.first
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class DependencyTest < TaskWarrior::Test::Integration::TestCase
|
4
|
+
include TaskWarrior::Test::Fixtures
|
5
|
+
|
6
|
+
def test_no_dependencies
|
7
|
+
task("import #{fixture('no_deps.json')}")
|
8
|
+
tasks = export_tasks
|
9
|
+
assert_equal(6, tasks.size)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_full_dependencies
|
13
|
+
task("import #{fixture('party.json')}")
|
14
|
+
tasks = export_tasks
|
15
|
+
assert_equal(6, tasks.size)
|
16
|
+
end
|
17
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'twtest'
|
2
|
+
require 'twdeps'
|
3
|
+
require 'helpers/plain_graph_parser.rb'
|
4
|
+
|
5
|
+
module TaskWarrior
|
6
|
+
module Test
|
7
|
+
module Fixtures
|
8
|
+
def fixture(name)
|
9
|
+
File.join(File.dirname(__FILE__), 'fixtures', name)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Validations
|
14
|
+
def assert_valid(task)
|
15
|
+
assert(task.valid?, error_message(task.errors))
|
16
|
+
end
|
17
|
+
|
18
|
+
def assert_invalid(task)
|
19
|
+
assert(task.invalid?, 'Expect validation to fail')
|
20
|
+
end
|
21
|
+
|
22
|
+
def error_message(errors)
|
23
|
+
errors.each_with_object([]){|e, result|
|
24
|
+
result << e.join(' ')
|
25
|
+
}.join("\n")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module TaskWarrior
|
4
|
+
module Test
|
5
|
+
class TestGraph < ::Test::Unit::TestCase
|
6
|
+
include TaskWarrior::Test::Fixtures
|
7
|
+
|
8
|
+
def setup
|
9
|
+
repo = TaskWarrior::Repository.new(File.read(fixture('party_taxes.json')))
|
10
|
+
|
11
|
+
plain = TaskWarrior::Dependencies::Graph.new
|
12
|
+
|
13
|
+
repo.tasks.each do |task|
|
14
|
+
plain << task
|
15
|
+
end
|
16
|
+
|
17
|
+
@graph = TaskWarrior::Test::PlainGraphParser.new(plain.render(:plain))
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_nodes
|
21
|
+
assert_equal(8, @graph.nodes.size)
|
22
|
+
|
23
|
+
assert_node("6fd0ba4a-ab67-49cd-ac69-64aa999aff8a", "Select a free weekend in November")
|
24
|
+
assert_node("c992448a-f1ea-4982-8461-47f0705ff509", "Select and book a venue")
|
25
|
+
assert_node("3b53178e-d5a4-45e0-afc2-1292db58a59a", "Mail invitations")
|
26
|
+
assert_node("9f6f3738-1c08-4f45-8eb4-1e90864c7588", "Print invitations")
|
27
|
+
assert_node("e5a867b7-0116-457d-ba43-9ac2bee6ad2a", "Design invitations")
|
28
|
+
assert_node("c590941b-eb10-4569-bdc9-0e339f79305e", "Select a caterer")
|
29
|
+
assert_node("b587f364-c68e-4438-b4d6-f2af6ad62518", "Pay taxes")
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_edges
|
33
|
+
assert_equal(6, @graph.edges.size)
|
34
|
+
assert_not_nil(@graph.edge('c992448a-f1ea-4982-8461-47f0705ff509', '6fd0ba4a-ab67-49cd-ac69-64aa999aff8a'))
|
35
|
+
assert_not_nil(@graph.edge('3b53178e-d5a4-45e0-afc2-1292db58a59a', '9f6f3738-1c08-4f45-8eb4-1e90864c7588'))
|
36
|
+
assert_not_nil(@graph.edge('9f6f3738-1c08-4f45-8eb4-1e90864c7588', 'e5a867b7-0116-457d-ba43-9ac2bee6ad2a'))
|
37
|
+
assert_not_nil(@graph.edge('e5a867b7-0116-457d-ba43-9ac2bee6ad2a', 'c992448a-f1ea-4982-8461-47f0705ff509'))
|
38
|
+
assert_not_nil(@graph.edge('c590941b-eb10-4569-bdc9-0e339f79305e', '6fd0ba4a-ab67-49cd-ac69-64aa999aff8a'))
|
39
|
+
assert_not_nil(@graph.edge('c590941b-eb10-4569-bdc9-0e339f79305e', 'c992448a-f1ea-4982-8461-47f0705ff509'))
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
def assert_node(id, label)
|
44
|
+
node = @graph.node(id)
|
45
|
+
assert_not_nil(node)
|
46
|
+
assert_equal(id, node.id)
|
47
|
+
assert_equal(label, node.label)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestPriorityMapper < Test::Unit::TestCase
|
4
|
+
def test_nil
|
5
|
+
assert_nil(TaskWarrior::PriorityMapper.map(nil))
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_empty
|
9
|
+
assert_nil(TaskWarrior::PriorityMapper.map(''))
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_low
|
13
|
+
assert_equal(:low, TaskWarrior::PriorityMapper.map('L'))
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_medium
|
17
|
+
assert_equal(:medium, TaskWarrior::PriorityMapper.map('M'))
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_high
|
21
|
+
assert_equal(:high, TaskWarrior::PriorityMapper.map('H'))
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_unknown
|
25
|
+
assert_nil(TaskWarrior::PriorityMapper.map('crap'))
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestProject < Test::Unit::TestCase
|
4
|
+
include TaskWarrior::Test::Validations
|
5
|
+
|
6
|
+
def test_name
|
7
|
+
project = TaskWarrior::Project.new('foo')
|
8
|
+
assert_valid(project)
|
9
|
+
assert_empty(project.tasks)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_empty_tasks
|
13
|
+
project = TaskWarrior::Project.new('foo', [])
|
14
|
+
assert_valid(project)
|
15
|
+
assert_empty(project.tasks)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_with_tasks
|
19
|
+
project = TaskWarrior::Project.new('foo', [TaskWarrior::Task.new('foobar')])
|
20
|
+
assert_valid(project)
|
21
|
+
assert_equal(1, project.tasks.size)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_name_nil
|
25
|
+
project = TaskWarrior::Project.new(nil)
|
26
|
+
assert_invalid(project)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_name_empty
|
30
|
+
project = TaskWarrior::Project.new('')
|
31
|
+
assert_invalid(project)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_name_with_space
|
35
|
+
project = TaskWarrior::Project.new('foo bar')
|
36
|
+
assert_invalid(project)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_name_just_space
|
40
|
+
project = TaskWarrior::Project.new(' ')
|
41
|
+
assert_invalid(project)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_add_task
|
45
|
+
project = TaskWarrior::Project.new('foo')
|
46
|
+
assert_empty(project.tasks)
|
47
|
+
t1 = TaskWarrior::Task.new('foobar')
|
48
|
+
t2 = TaskWarrior::Task.new('foobaz')
|
49
|
+
project << t1
|
50
|
+
project << t2
|
51
|
+
assert_equal(2, project.tasks.size)
|
52
|
+
assert_equal(project, t1.project)
|
53
|
+
assert_equal(project, t2.project)
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestRepository < Test::Unit::TestCase
|
4
|
+
include TaskWarrior
|
5
|
+
include TaskWarrior::Test::Fixtures
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@repo = Repository.new(File.read(fixture('party_taxes.json')))
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_tags_of_task
|
12
|
+
atm = @repo['67aafe0b-ddd7-482b-9cfa-ac42c43e7559']
|
13
|
+
assert_not_nil(atm)
|
14
|
+
assert_equal(2, atm.tags.size)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_all
|
18
|
+
assert_equal(8, @repo.tasks.size)
|
19
|
+
|
20
|
+
one = @repo['6fd0ba4a-ab67-49cd-ac69-64aa999aff8a']
|
21
|
+
assert_equal('Select a free weekend in November', one.description)
|
22
|
+
assert_equal(:high, one.priority)
|
23
|
+
assert_equal('party', one.project.name)
|
24
|
+
assert_equal(:pending, one.status)
|
25
|
+
|
26
|
+
# assert_equal(1, one.annotations.size)
|
27
|
+
# assert_equal(DateTime.new('20120629T191534Z'), one.annotations.first.entry)
|
28
|
+
# assert_equal('the 13th looks good', one.annotations.first.entry.description)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_child
|
32
|
+
assert_equal(1, @repo['b587f364-c68e-4438-b4d6-f2af6ad62518'].children.size)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_parent
|
36
|
+
assert_equal(@repo['b587f364-c68e-4438-b4d6-f2af6ad62518'], @repo['99c9e1bb-ed75-4525-b05d-cf153a7ee1a1'].parent)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_projects
|
40
|
+
party = @repo.project('party')
|
41
|
+
assert_not_nil(party)
|
42
|
+
assert_equal(6, party.tasks.size)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_tags
|
46
|
+
tags = @repo.tags
|
47
|
+
assert_not_nil(tags)
|
48
|
+
assert_equal(2, tags.size)
|
49
|
+
assert(tags.include?(Tag.new('finance')))
|
50
|
+
assert(tags.include?(Tag.new('mall')))
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_tasks_of_tag_finance
|
54
|
+
finance = @repo.tag('finance')
|
55
|
+
assert_not_nil(finance)
|
56
|
+
assert_equal(2, finance.tasks.size)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_tasks_of_tag_mall
|
60
|
+
mall = @repo.tag('mall')
|
61
|
+
assert_not_nil(mall)
|
62
|
+
assert_equal(3, mall.tasks.size)
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestTag < Test::Unit::TestCase
|
4
|
+
include TaskWarrior
|
5
|
+
include TaskWarrior::Test::Validations
|
6
|
+
|
7
|
+
def test_name
|
8
|
+
tag = Tag.new('foo')
|
9
|
+
assert_valid(tag)
|
10
|
+
assert_empty(tag.tasks)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_empty_tasks
|
14
|
+
tag = Tag.new('foo', [])
|
15
|
+
assert_valid(tag)
|
16
|
+
assert_empty(tag.tasks)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_with_tasks
|
20
|
+
tag = Tag.new('foo', [Task.new('foobar')])
|
21
|
+
assert_valid(tag)
|
22
|
+
assert_equal(1, tag.tasks.size)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_name_nil
|
26
|
+
tag = Tag.new(nil)
|
27
|
+
assert_invalid(tag)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_name_empty
|
31
|
+
tag = Tag.new('')
|
32
|
+
assert_invalid(tag)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_name_with_space
|
36
|
+
tag = Tag.new('foo bar')
|
37
|
+
assert_invalid(tag)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_name_just_space
|
41
|
+
tag = Tag.new(' ')
|
42
|
+
assert_invalid(tag)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_construction
|
46
|
+
foo = Tag.new('foo')
|
47
|
+
assert_equal(foo, Tag.new(foo))
|
48
|
+
assert_equal(Tag.new(foo), foo)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_value_object
|
52
|
+
f1 = Tag.new('foo')
|
53
|
+
f2 = Tag.new('foo')
|
54
|
+
assert_not_equal(f1.object_id, f2.object_id)
|
55
|
+
assert_equal(f1, f2)
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestTagHasAndBelongsToMany < Test::Unit::TestCase
|
4
|
+
include TaskWarrior::Test::Validations
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@lookup_foo = TaskWarrior::Task.new('Lookup foo in Wikipedia')
|
8
|
+
@lookup_deadbeef = TaskWarrior::Task.new('Lookup deadbeef in Wikipedia')
|
9
|
+
|
10
|
+
@foo = TaskWarrior::Tag.new('foo')
|
11
|
+
@deadbeef = TaskWarrior::Tag.new('deadbeef')
|
12
|
+
@metasyntactic = TaskWarrior::Tag.new('metasyntactic')
|
13
|
+
|
14
|
+
# We need to do what the repo does - cross-reference manually.
|
15
|
+
@foo << @lookup_foo
|
16
|
+
@lookup_foo.tags << @foo
|
17
|
+
@lookup_foo.tags << @metasyntactic
|
18
|
+
|
19
|
+
@deadbeef << @lookup_deadbeef
|
20
|
+
@lookup_deadbeef.tags << @deadbeef
|
21
|
+
@lookup_deadbeef.tags << @metasyntactic
|
22
|
+
|
23
|
+
@metasyntactic << @lookup_foo
|
24
|
+
@metasyntactic << @lookup_deadbeef
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_task_tagged
|
28
|
+
assert_equal(2, @lookup_foo.tags.size)
|
29
|
+
assert_equal(2, @lookup_deadbeef.tags.size)
|
30
|
+
|
31
|
+
assert_tagged_with(@lookup_foo, @foo)
|
32
|
+
assert_tagged_with(@lookup_foo, @metasyntactic)
|
33
|
+
assert_not_tagged_with(@lookup_foo, @deadbeef)
|
34
|
+
|
35
|
+
assert_not_tagged_with(@lookup_deadbeef, @foo)
|
36
|
+
assert_tagged_with(@lookup_deadbeef, @metasyntactic)
|
37
|
+
assert_tagged_with(@lookup_deadbeef, @deadbeef)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_tag_has_tasks
|
41
|
+
assert_equal(1, @foo.tasks.size)
|
42
|
+
assert_equal(1, @deadbeef.tasks.size)
|
43
|
+
assert_equal(2, @metasyntactic.tasks.size)
|
44
|
+
|
45
|
+
assert_contains_task(@deadbeef, @lookup_deadbeef)
|
46
|
+
assert_not_contains_task(@deadbeef, @lookup_foo)
|
47
|
+
assert_not_contains_task(@foo, @lookup_deadbeef)
|
48
|
+
assert_contains_task(@foo, @lookup_foo)
|
49
|
+
|
50
|
+
assert_contains_task(@metasyntactic, @lookup_deadbeef)
|
51
|
+
assert_contains_task(@metasyntactic, @lookup_foo)
|
52
|
+
end
|
53
|
+
|
54
|
+
def assert_tagged_with(task, tag)
|
55
|
+
assert(task.tags.include?(tag), "#{task} expected to be tagged with #{tag}, but it isn't.'")
|
56
|
+
end
|
57
|
+
|
58
|
+
def assert_not_tagged_with(task, tag)
|
59
|
+
assert(!task.tags.include?(tag), "#{task} expected not to be tagged with #{tag}, but it actually is.")
|
60
|
+
end
|
61
|
+
|
62
|
+
def assert_contains_task(tag, task)
|
63
|
+
assert(tag.tasks.include?(task), "#{tag} expected to contain #{task}, but it doesn't.")
|
64
|
+
end
|
65
|
+
|
66
|
+
def assert_not_contains_task(tag, task)
|
67
|
+
assert(!tag.tasks.include?(task), "#{tag} expected to not contain #{task}, but it actually does.")
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'date'
|
3
|
+
require 'active_support/core_ext'
|
4
|
+
|
5
|
+
# TODO Add tests for dependencies
|
6
|
+
|
7
|
+
class TestTask < Test::Unit::TestCase
|
8
|
+
include TaskWarrior::Test::Validations
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@task = TaskWarrior::Task.new('foobar')
|
12
|
+
@task.id = 1
|
13
|
+
@task.uuid = '66465716-b08d-41ea-8567-91b988a2bcbf'
|
14
|
+
@task.entry = DateTime.now
|
15
|
+
@task.status = :pending
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_task_id_nil
|
19
|
+
@task.id = nil
|
20
|
+
assert_invalid(@task)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_task_id_0
|
24
|
+
@task.id = 0
|
25
|
+
assert_invalid(@task)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_task_uuid_nil
|
29
|
+
@task.uuid = nil
|
30
|
+
assert_invalid(@task)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_task_uuid_empty
|
34
|
+
@task.uuid = ''
|
35
|
+
assert_invalid(@task)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_task_uuid_wrong_format
|
39
|
+
@task.uuid = 'abcdefg'
|
40
|
+
assert_invalid(@task)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_task_entry_nil
|
44
|
+
@task.entry = nil
|
45
|
+
assert_invalid(@task)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_task_entry_empty
|
49
|
+
@task.entry = ''
|
50
|
+
assert_invalid(@task)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_task_entry_wrong_format
|
54
|
+
@task.entry = "foobar"
|
55
|
+
assert_invalid(@task)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_task_entry_future
|
59
|
+
@task.entry = DateTime.now.advance(:days => 1)
|
60
|
+
assert_invalid(@task)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_task_status_nil
|
64
|
+
@task.status = nil
|
65
|
+
assert_invalid(@task)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_task_status_empty
|
69
|
+
@task.status = ''
|
70
|
+
assert_invalid(@task)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_task_status_unknown_string
|
74
|
+
@task.status = "foobar"
|
75
|
+
assert_invalid(@task)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_task_status_unknown_symbol
|
79
|
+
@task.status = :foobar
|
80
|
+
assert_invalid(@task)
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_task_priority_nil
|
84
|
+
@task.priority = nil
|
85
|
+
assert_valid(@task)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_task_priority_empty
|
89
|
+
@task.priority = ''
|
90
|
+
assert_valid(@task)
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_task_priority_unknown_string
|
94
|
+
@task.priority = "foobar"
|
95
|
+
assert_invalid(@task)
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_task_priority_unknown_symbol
|
99
|
+
@task.priority = :foobar
|
100
|
+
assert_invalid(@task)
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_task_priority_high
|
104
|
+
@task.priority = :high
|
105
|
+
assert_valid(@task)
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_task_priority_medium
|
109
|
+
@task.priority = :medium
|
110
|
+
assert_valid(@task)
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_task_priority_low
|
114
|
+
@task.priority = :low
|
115
|
+
assert_valid(@task)
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_task_valid
|
119
|
+
assert_valid(@task)
|
120
|
+
end
|
121
|
+
end
|
data/twdeps.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/twdeps/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Nicholas E. Rabenau"]
|
6
|
+
gem.email = ["nerab@gmx.net"]
|
7
|
+
gem.description = %q{Takes a TaskWarrior export and emits a graph that visualizes the dependencies between tasks.}
|
8
|
+
gem.summary = %q{Visualizes dependencies between TaskWarrior tasks.}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "twdeps"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = TaskWarrior::Dependencies::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency 'ruby-graphviz', '~> 1.0.7'
|
19
|
+
gem.add_dependency 'activemodel', '~> 3.2'
|
20
|
+
gem.add_dependency 'trollop', '~> 1'
|
21
|
+
gem.add_development_dependency 'activesupport', '~> 3.2'
|
22
|
+
gem.add_development_dependency 'twtest', '~> 0.0.4'
|
23
|
+
gem.add_development_dependency 'guard-test', '~> 0.5'
|
24
|
+
gem.add_development_dependency 'guard-bundler', '~> 1.0'
|
25
|
+
gem.add_development_dependency 'rake', '~> 0.9'
|
26
|
+
|
27
|
+
gem.add_development_dependency 'pry'
|
28
|
+
end
|