paradeiser 0.2.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/Guardfile +1 -0
- data/README.md +98 -6
- data/TODO.md +22 -6
- data/VISION.md +171 -26
- data/bin/par +20 -4
- data/lib/paradeiser/controllers/breaks_controller.rb +0 -1
- data/lib/paradeiser/controllers/controller.rb +15 -1
- data/lib/paradeiser/controllers/paradeiser_controller.rb +23 -1
- data/lib/paradeiser/controllers/pomodori_controller.rb +23 -1
- data/lib/paradeiser/errors.rb +6 -0
- data/lib/paradeiser/executor.rb +1 -1
- data/lib/paradeiser/initializers/inflections.rb +3 -0
- data/lib/paradeiser/models/break.rb +1 -0
- data/lib/paradeiser/models/pomodoro.rb +13 -1
- data/lib/paradeiser/models/repository.rb +11 -1
- data/lib/paradeiser/models/scheduled.rb +7 -1
- data/lib/paradeiser/refinements/pluralize.rb +10 -0
- data/lib/paradeiser/router.rb +0 -2
- data/lib/paradeiser/version.rb +1 -1
- data/lib/paradeiser/view.rb +1 -1
- data/lib/paradeiser/views/breaks/finish.erb +1 -0
- data/lib/paradeiser/views/breaks/start.erb +1 -0
- data/lib/paradeiser/views/paradeiser/init.erb +1 -1
- data/lib/paradeiser/views/paradeiser/report.erb +10 -4
- data/lib/paradeiser/views/paradeiser/status.erb +2 -1
- data/lib/paradeiser/views/pomodori/annotate.erb +1 -0
- data/lib/paradeiser/views/pomodori/cancel.erb +1 -0
- data/lib/paradeiser/views/pomodori/interrupt.erb +1 -0
- data/lib/paradeiser/views/pomodori/log.erb +1 -0
- data/lib/paradeiser/views/pomodori/start.erb +1 -1
- data/paradeiser.gemspec +2 -0
- data/test/bin/notify-send +1 -0
- data/test/helper.rb +7 -24
- data/test/integration/test_annotate.rb +19 -0
- data/test/integration/test_finish.rb +9 -0
- data/test/integration/test_interrupt.rb +9 -0
- data/test/integration/test_log.rb +12 -0
- data/test/integration/test_no_args.rb +7 -0
- data/test/integration/test_start.rb +7 -0
- data/test/integration/test_status.rb +10 -0
- data/test/integration/test_unknown.rb +7 -0
- data/test/lib/at_mock.rb +1 -1
- data/test/lib/controller_test.rb +25 -0
- data/test/lib/integration_test.rb +45 -0
- data/test/lib/paradeiser_controller_test.rb +7 -0
- data/test/lib/view_test.rb +12 -0
- data/test/unit/test_break.rb +7 -44
- data/test/unit/test_break_view.rb +22 -0
- data/test/unit/test_breaks_controller.rb +66 -0
- data/test/unit/test_paradeiser_controller_export.rb +107 -0
- data/test/unit/test_paradeiser_controller_report.rb +73 -26
- data/test/unit/test_paradeiser_controller_status.rb +42 -24
- data/test/unit/test_paradeiser_view_init.rb +7 -0
- data/test/unit/test_paradeiser_view_report.rb +132 -0
- data/test/unit/test_paradeiser_view_status.rb +17 -0
- data/test/unit/test_pomodori_controller.rb +241 -33
- data/test/unit/test_pomodori_view.rb +26 -13
- data/test/unit/test_pomodoro.rb +23 -81
- data/test/unit/test_pomodoro_hooks.rb +12 -25
- data/test/unit/test_repository.rb +5 -21
- data/test/unit/test_scheduler.rb +1 -1
- metadata +61 -8
- data/test/integration/test_par.rb +0 -17
- data/test/unit/test_break_controller.rb +0 -56
- data/test/unit/test_paradeiser_view.rb +0 -66
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestAnnotateCommand < Paradeiser::IntegrationTest
|
4
|
+
def test_annotate_no_previous
|
5
|
+
refute_command('annotate')
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_annotate_active
|
9
|
+
assert_command('start')
|
10
|
+
assert_command('annotate', 0, name.split('_'))
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_annotate_second_last_successful
|
14
|
+
assert_command('start')
|
15
|
+
assert_command('finish')
|
16
|
+
assert_command('break')
|
17
|
+
assert_command('annotate', 0, name.split('_'))
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestStatusCommand < Paradeiser::IntegrationTest
|
4
|
+
def test_status
|
5
|
+
assert_command('status', 255) # not initialized
|
6
|
+
assert_command('start')
|
7
|
+
out = assert_command('status')
|
8
|
+
refute_empty(out, "Expected 'status' to produce an non-empty output")
|
9
|
+
end
|
10
|
+
end
|
data/test/lib/at_mock.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Paradeiser
|
2
|
+
class ControllerTest < MiniTest::Test
|
3
|
+
def invoke(method, args = nil, options = nil, *attributes)
|
4
|
+
controller = Paradeiser.const_get("#{model.pluralize.capitalize}Controller".to_sym).new(method)
|
5
|
+
|
6
|
+
stdout, stderr = Repository.stub :backend, @backend do
|
7
|
+
Scheduler.stub(:add, nil) do
|
8
|
+
Scheduler.stub(:clear, nil) do
|
9
|
+
capture_io do
|
10
|
+
controller.call(Array(args), options)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
result = Hash[attributes.map do |e|
|
17
|
+
[e.split('@').last.to_sym, controller.get_binding.eval(e)]
|
18
|
+
end]
|
19
|
+
|
20
|
+
result[:stdout] = stdout
|
21
|
+
result[:stderr] = stderr
|
22
|
+
result
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Paradeiser
|
4
|
+
#
|
5
|
+
# We put all integration tests into separate files so we only run one at a
|
6
|
+
# time after a change. These tests are expensive to run.
|
7
|
+
#
|
8
|
+
class IntegrationTest < MiniTest::Test
|
9
|
+
PAR = 'bin/par'
|
10
|
+
include Executor
|
11
|
+
|
12
|
+
def setup
|
13
|
+
if Scheduler.list.any?
|
14
|
+
@do_not_clear = true
|
15
|
+
raise "The at queue '#{queue}' is not empty. Clean it up before running this test again."
|
16
|
+
end
|
17
|
+
|
18
|
+
@orig_PAR_DIR = ENV['PAR_DIR']
|
19
|
+
ENV['PAR_DIR'] = Dir.mktmpdir
|
20
|
+
ENV['PAR_AT_QUEUE'] = 'i'
|
21
|
+
assert_command('init')
|
22
|
+
end
|
23
|
+
|
24
|
+
def teardown
|
25
|
+
FileUtils.rm_rf(Paradeiser.par_dir)
|
26
|
+
ENV['PAR_DIR'] = @orig_PAR_DIR
|
27
|
+
Scheduler.clear unless @do_not_clear
|
28
|
+
raise "The at queue #{queue} is not empty. Clean it up before running this test again." if Scheduler.list.any?
|
29
|
+
ENV.delete('PAR_AT_QUEUE')
|
30
|
+
end
|
31
|
+
|
32
|
+
def assert_command(cmd, expected_status = 0, *args)
|
33
|
+
out, err, status = Open3.capture3("#{PAR} #{cmd} #{Shellwords.join(args)}")
|
34
|
+
assert_equal(expected_status, status.exitstatus, "Expected exit status to be #{expected_status}, but it was #{status.exitstatus}. STDERR is: '#{err}'")
|
35
|
+
assert_empty(err)
|
36
|
+
out
|
37
|
+
end
|
38
|
+
|
39
|
+
def refute_command(cmd, expected_status = 1, *args)
|
40
|
+
out, err, status = Open3.capture3("#{PAR} #{cmd}")
|
41
|
+
assert_equal(expected_status, status.exitstatus, "Expected exit status to be #{expected_status}, but it was #{status.exitstatus}.")
|
42
|
+
[out, err]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/test/unit/test_break.rb
CHANGED
@@ -2,26 +2,14 @@ require 'helper'
|
|
2
2
|
|
3
3
|
class TestBreak < MiniTest::Test
|
4
4
|
def setup
|
5
|
-
@break = Break
|
5
|
+
@break = produce(Break)
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
9
|
-
assert_equal(:idle, @break.status_name)
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_break
|
13
|
-
start!
|
8
|
+
def test_new
|
14
9
|
assert_equal(:active, @break.status_name)
|
15
10
|
end
|
16
11
|
|
17
|
-
def test_finish_idle
|
18
|
-
assert_raises StateMachine::InvalidTransition do
|
19
|
-
finish!
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
12
|
def test_finish_break
|
24
|
-
start!
|
25
13
|
assert_equal(:active, @break.status_name)
|
26
14
|
|
27
15
|
now = srand
|
@@ -38,43 +26,25 @@ class TestBreak < MiniTest::Test
|
|
38
26
|
assert_equal(5 * 60, @break.length)
|
39
27
|
end
|
40
28
|
|
41
|
-
|
42
|
-
def test_duration_idle
|
43
|
-
assert_equal(0, @break.duration)
|
44
|
-
end
|
45
|
-
|
46
29
|
def test_duration
|
47
|
-
|
48
|
-
|
49
|
-
Time.stub :now, Time.at(now) do
|
50
|
-
start!
|
51
|
-
end
|
52
|
-
|
53
|
-
later = now + rand(42)
|
30
|
+
later = @started + rand(42)
|
54
31
|
|
55
32
|
Time.stub :now, Time.at(later) do
|
56
|
-
assert_equal(later -
|
33
|
+
assert_equal(later - @started, @break.duration)
|
57
34
|
end
|
58
35
|
end
|
59
36
|
|
60
37
|
def test_duration_finished
|
61
|
-
|
62
|
-
|
63
|
-
Time.stub :now, Time.at(now) do
|
64
|
-
start!
|
65
|
-
end
|
66
|
-
|
67
|
-
later = now + rand(42)
|
38
|
+
later = @started + rand(42)
|
68
39
|
|
69
40
|
Time.stub :now, Time.at(later) do
|
70
41
|
finish!
|
71
42
|
end
|
72
43
|
|
73
|
-
assert_equal(later -
|
44
|
+
assert_equal(later - @started, @break.duration)
|
74
45
|
end
|
75
46
|
|
76
47
|
def test_finish_break
|
77
|
-
start!
|
78
48
|
finish!
|
79
49
|
assert_raises StateMachine::InvalidTransition do
|
80
50
|
finish!
|
@@ -82,15 +52,8 @@ class TestBreak < MiniTest::Test
|
|
82
52
|
end
|
83
53
|
|
84
54
|
def test_remaining
|
85
|
-
now = srand
|
86
|
-
|
87
|
-
Time.stub :now, Time.at(now) do
|
88
|
-
start!
|
89
|
-
assert_equal(@break.length, @break.remaining)
|
90
|
-
end
|
91
|
-
|
92
55
|
delta = 120
|
93
|
-
later =
|
56
|
+
later = @started + delta
|
94
57
|
|
95
58
|
Time.stub :now, Time.at(later) do
|
96
59
|
assert_equal(@break.length - delta, @break.remaining)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestBreakView < ViewTest
|
4
|
+
def setup
|
5
|
+
@break = produce(Break)
|
6
|
+
@break.id = 1
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_start
|
10
|
+
assert_match(/^Started a new break \(5 minutes\)\.$/m, render(:start))
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_finish
|
14
|
+
assert_match(/^Finished break #1 after .* minutes\.$/m, render(:finish))
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def model
|
20
|
+
'Break'
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestBreaksController < ControllerTest
|
4
|
+
def setup
|
5
|
+
@backend = PStoreMock.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def model
|
9
|
+
'break'
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_break
|
13
|
+
attrs = invoke(:start, nil, nil, '@break', 'exitstatus', 'has_output')
|
14
|
+
assert_equal(:active, attrs[:break].status_name)
|
15
|
+
assert_equal(false, attrs[:has_output])
|
16
|
+
assert_empty(attrs[:stdout])
|
17
|
+
assert_empty(attrs[:stderr])
|
18
|
+
assert_equal(1, @backend.size)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_break_verbose
|
22
|
+
attrs = invoke(:start, nil, OpenStruct.new(:verbose => true), '@break', 'exitstatus', 'has_output')
|
23
|
+
assert_equal(:active, attrs[:break].status_name)
|
24
|
+
assert_equal(false, attrs[:has_output])
|
25
|
+
refute_empty(attrs[:stdout])
|
26
|
+
assert_empty(attrs[:stderr])
|
27
|
+
assert_equal(1, @backend.size)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_break_active
|
31
|
+
invoke(:start)
|
32
|
+
assert_equal(1, @backend.size)
|
33
|
+
|
34
|
+
assert_raises SingletonError do
|
35
|
+
invoke(:start)
|
36
|
+
end
|
37
|
+
assert_equal(1, @backend.size)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_finish
|
41
|
+
invoke(:start)
|
42
|
+
attrs = invoke(:finish, nil, nil, '@break', 'exitstatus', 'has_output')
|
43
|
+
assert_equal(:finished, attrs[:break].status_name)
|
44
|
+
assert_equal(false, attrs[:has_output])
|
45
|
+
assert_empty(attrs[:stdout])
|
46
|
+
assert_empty(attrs[:stderr])
|
47
|
+
assert_equal(1, @backend.size)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_finish_verbose
|
51
|
+
invoke(:start)
|
52
|
+
attrs = invoke(:finish, nil, OpenStruct.new(:verbose => true), '@break', 'exitstatus', 'has_output')
|
53
|
+
assert_equal(:finished, attrs[:break].status_name)
|
54
|
+
assert_equal(false, attrs[:has_output])
|
55
|
+
refute_empty(attrs[:stdout])
|
56
|
+
assert_empty(attrs[:stderr])
|
57
|
+
assert_equal(1, @backend.size)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_finish_idle
|
61
|
+
assert_raises NotActiveError do
|
62
|
+
invoke(:finish)
|
63
|
+
end
|
64
|
+
assert_equal(0, @backend.size)
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
#
|
4
|
+
# There is no view for export, so we need to test the entire results here
|
5
|
+
#
|
6
|
+
class TestParadeiserControllerExport < ParadeiserControllerTest
|
7
|
+
def setup
|
8
|
+
@backend = PStoreMock.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_empty
|
12
|
+
attrs = invoke(:export)
|
13
|
+
assert_empty(attrs[:stderr])
|
14
|
+
|
15
|
+
result = JSON.parse(attrs[:stdout])
|
16
|
+
assert(result)
|
17
|
+
assert_empty(result)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_pomodoro
|
21
|
+
pom = produce(Pomodoro)
|
22
|
+
started_at = Time.new(8)
|
23
|
+
pom.started_at = started_at
|
24
|
+
pom.finish!
|
25
|
+
finished_at = Time.new(16)
|
26
|
+
pom.finished_at = finished_at
|
27
|
+
@backend[:bar] = pom
|
28
|
+
|
29
|
+
attrs = invoke(:export)
|
30
|
+
assert_empty(attrs[:stderr])
|
31
|
+
result = JSON.parse(attrs[:stdout])
|
32
|
+
|
33
|
+
assert(result)
|
34
|
+
refute_empty(result)
|
35
|
+
assert_equal(1, result.size)
|
36
|
+
p = result.first
|
37
|
+
assert(p)
|
38
|
+
|
39
|
+
assert_equal('Pomodoro', p['type'])
|
40
|
+
assert_equal(1500, p['length'])
|
41
|
+
assert_equal('finished', p['status'])
|
42
|
+
assert_equal(started_at.as_json, p['started_at'])
|
43
|
+
assert_equal(finished_at.as_json, p['finished_at'])
|
44
|
+
|
45
|
+
interrupts = p['interrupts']
|
46
|
+
assert(interrupts)
|
47
|
+
assert_empty(interrupts)
|
48
|
+
|
49
|
+
annotations = p['annotations']
|
50
|
+
assert(annotations)
|
51
|
+
assert_empty(annotations)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_break
|
55
|
+
br3ak = produce(Break)
|
56
|
+
started_at = Time.new(8)
|
57
|
+
br3ak.started_at = started_at
|
58
|
+
br3ak.finish!
|
59
|
+
finished_at = Time.new(16)
|
60
|
+
br3ak.finished_at = finished_at
|
61
|
+
@backend[:bar] = br3ak
|
62
|
+
|
63
|
+
attrs = invoke(:export)
|
64
|
+
assert_empty(attrs[:stderr])
|
65
|
+
result = JSON.parse(attrs[:stdout])
|
66
|
+
|
67
|
+
assert(result)
|
68
|
+
refute_empty(result)
|
69
|
+
assert_equal(1, result.size)
|
70
|
+
p = result.first
|
71
|
+
assert(p)
|
72
|
+
|
73
|
+
assert_equal('Break', p['type'])
|
74
|
+
assert_equal(300, p['length'])
|
75
|
+
assert_equal('finished', p['status'])
|
76
|
+
assert_equal(started_at.as_json, p['started_at'])
|
77
|
+
assert_equal(finished_at.as_json, p['finished_at'])
|
78
|
+
|
79
|
+
refute(p['interrupts'])
|
80
|
+
refute(p['annotations'])
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_multiple
|
84
|
+
br3ak = produce(Break)
|
85
|
+
br3ak.started_at = Time.new(8)
|
86
|
+
br3ak.finish!
|
87
|
+
br3ak.finished_at = Time.new(16)
|
88
|
+
@backend[:bar] = br3ak
|
89
|
+
|
90
|
+
pom = produce(Pomodoro)
|
91
|
+
pom.started_at = Time.new(8)
|
92
|
+
pom.finish!
|
93
|
+
pom.finished_at = Time.new(16)
|
94
|
+
@backend[:foo] = pom
|
95
|
+
|
96
|
+
attrs = invoke(:export)
|
97
|
+
assert_empty(attrs[:stderr])
|
98
|
+
result = JSON.parse(attrs[:stdout])
|
99
|
+
|
100
|
+
assert(result)
|
101
|
+
refute_empty(result)
|
102
|
+
assert_equal(2, result.size)
|
103
|
+
|
104
|
+
assert_equal('Break', result.first['type'])
|
105
|
+
assert_equal('Pomodoro', result.last['type'])
|
106
|
+
end
|
107
|
+
end
|