checklist 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *~
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - jruby-18mode # JRuby in 1.8 mode
7
+ - jruby-19mode # JRuby in 1.9 mode
8
+ - rbx-18mode
9
+ - rbx-19mode
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ group "development" do
5
+ gem "pry"
6
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Maciej Pasternacki
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,15 @@
1
+
2
+ * Features I'd like to see
3
+ ** TODO Colorful console UI
4
+ - formatador gem
5
+ ** TODO Separate "verify" lambda to call
6
+ ** predefined steps & helper functions
7
+ *** TODO wait for user confirmation
8
+ *** TODO run a rake task
9
+ ** TODO "Retry" exception
10
+ ** TODO Checklist sections
11
+ ** Export checklists
12
+ *** TODO PDF
13
+ *** TODO HTML
14
+ *** TODO Active HTML (w/ JS to go through the checklist)
15
+ *** TODO http://checklist.foreflight.com/
@@ -0,0 +1,45 @@
1
+ # Checklist
2
+
3
+ Execute your tasks as checklist, get clear status of what has been
4
+ done and what has not on your terminal.
5
+
6
+ ![A screenshot is worth thousand words](http://cloud.github.com/downloads/3ofcoins/checklist/Terminal%20—%20zsh%20—%20157×40.jpg)
7
+
8
+ [![Build Status](https://secure.travis-ci.org/3ofcoins/checklist.png?branch=master)](http://travis-ci.org/3ofcoins/checklist)
9
+
10
+ ## More info
11
+
12
+ * [Code and home page at GitHub](https://github.com/3ofcoins/checklist)
13
+ * [Build status at Travis CI](http://travis-ci.org/3ofcoins/checklist)
14
+ * [API documentation at RubyDoc.info](http://rdoc.info/github/3ofcoins/checklist)
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ gem 'checklist'
21
+
22
+ And then execute:
23
+
24
+ $ bundle
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install checklist
29
+
30
+ ## Usage
31
+
32
+ For now, see the examples/ directory and test cases. More docs will follow.
33
+
34
+ ## Contributing
35
+
36
+ 1. Fork it
37
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
38
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
39
+ 4. Push to the branch (`git push origin my-new-feature`)
40
+ 5. Create new Pull Request
41
+
42
+ ## References
43
+
44
+ 1. Gawande, Atul (2009) [The Checklist Manifesto](http://gawande.com/the-checklist-manifesto) ISBN: 978-0805091784
45
+ 2. Degani, A., & Wiener, E. L. (1993). [Cockpit checklists: Concepts, design, and use.](http://ti.arc.nasa.gov/m/profile/adegani/Cockpit%20Checklists.pdf) Human Factors, 35(2), 345-359. (more: [Asaf Degani - Procedure Design](http://ti.arc.nasa.gov/profile/adegani/procedure-design/))
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ desc "Run specs"
5
+ RSpec::Core::RakeTask.new do |t|
6
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
7
+ end
8
+
9
+ task :default => :spec
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/checklist/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Maciej Pasternacki"]
6
+ gem.email = ["maciej@pasternacki.net"]
7
+ gem.description = 'Multi-step checklist execution'
8
+ gem.summary = 'Define and execute a checklist'
9
+ gem.homepage = "https://github.com/3ofcoins/checklist"
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 = "checklist"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Checklist::VERSION
17
+
18
+ gem.add_dependency "formatador"
19
+ gem.add_dependency "locale"
20
+ gem.add_dependency "must_be"
21
+
22
+ gem.add_development_dependency 'bundler'
23
+ gem.add_development_dependency 'rake'
24
+ gem.add_development_dependency 'simplecov'
25
+ gem.add_development_dependency 'rspec'
26
+ end
@@ -0,0 +1,8 @@
1
+ require 'checklist'
2
+
3
+ Checklist.checklist 'Example failing checklist' do |cl|
4
+ cl.step('One', 'DONE') { sleep(1) }
5
+ cl.step('Two', 'OK') { sleep(1) }
6
+ cl.step('Three', 'NO') { raise RuntimeError }
7
+ cl.step('Four', 'BAAH', 'A longer description here') { }
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'checklist'
2
+
3
+ Checklist.checklist 'Example successful checklist' do |cl|
4
+ cl.step('One', 'DONE') { sleep(1) }
5
+ cl.step('Two', 'OK') { sleep(1) }
6
+ cl.step('Three', 'YES') { }
7
+ cl.step('Four', 'BAAH', 'A longer description here') { }
8
+ end
@@ -0,0 +1,104 @@
1
+ require 'must_be'
2
+
3
+ require "checklist/version"
4
+ require 'checklist/step'
5
+ require 'checklist/ui'
6
+ require 'checklist/wrapper'
7
+
8
+ class Checklist
9
+ attr_reader :steps, :current, :name, :ui
10
+
11
+ def initialize(name, options={})
12
+ @steps = []
13
+ @remaining_steps = nil
14
+ @completed_steps = nil
15
+ @current = nil
16
+ @name = name
17
+ @ui = options[:ui] || Checklist::UI.new
18
+ end
19
+
20
+ # appendd a Checklist::Step to the checklist
21
+ def <<(step)
22
+ raise RuntimeError, 'List is open' if open?
23
+ step.must_be_a(Step)
24
+ steps << step
25
+ end
26
+
27
+ # create new Checklist::Step and add it to the checklist
28
+ def step(challenge, response, description=nil, &code)
29
+ self << Checklist::step(challenge, response, description, &code)
30
+ end
31
+
32
+ # true if checklist is started
33
+ def open?
34
+ !!remaining_steps
35
+ end
36
+
37
+ # true if checklist is started and all steps are completed_steps
38
+ def completed?
39
+ remaining_steps && remaining_steps.empty?
40
+ end
41
+
42
+ # Number of defined steps
43
+ def length
44
+ steps.length
45
+ end
46
+
47
+ # Number of remaining steps or nil if list is not open
48
+ def remaining
49
+ remaining_steps and remaining_steps.length
50
+ end
51
+
52
+ # Number of completed steps or nil if list is not open
53
+ def completed
54
+ completed_steps and completed_steps.length
55
+ end
56
+
57
+ def open!
58
+ raise RuntimeError, "Checklist is already open" if open?
59
+ ui.header(self)
60
+ self.remaining_steps = steps.clone
61
+ self.completed_steps = []
62
+ self
63
+ end
64
+
65
+ # Execute one step of the checklist
66
+ def step!
67
+ raise RuntimeError, 'Checklist is not open' unless open?
68
+ raise RuntimeError, 'Checklist is completed' if completed?
69
+ self.current = remaining_steps.first
70
+ ui.start(current)
71
+ current.run!
72
+ ui.finish(current)
73
+ completed_steps << remaining_steps.shift
74
+ end
75
+
76
+ # Finish the checklist, print and return outstanding steps
77
+ def close!
78
+ raise RuntimeError, 'Checklist is not open' unless open?
79
+ if completed?
80
+ ui.complete(self)
81
+ else
82
+ ui.incomplete(self, remaining_steps)
83
+ end
84
+ rv = remaining_steps
85
+ self.current =
86
+ self.remaining_steps =
87
+ self.completed_steps =
88
+ nil
89
+ rv
90
+ end
91
+
92
+ # Run the whole thing
93
+ def run!
94
+ open!
95
+ step! until completed?
96
+ self
97
+ ensure
98
+ close!
99
+ end
100
+
101
+ private
102
+ attr_writer :current
103
+ attr_accessor :remaining_steps, :completed_steps
104
+ end
@@ -0,0 +1,20 @@
1
+ class Checklist
2
+ Step = Struct.new(:challenge, :response, :description, :code) do
3
+ # Run checklist's body code
4
+ def run!
5
+ self.code.call
6
+ end
7
+
8
+ def to_hash
9
+ { "Challenge" => self.challenge,
10
+ "Response" => self.response,
11
+ "Description" => self.description }
12
+ end
13
+ end
14
+
15
+ # Create a new Step instance
16
+ def self.step(challenge, response, description=nil, &block)
17
+ raise ArgumentError, 'need a block' unless block_given?
18
+ Step.new(challenge, response, description, block)
19
+ end
20
+ end
@@ -0,0 +1,57 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'formatador'
3
+ require 'locale'
4
+
5
+ class Checklist
6
+ class UI
7
+ UTF8_MARKS = {
8
+ :tick => '✓',
9
+ :cross => '✗' }
10
+
11
+ ASCII_MARKS = {
12
+ :tick => '[bold]+',
13
+ :cross => '[bold]X' }
14
+
15
+ def initialize
16
+ @fmtd = Formatador.new
17
+ @marks = Locale.charset == 'UTF-8' ? UTF8_MARKS : ASCII_MARKS
18
+ end
19
+
20
+ def say(msg='')
21
+ fmtd.display "#{msg}\n"
22
+ end
23
+
24
+ def header(checklist)
25
+ fmtd.display "[bold][yellow]CHECKLIST[/][yellow]:[/] [bold]#{checklist.name}[/]\n"
26
+ end
27
+
28
+ def start(step)
29
+ fmtd.display " [ ] [yellow]#{step.challenge}[/] ..."
30
+ end
31
+
32
+ def finish(step)
33
+ fmtd.redisplay " [[green]#{marks[:tick]}[/]] #{step.challenge} [green]#{step.response}[/]\n"
34
+ end
35
+
36
+ def complete(checklist)
37
+ fmtd.display "[green]All #{checklist.length} steps [bold]completed[/]\n"
38
+ end
39
+
40
+ def incomplete(checklist, remaining_steps)
41
+ fmtd.redisplay " [[red]#{marks[:cross]}[/]] #{remaining_steps.first.challenge} [red]FAILED[/]\n"
42
+ remaining_steps[1..remaining_steps.length].each do |step|
43
+ fmtd.display " [ ] #{step.challenge} [yellow]PENDING[/]\n"
44
+ end
45
+ fmtd.display "\n[indent]#{checklist.remaining} of #{checklist.length} steps [red]NOT COMPLETED[/]:\n"
46
+
47
+ fmtd.indent do
48
+ fmtd.display_table(
49
+ remaining_steps.map(&:to_hash),
50
+ %w(Challenge Response Description))
51
+ end
52
+ end
53
+
54
+ private
55
+ attr_reader :fmtd, :marks
56
+ end
57
+ end
@@ -0,0 +1,3 @@
1
+ class Checklist
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,9 @@
1
+ class Checklist
2
+ # Yields a new checklist to block and runs it
3
+ def self.checklist(*args)
4
+ raise ArgumentError, 'need a block' unless block_given?
5
+ cl = self.new(*args)
6
+ yield cl
7
+ cl.run!
8
+ end
9
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Checklist, '.checklist' do
4
+ let(:ui) { double('UI').stub_checklist_ui }
5
+
6
+ it "yields a Checklist instance" do
7
+ Checklist.checklist 'Test', :ui => ui do |cl|
8
+ cl.should be_instance_of Checklist
9
+ end
10
+ end
11
+
12
+ it "runs a checklist defined within the block" do
13
+ tt = double("tracker")
14
+ tt.should_receive(:first).once.ordered
15
+ tt.should_receive(:second).once.ordered
16
+ tt.should_receive(:third).once.ordered
17
+
18
+ Checklist.checklist "A sample checklist", :ui => ui do |cl|
19
+ cl.step('first', 'done') { tt.first }
20
+ cl.step('second', 'ok') { tt.second }
21
+ cl.step('third', 'fine') { tt.third }
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Checklist, '#close!' do
4
+ subject { example_checklist }
5
+
6
+ it "should report checklist completion" do
7
+ subject.ui.should_receive(:complete).with(subject)
8
+
9
+ subject.open!
10
+ subject.length.times { subject.step! }
11
+ subject.close!
12
+ end
13
+
14
+ it "should report outstanding steps" do
15
+ subject.ui.should_receive(:incomplete).with(subject, subject.steps[2..3])
16
+
17
+ subject.open!
18
+ 2.times { subject.step! }
19
+ subject.close!
20
+ end
21
+
22
+ it 'should return outstanding steps' do
23
+ subject.open!
24
+ subject.step!
25
+
26
+ rv = subject.close!
27
+ rv.should be_instance_of Array
28
+ rv.length.should == 3
29
+ rv.each_with_index do |s, i|
30
+ s.should be_instance_of Checklist::Step
31
+ s.challenge.should == EXAMPLE_STEPS[i+1][0]
32
+ s.response.should == EXAMPLE_STEPS[i+1][1]
33
+ end
34
+ end
35
+
36
+ it 'should require checklist to be open' do
37
+ expect { subject.close! }.to raise_exception(RuntimeError)
38
+ end
39
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe Checklist do
4
+ let(:checklist) { Checklist.new('Test') }
5
+
6
+ it "has a name" do
7
+ checklist.name.should eq 'Test'
8
+ end
9
+
10
+ it 'initially has an empty step list' do
11
+ checklist.steps.should eq []
12
+ checklist.length.should eq 0
13
+ end
14
+
15
+ it 'initially is not open' do
16
+ checklist.open?.should be false
17
+ checklist.remaining.should be nil
18
+ checklist.completed.should be nil
19
+ end
20
+
21
+ it 'initially is not completed' do
22
+ checklist.completed?.should be nil
23
+ end
24
+ end
25
+
26
+ describe Checklist, '#<<' do
27
+ let(:checklist) { Checklist.new('Test') }
28
+
29
+ it 'adds new step to a checklist' do
30
+ checklist.steps.should eq []
31
+ step = Checklist.step('foo', 'bar') { nil }
32
+ checklist << step
33
+ checklist.steps.length.should eq 1
34
+ checklist.steps.first.should eq step
35
+ end
36
+
37
+ it 'requires argument to be a step' do
38
+ lambda { checklist << 23 }.should raise_error MustBe::Note
39
+ end
40
+ end
41
+
42
+ describe Checklist, '#step' do
43
+ let(:checklist) { Checklist.new('Test') }
44
+
45
+ it 'adds new step to a checklist' do
46
+ checklist.steps.should eq []
47
+ checklist.step('foo', 'bar') { 23 }
48
+ checklist.steps.length.should eq 1
49
+ checklist.steps.first.challenge.should eq 'foo'
50
+ checklist.steps.first.response.should eq 'bar'
51
+ checklist.steps.first.description.should be nil
52
+ checklist.steps.first.code.call.should eq 23
53
+
54
+ checklist.step('one', 'one done') { nil }
55
+ checklist.step('two', 'check two') { nil }
56
+ checklist.step('three', 'three it is') { nil }
57
+ checklist.length.should == 4
58
+ end
59
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Checklist, '#open!' do
4
+ subject { example_checklist }
5
+
6
+ it 'opens the checklist' do
7
+ subject.open?.should be false
8
+ subject.open!
9
+ subject.open?.should be true
10
+ subject.completed.should == 0
11
+ subject.remaining.should == subject.length
12
+ end
13
+
14
+ it "reports the checklist header" do
15
+ subject.ui.should_receive(:header).with(subject)
16
+ subject.open!
17
+ end
18
+
19
+ it 'cannot be called twice' do
20
+ subject.open!
21
+ expect { subject.open! }.to raise_exception(RuntimeError)
22
+ end
23
+
24
+ it 'should prevent adding new steps' do
25
+ subject.open!
26
+ expect { subject.step('one', 'one done') { nil } }.
27
+ to raise_exception(RuntimeError)
28
+ end
29
+
30
+ it 'returns checklist itself' do
31
+ subject.open!.should == subject
32
+ end
33
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Checklist, '#run!' do
4
+ subject { example_checklist }
5
+
6
+ it "should call all the methods and execute all the steps" do
7
+ def should_receive_and_call(method)
8
+ original_method = subject.method(method)
9
+ subject.should_receive(method) { original_method.call }
10
+ end
11
+
12
+ should_receive_and_call(:run!).once
13
+ should_receive_and_call(:open!).once
14
+ should_receive_and_call(:step!).exactly(subject.length).times
15
+ should_receive_and_call(:close!).once
16
+
17
+ subject.body.should_receive(:step).with(0).once
18
+ subject.body.should_receive(:step).with(1).once
19
+ subject.body.should_receive(:step).with(2).once
20
+ subject.body.should_receive(:step).with(3).once
21
+
22
+ subject.run!
23
+ end
24
+
25
+ it 'should return the checklist itself' do
26
+ subject.run!.should == subject
27
+ end
28
+
29
+ it 'should raise and report incomplete steps if a step bombs' do
30
+ subject.step('five', 'bomb') do
31
+ raise Exception, 'as planned'
32
+ body.step(5)
33
+ end
34
+ subject.step('six', 'done', 'a description') { body.step(6) }
35
+
36
+ subject.body.should_not_receive(:step).with(5)
37
+ subject.body.should_not_receive(:step).with(6)
38
+ subject.ui.should_receive(:incomplete).with(subject, subject.steps[4..5])
39
+
40
+ expect { subject.run! }.to raise_exception(Exception)
41
+ end
42
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ describe Checklist, '#step!' do
4
+ subject { example_checklist() }
5
+
6
+ it 'should execute one next step and push it from remaining to completed' do
7
+ subject.open!
8
+
9
+ subject.remaining.should == 4
10
+ subject.completed.should == 0
11
+
12
+ subject.body.should_receive(:step).with(0).once
13
+ subject.step!
14
+
15
+ subject.remaining.should == 3
16
+ subject.completed.should == 1
17
+
18
+ subject.body.should_receive(:step).with(1).once
19
+ subject.step!
20
+
21
+ subject.remaining.should == 2
22
+ subject.completed.should == 2
23
+
24
+ subject.body.should_receive(:step).with(2).once
25
+ subject.step!
26
+
27
+ subject.remaining.should == 1
28
+ subject.completed.should == 3
29
+
30
+ subject.body.should_receive(:step).with(3).once
31
+ subject.step!
32
+
33
+ subject.remaining.should == 0
34
+ subject.completed.should == 4
35
+ end
36
+
37
+ it 'should complete the checklist, eventually' do
38
+ subject.open!
39
+
40
+ subject.length.times do
41
+ subject.completed?.should be false
42
+ subject.step!
43
+ end
44
+
45
+ subject.completed?.should be true
46
+ end
47
+
48
+ it 'should not be allowed when list is completed' do
49
+ subject.open!
50
+
51
+ subject.length.times { subject.step! }
52
+ expect { subject.step! }.to raise_exception(RuntimeError)
53
+ end
54
+
55
+ it 'should report task start and finish' do
56
+
57
+ end
58
+
59
+ it 'should be disallowed when list is not open' do
60
+ # Look, Ma, no open!
61
+ expect { subject.step! }.to raise_exception(RuntimeError)
62
+ end
63
+ end
@@ -0,0 +1,49 @@
1
+ if ENV['COVERAGE']
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+ SimpleCov.add_filter('spec')
5
+ SimpleCov.add_filter('lib/checklist/ui.rb') # not covered by tests
6
+ end
7
+
8
+ require 'rspec/expectations'
9
+ require 'rspec/mocks'
10
+ require 'checklist'
11
+
12
+ RSpec.configure do |config|
13
+ config.before(:each) do
14
+ Checklist.stub(:say)
15
+ end
16
+ end
17
+
18
+ EXAMPLE_STEPS = [
19
+ [ 'one', 'one done' ],
20
+ [ 'two', 'check two' ],
21
+ [ 'three', 'three it is' ],
22
+ [ 'four', 'here you are', 'A surprise description' ]]
23
+
24
+ class RSpec::Mocks::Mock
25
+ def stub_checklist_ui
26
+ [
27
+ :say, :header, :start, :finish, :complete, :incomplete, :describe
28
+ ].each { |mm| self.stub(mm) }
29
+ self
30
+ end
31
+ end
32
+
33
+ def example_checklist
34
+ body = RSpec::Mocks::Mock.new('body')
35
+ body.stub(:step)
36
+
37
+ cl = Checklist.new('Test',
38
+ :ui => RSpec::Mocks::Mock.new('UI').stub_checklist_ui)
39
+
40
+ class << cl ; attr_accessor :body ; end
41
+ cl.body = body
42
+
43
+ EXAMPLE_STEPS.each_with_index do |step, ii|
44
+ challenge, response, description = step
45
+ cl.step(challenge, response, description) { body.step(ii) }
46
+ end
47
+
48
+ cl
49
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe Checklist::Step do
4
+ it "is a struct with challenge, response, description, and code fields" do
5
+ step = Checklist::Step.new(
6
+ 'the challenge',
7
+ 'the response',
8
+ 'the description',
9
+ 'some code')
10
+ step.challenge.should eq('the challenge')
11
+ step.response.should eq('the response')
12
+ step.description.should eq('the description')
13
+ step.code.should eq('some code')
14
+ end
15
+ end
16
+
17
+ describe Checklist::Step, "#run!" do
18
+ let(:code_body) do
19
+ code_body = double('code body')
20
+ code_body.should_receive(:poke!)
21
+ code_body
22
+ end
23
+ let(:step) do
24
+ Checklist::Step.new(
25
+ 'the challenge',
26
+ 'the response',
27
+ 'the description',
28
+ lambda { code_body.poke! } )
29
+ end
30
+
31
+ it "runs the proc from code field" do
32
+ step.run!
33
+ end
34
+
35
+ it "does not catch exceptions raised by code" do
36
+ step.code = lambda { code_body.poke! ; raise RuntimeError }
37
+ lambda { step.run! }.should raise_error(RuntimeError)
38
+ end
39
+ end
40
+
41
+ describe Checklist, '::step' do
42
+ it "Creates a runnable Checklist::Step instance" do
43
+ called = false
44
+ step = Checklist.step('the challenge', 'the response', 'a description') do
45
+ called = true
46
+ end
47
+ step.challenge.should eq 'the challenge'
48
+ step.response.should eq 'the response'
49
+ step.description.should eq 'a description'
50
+
51
+ step.run!
52
+ called.should be_true
53
+ end
54
+
55
+ it "Defaults description to nil" do
56
+ step = Checklist.step('the challenge', 'the response') { nil }
57
+ step.challenge.should eq 'the challenge'
58
+ step.response.should eq 'the response'
59
+ step.description.should be nil
60
+ end
61
+
62
+ it "Requires block" do
63
+ lambda { Checklist.step('foo', 'bar') }.should raise_error(ArgumentError)
64
+ end
65
+ end
metadata ADDED
@@ -0,0 +1,188 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: checklist
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Maciej Pasternacki
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: formatador
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: locale
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: must_be
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: bundler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rake
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: simplecov
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rspec
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ description: Multi-step checklist execution
127
+ email:
128
+ - maciej@pasternacki.net
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - .gitignore
134
+ - .travis.yml
135
+ - Gemfile
136
+ - LICENSE
137
+ - NOTES.org
138
+ - README.md
139
+ - Rakefile
140
+ - checklist.gemspec
141
+ - examples/failing.rb
142
+ - examples/simple.rb
143
+ - lib/checklist.rb
144
+ - lib/checklist/step.rb
145
+ - lib/checklist/ui.rb
146
+ - lib/checklist/version.rb
147
+ - lib/checklist/wrapper.rb
148
+ - spec/checklist/checklist_wrapper_method_spec.rb
149
+ - spec/checklist/close_spec.rb
150
+ - spec/checklist/initialize_spec.rb
151
+ - spec/checklist/open_spec.rb
152
+ - spec/checklist/run_spec.rb
153
+ - spec/checklist/step_spec.rb
154
+ - spec/spec_helper.rb
155
+ - spec/step/step_spec.rb
156
+ homepage: https://github.com/3ofcoins/checklist
157
+ licenses: []
158
+ post_install_message:
159
+ rdoc_options: []
160
+ require_paths:
161
+ - lib
162
+ required_ruby_version: !ruby/object:Gem::Requirement
163
+ none: false
164
+ requirements:
165
+ - - ! '>='
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ required_rubygems_version: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ requirements: []
175
+ rubyforge_project:
176
+ rubygems_version: 1.8.24
177
+ signing_key:
178
+ specification_version: 3
179
+ summary: Define and execute a checklist
180
+ test_files:
181
+ - spec/checklist/checklist_wrapper_method_spec.rb
182
+ - spec/checklist/close_spec.rb
183
+ - spec/checklist/initialize_spec.rb
184
+ - spec/checklist/open_spec.rb
185
+ - spec/checklist/run_spec.rb
186
+ - spec/checklist/step_spec.rb
187
+ - spec/spec_helper.rb
188
+ - spec/step/step_spec.rb