twdeps 0.0.2
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.
- 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
|