saga 0.8.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -15,19 +15,4 @@ namespace :documentation do
15
15
  rd.rdoc_files.include("README.rdoc", "LICENSE", "bin/**/*.rb", "lib/**/*.rb", "templates/**/*.rb")
16
16
  rd.options << "--all" << "--charset" << "utf-8"
17
17
  end
18
- end
19
-
20
- begin
21
- require 'jeweler'
22
- Jeweler::Tasks.new do |s|
23
- s.name = "saga"
24
- s.summary = s.description = "Saga is a tool to convert stories syntax to a nicely formatted document."
25
- s.homepage = "http://fingertips.github.com"
26
- s.email = "manfred@fngtps.com"
27
- s.authors = ["Manfred Stienstra"]
28
- s.add_dependency('erubis', '>= 2.6')
29
- s.add_dependency('activesupport', '>= 2.3')
30
- s.add_development_dependency('mocha-on-bacon')
31
- end
32
- rescue LoadError
33
- end
18
+ end
@@ -20,6 +20,10 @@ module Saga
20
20
  end; stories_as_flat_list
21
21
  end
22
22
 
23
+ def _binding
24
+ binding
25
+ end
26
+
23
27
  def used_ids
24
28
  @stories.values.inject([]) do |ids, stories|
25
29
  stories.each do |story|
@@ -20,7 +20,7 @@ module Saga
20
20
  template_file = File.join(@options[:template], 'document.erb')
21
21
  if File.exist?(template_file)
22
22
  template = Erubis::Eruby.new(File.read(template_file))
23
- template.result(@document.send(:binding))
23
+ template.result(@document._binding)
24
24
  else
25
25
  raise ArgumentError, "The template at path `#{template_file}' could not be found."
26
26
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: saga
3
3
  version: !ruby/object:Gem::Version
4
- hash: 61
4
+ hash: 59
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 8
9
- - 1
10
- version: 0.8.1
8
+ - 9
9
+ - 0
10
+ version: 0.9.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Manfred Stienstra
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-06-18 00:00:00 Z
18
+ date: 2012-07-10 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: erubis
@@ -48,7 +48,7 @@ dependencies:
48
48
  type: :runtime
49
49
  version_requirements: *id002
50
50
  - !ruby/object:Gem::Dependency
51
- name: mocha-on-bacon
51
+ name: bacon
52
52
  prerelease: false
53
53
  requirement: &id003 !ruby/object:Gem::Requirement
54
54
  none: false
@@ -61,8 +61,22 @@ dependencies:
61
61
  version: "0"
62
62
  type: :development
63
63
  version_requirements: *id003
64
+ - !ruby/object:Gem::Dependency
65
+ name: mocha-on-bacon
66
+ prerelease: false
67
+ requirement: &id004 !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ type: :development
77
+ version_requirements: *id004
64
78
  description: Saga is a tool to convert stories syntax to a nicely formatted document.
65
- email: manfred@fngtps.com
79
+ email: manfred@fngtpspec.com
66
80
  executables:
67
81
  - saga
68
82
  extensions: []
@@ -71,43 +85,24 @@ extra_rdoc_files:
71
85
  - LICENSE
72
86
  - README.rdoc
73
87
  files:
74
- - .kick
75
88
  - LICENSE
76
89
  - README.rdoc
77
90
  - Rakefile
78
91
  - VERSION
79
- - bin/saga
80
- - design/requirements.html
81
- - design/requirements.txt
82
- - lib/saga.rb
92
+ - templates/default/document.erb
93
+ - templates/default/helpers.rb
94
+ - templates/requirements.txt.erb
95
+ - templates/saga/document.erb
96
+ - templates/saga/helpers.rb
83
97
  - lib/saga/document.rb
84
98
  - lib/saga/formatter.rb
85
99
  - lib/saga/parser.rb
86
100
  - lib/saga/planning.rb
87
101
  - lib/saga/runner.rb
88
102
  - lib/saga/tokenizer.rb
89
- - saga.gemspec
90
- - templates/default/document.erb
91
- - templates/default/helpers.rb
92
- - templates/requirements.txt.erb
93
- - templates/saga/document.erb
94
- - templates/saga/helpers.rb
95
- - test/cases/author.txt
96
- - test/cases/definition.txt
97
- - test/cases/document.txt
98
- - test/cases/nested_stories.txt
99
- - test/cases/story.txt
100
- - test/cases/story_attributes.txt
101
- - test/fixtures/document.erb
102
- - test/saga_document_spec.rb
103
- - test/saga_formatter_spec.rb
104
- - test/saga_parser_spec.rb
105
- - test/saga_planning_spec.rb
106
- - test/saga_runner_spec.rb
107
- - test/saga_spec.rb
108
- - test/saga_tokenizer_spec.rb
109
- - test/spec_helper.rb
110
- homepage: http://fingertips.github.com
103
+ - lib/saga.rb
104
+ - bin/saga
105
+ homepage:
111
106
  licenses: []
112
107
 
113
108
  post_install_message:
data/.kick DELETED
@@ -1,25 +0,0 @@
1
- recipe :ignore
2
- ignore(/(^tmp|\.DS_Store)$/)
3
-
4
- recipe :ruby
5
- process do |files|
6
- Ruby.run_tests(files.take_and_map do |file|
7
- case file
8
- when %r{^lib/(.+)\.rb$}
9
- "test/#{$1.gsub('/', '_')}_spec.rb"
10
- when %r{^templates}
11
- "test/saga_formatter_spec.rb"
12
- when %r{^test/(.+)_spec\.rb$}
13
- file
14
- when %r{^test/cases}
15
- "test/saga_tokenizer_spec.rb"
16
- end
17
- end)
18
- files.take_and_map do |file|
19
- case file
20
- when 'design/requirements.txt'
21
- log `./bin/saga design/requirements.txt > design/requirements.html`
22
- files.delete(file)
23
- end
24
- end
25
- end
@@ -1,83 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
4
- <head>
5
- <title>Requirements Saga &middot; Fingertips</title>
6
- <link rel="stylesheet" type="text/css" media="all" href="http://resources.fngtps.com/2006/doc.css" />
7
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
8
- <style type="text/css">
9
- td.id { text-align: right !important; }
10
- td.id a { color: #000; }
11
- table.review { border-bottom: 1px solid #ccc; margin-top: -1em;}
12
- table.review td { padding: .25em 0; vertical-align: top; text-align: left; min-width: 1em; }
13
- table.review th { padding: .25em 0; vertical-align: top; text-align: right; }
14
- table.review td.story { width: 100%; border-top: 1px solid #ccc; }
15
- table.review td.meta { padding-left: 1em; border-top: 1px solid #ccc; text-align: right !important; white-space: nowrap; }
16
- table.review td.notes { color: #666; padding: 0 0 .25em 0; font-style: italic; }
17
- table.review .dropped { color: #666; text-decoration: line-through; }
18
- table.review .done { color: #666; background-color: #f0f8ff; }
19
- table.review tr.nested td.story { padding-left: 1em; }
20
- </style>
21
- <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
22
- </head>
23
- <body id="doc" class="requirements">
24
-
25
- <p id="logo"><img src="http://resources.fngtps.com/2006/print-logo.png" alt="Fingertips design &amp; development" /> </p>
26
-
27
- <h1>Requirements <br />Saga</h1>
28
-
29
- <p class="author">Manfred Stienstra, <a href="mailto:manfred@fngtps.com">manfred@fngtps.com</a></p>
30
-
31
-
32
- <h2>User stories</h2>
33
- <table class="review">
34
- <tr>
35
- <th></th>
36
- <th title="id">#</th>
37
- <th title="Estimate">e</th>
38
- <th title="Iteration">i</th>
39
- <th title="Status">s</th>
40
- </tr>
41
- <tr class="done" id="story1">
42
- <td class="story">As a writer I would like to write stories so developers can implement them.</td>
43
- <td class="meta id">1</td>
44
- <td class="meta estimate"></td>
45
- <td class="meta iteration"></td>
46
- <td class="meta status">done</td>
47
- </tr>
48
- <tr class="todo" id="story2">
49
- <td class="story">As a writer I would like to add priorities to my stories so that I can show their importance.</td>
50
- <td class="meta id">2</td>
51
- <td class="meta estimate"></td>
52
- <td class="meta iteration"></td>
53
- <td class="meta status">todo</td>
54
- </tr>
55
- <tr class="todo" id="story3">
56
- <td class="story">As a writer I would like to order my stories so that I can easily find the story I need.</td>
57
- <td class="meta id">3</td>
58
- <td class="meta estimate"></td>
59
- <td class="meta iteration"></td>
60
- <td class="meta status">todo</td>
61
- </tr>
62
- <tr class="todo">
63
- <td class="notes" colspan="5">Improve the HTML template to allow ordering by ID, estimate, iteration, status, and priority.</td>
64
- </tr>
65
- <tr class="todo" id="story4">
66
- <td class="story">As a writer I would like to ignore certain themes during autofill and planning so that I can specify non-functional stories.</td>
67
- <td class="meta id">4</td>
68
- <td class="meta estimate"></td>
69
- <td class="meta iteration"></td>
70
- <td class="meta status">todo</td>
71
- </tr>
72
- <tr class="todo">
73
- <td class="notes" colspan="5">saga -n 'Non-functional' -n 'Optional' autofill design/requirements.txt</td>
74
- </tr>
75
- </table>
76
-
77
- <h2>Roles</h2>
78
- <dl>
79
- <dt>Writer</dt>
80
- <dd>Someone who is responsible for writing down requirements in the form of stories</dd>
81
- </dl>
82
- </body>
83
- </html>
@@ -1,16 +0,0 @@
1
- Requirements Saga
2
-
3
- - Manfred Stienstra, manfred@fngtps.com
4
-
5
- USER STORIES
6
-
7
- As a writer I would like to write stories so developers can implement them. - #1 done
8
- As a writer I would like to add priorities to my stories so that I can show their importance. - #2 todo
9
- As a writer I would like to order my stories so that I can easily find the story I need. - #3 todo
10
- Improve the HTML template to allow ordering by ID, estimate, iteration, status, and priority.
11
- As a writer I would like to ignore certain themes during autofill and planning so that I can specify non-functional stories. - #4 todo
12
- saga -n 'Non-functional' -n 'Optional' autofill design/requirements.txt
13
-
14
- ROLES
15
-
16
- Writer: Someone who is responsible for writing down requirements in the form of stories
@@ -1,81 +0,0 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
5
-
6
- Gem::Specification.new do |s|
7
- s.name = "saga"
8
- s.version = "0.8.1"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Manfred Stienstra"]
12
- s.date = "2012-06-18"
13
- s.description = "Saga is a tool to convert stories syntax to a nicely formatted document."
14
- s.email = "manfred@fngtps.com"
15
- s.executables = ["saga"]
16
- s.extra_rdoc_files = [
17
- "LICENSE",
18
- "README.rdoc"
19
- ]
20
- s.files = [
21
- ".kick",
22
- "LICENSE",
23
- "README.rdoc",
24
- "Rakefile",
25
- "VERSION",
26
- "bin/saga",
27
- "design/requirements.html",
28
- "design/requirements.txt",
29
- "lib/saga.rb",
30
- "lib/saga/document.rb",
31
- "lib/saga/formatter.rb",
32
- "lib/saga/parser.rb",
33
- "lib/saga/planning.rb",
34
- "lib/saga/runner.rb",
35
- "lib/saga/tokenizer.rb",
36
- "saga.gemspec",
37
- "templates/default/document.erb",
38
- "templates/default/helpers.rb",
39
- "templates/requirements.txt.erb",
40
- "templates/saga/document.erb",
41
- "templates/saga/helpers.rb",
42
- "test/cases/author.txt",
43
- "test/cases/definition.txt",
44
- "test/cases/document.txt",
45
- "test/cases/nested_stories.txt",
46
- "test/cases/story.txt",
47
- "test/cases/story_attributes.txt",
48
- "test/fixtures/document.erb",
49
- "test/saga_document_spec.rb",
50
- "test/saga_formatter_spec.rb",
51
- "test/saga_parser_spec.rb",
52
- "test/saga_planning_spec.rb",
53
- "test/saga_runner_spec.rb",
54
- "test/saga_spec.rb",
55
- "test/saga_tokenizer_spec.rb",
56
- "test/spec_helper.rb"
57
- ]
58
- s.homepage = "http://fingertips.github.com"
59
- s.require_paths = ["lib"]
60
- s.rubygems_version = "1.8.18"
61
- s.summary = "Saga is a tool to convert stories syntax to a nicely formatted document."
62
-
63
- if s.respond_to? :specification_version then
64
- s.specification_version = 3
65
-
66
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
67
- s.add_runtime_dependency(%q<erubis>, [">= 2.6"])
68
- s.add_runtime_dependency(%q<activesupport>, [">= 2.3"])
69
- s.add_development_dependency(%q<mocha-on-bacon>, [">= 0"])
70
- else
71
- s.add_dependency(%q<erubis>, [">= 2.6"])
72
- s.add_dependency(%q<activesupport>, [">= 2.3"])
73
- s.add_dependency(%q<mocha-on-bacon>, [">= 0"])
74
- end
75
- else
76
- s.add_dependency(%q<erubis>, [">= 2.6"])
77
- s.add_dependency(%q<activesupport>, [">= 2.3"])
78
- s.add_dependency(%q<mocha-on-bacon>, [">= 0"])
79
- end
80
- end
81
-
@@ -1,8 +0,0 @@
1
- - Thijs van der Vossen
2
- => {:name => 'Thijs van der Vossen'}
3
- - Thijs van der Vossen, thijs@fngtps.com
4
- => {:name => 'Thijs van der Vossen', :email => 'thijs@fngtps.com'}
5
- - Thijs van der Vossen, thijs@fngtps.com, Fingertips
6
- => {:name => 'Thijs van der Vossen', :email => 'thijs@fngtps.com', :company => 'Fingertips'}
7
- - Thijs van der Vossen, thijs@fngtps.com, Fingertips, http://www.fngtps.com
8
- => {:name => 'Thijs van der Vossen', :email => 'thijs@fngtps.com', :company => 'Fingertips', :website => 'http://www.fngtps.com'}
@@ -1,10 +0,0 @@
1
-
2
- => {}
3
- User: A user
4
- => {:title => 'User', :definition => 'A user'}
5
- Administrator: Any user with full administrative access.
6
- => {:title => 'Administrator', :definition => 'Any user with full administrative access.'}
7
- Non-functional: Stories related to non-functional requirements.
8
- => {:title => 'Non-functional', :definition => 'Stories related to non-functional requirements.'}
9
- Service: The part of the web service used by clients to provide search and retrieval as well as account, device, and user management.
10
- => {:title => 'Service', :definition => 'The part of the web service used by clients to provide search and retrieval as well as account, device, and user management.'}
@@ -1,15 +0,0 @@
1
- Requirements Case
2
-
3
- - Manfred Stienstra, manfred@fngtps.com
4
-
5
- Saga is a tool for writing and publishing <requirements> in the form of user stories.
6
-
7
- USER STORIES
8
-
9
- As a writer I would like to write stories so that developers can implement them. - #1 todo
10
- Stories are written in Saga format.
11
- | As a writer I would like to add nested stories so that I can write requirements on two zoom levels. - todo
12
- | Nested stories are basicaly substories of regular stories.
13
- | As a writer I would like to add header so that I can group stories by theme. - todo
14
-
15
- Writer: Someone who is responsible for writing down requirements in the form of stories
@@ -1,4 +0,0 @@
1
- As an editor I would like to manage content so that I can keep the site up to date.
2
- | As an editor I would like to add a page so that I can create new pages.
3
- | As an editor I would like to remove a page so that I can remove unwanted pages.
4
- => {:description => 'As an editor I would like to manage content so that I can keep the site up to date.', :stories => [{:description => 'As an editor I would like to add a page so that I can create new pages.'}, {:description => 'As an editor I would like to remove a page so that I can remove unwanted pages.'}]}
@@ -1,6 +0,0 @@
1
- As a developer I would like to have created database indexes so that the queries run as fast as possible.
2
- => {:description => 'As a developer I would like to have created database indexes so that the queries run as fast as possible.'}
3
- As a recorder I would like to use TLS (SSL) so that my connection with the storage API is secure and I can be sure of the API’s identity. - #4 todo
4
- => {:description => 'As a recorder I would like to use TLS (SSL) so that my connection with the storage API is secure and I can be sure of the API’s identity.', :id => 4, :status => 'todo' }
5
- As a subscriber I would like to be able to buy additional pre-paid recording slots even though I also have a subscription so that I don’t have to upgrade my subscription level when I temporarily need to make a lot more recordings than usual. - #16 todo
6
- => {:description => 'As a subscriber I would like to be able to buy additional pre-paid recording slots even though I also have a subscription so that I don’t have to upgrade my subscription level when I temporarily need to make a lot more recordings than usual.', :id => 16, :status => 'todo'}
@@ -1,22 +0,0 @@
1
-
2
- => {}
3
-
4
- => {}
5
- #4
6
- => {:id => 4}
7
- #12 todo
8
- => {:id => 12, :status => 'todo'}
9
- #3 partially done
10
- => {:id => 3, :status => 'partially done'}
11
- 12
12
- => {:estimate => [12, :hours]}
13
- 1d
14
- => {:estimate => [1, :days]}
15
- #1 1w partially done
16
- => {:id => 1, :estimate => [1, :weeks], :status => 'partially done'}
17
- i12
18
- => {:iteration => 12}
19
- #1 i1
20
- => {:id => 1, :iteration => 1}
21
- #3 1 i2
22
- => {:id => 3, :iteration => 2, :estimate => [1, :hours]}
@@ -1,80 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
4
- <head>
5
- <title>Requirements <%= title %> &middot; Fingertips</title>
6
- <link rel="stylesheet" type="text/css" media="all" href="http://resources.fngtps.com/2006/doc.css" />
7
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
8
- <style type="text/css">
9
- td.id { text-align: right !important; }
10
- td.id a { color: #000; }
11
- table.review { border-bottom: 1px solid #ccc; margin-top: -1em;}
12
- table.review td { padding: .25em 0; vertical-align: top; text-align: left; min-width: 1em; }
13
- table.review th { padding: .25em 0; vertical-align: top; text-align: right; }
14
- table.review td.story { width: 100%; border-top: 1px solid #ccc; }
15
- table.review td.meta { padding-left: 1em; border-top: 1px solid #ccc; text-align: right !important; white-space: nowrap; }
16
- table.review td.notes { color: #666; padding: 0 0 .25em 0; font-style: italic; }
17
- table.review .dropped { color: #666; text-decoration: line-through; }
18
- table.review .done { color: #666; background-color: #f0f8ff; }
19
- </style>
20
- <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
21
- </head>
22
- <body id="doc" class="requirements">
23
-
24
- <p id="logo"><img src="http://resources.fngtps.com/2006/print-logo.png" alt="Fingertips design &amp; development" /> </p>
25
-
26
- <h1>Requirements <br /><%= title %></h1>
27
-
28
- <% authors.each do |author| %>
29
- <p class="author"><%= author %></p>
30
- <% end %>
31
-
32
- <% introduction.each do |paragraph| %>
33
- <p><%== paragraph %></p>
34
- <% end %>
35
-
36
- <% unless stories.empty? %>
37
- <h2>User stories</h2>
38
- <% stories.each do |header, stories| %>
39
- <% unless header.strip == '' %>
40
- <h3><%= header %></h3>
41
- <% end %>
42
- <table class="review">
43
- <tr>
44
- <th></th>
45
- <th title="id">#</th>
46
- <th title="Estimate">e</th>
47
- <th title="Iteration">i</th>
48
- <th title="Status">s</th>
49
- </tr>
50
- <% stories.each do |story| %>
51
- <tr class="<%= story[:status] %>" id="story<%= story[:id] %>">
52
- <td class="story"><%= story[:description] %></td>
53
- <td class="meta id"><%= story[:id] %></td>
54
- <td class="meta estimate"><%= story[:estimate] %></td>
55
- <td class="meta iteration"><%= story[:iteration] %></td>
56
- <td class="meta status"><%= story[:status] %></td>
57
- </tr>
58
- <% if story[:notes] %>
59
- <tr class="<%= story[:status] %>">
60
- <td class="notes" colspan="5"><%= story[:notes] %></td>
61
- </tr>
62
- <% end %>
63
- <% end %>
64
- </table>
65
- <% end %>
66
- <% end %>
67
-
68
- <% definitions.each do |header, definitions| %>
69
- <% unless header.strip == '' %>
70
- <h2><%= header %></h2>
71
- <% end %>
72
- <dl>
73
- <% definitions.each do |definition| %>
74
- <dt><%= definition[:title] %></dt>
75
- <dd><%= definition[:definition] %></dd>
76
- <% end %>
77
- </dl>
78
- <% end %>
79
- </body>
80
- </html>
@@ -1,112 +0,0 @@
1
- require File.expand_path('../spec_helper', __FILE__)
2
-
3
- describe "A Document" do
4
- it "responds to accessors" do
5
- document = Saga::Document.new
6
- [:title, :introduction, :authors, :stories, :definitions].each do |method|
7
- document.should.respond_to(method)
8
- end
9
- end
10
-
11
- it "stores stories in the order it receives them" do
12
- document = Saga::Document.new
13
- sections = %w(First Second Third Fourth Fifth)
14
- sections.each do |section|
15
- document.stories[section] = {}
16
- end
17
- document.stories.keys.should == sections
18
- end
19
-
20
- it "stores definitions in the order it receives them" do
21
- document = Saga::Document.new
22
- sections = %w(First Second Third Fourth Fifth)
23
- sections.each do |section|
24
- document.definitions[section] = {}
25
- end
26
- document.definitions.keys.should == sections
27
- end
28
-
29
- it "returns the number of stories as its length" do
30
- document = Saga::Document.new
31
- document.length == 0
32
-
33
- document.stories[''] = [{}, {}]
34
- document.length.should == 2
35
-
36
- document.stories['Non-functional'] = [{}]
37
- document.length.should == 3
38
- end
39
-
40
- it "know whether the document does or does not have stories" do
41
- document = Saga::Document.new
42
- document.should.be.empty
43
-
44
- document.stories[''] = [{},{}]
45
- document.should.not.be.empty
46
- end
47
-
48
- it "returns a list of used IDs" do
49
- document = Saga::Document.new
50
- document.used_ids.should == []
51
-
52
- document.stories[''] = []
53
- document.stories[''] << { :id => 2 }
54
- document.used_ids.should == [2]
55
-
56
- document.stories['Non-functional'] = []
57
- document.stories['Non-functional'] << { :id => 12 }
58
- document.used_ids.should == [2, 12]
59
-
60
- document.stories['Non-functional'] << { :id => 3 }
61
- document.used_ids.should == [2, 12, 3]
62
-
63
- document.stories[''][0][:stories] = [
64
- {}, {:id => 14}, {}, {:id => 5}
65
- ]
66
- document.used_ids.should == [2, 14, 5, 12, 3]
67
- end
68
-
69
- it "returns a list of unused IDs" do
70
- document = Saga::Document.new
71
- document.unused_ids(0).should == []
72
- document.unused_ids(3).should == [1,2,3]
73
- document.unused_ids(4).should == [1,2,3,4]
74
-
75
- document.stories[''] = []
76
- document.stories[''] << { :id => 2 }
77
- document.stories[''] << { :id => 4 }
78
- document.stories[''] << { :id => 5 }
79
- document.stories[''] << { :id => 6 }
80
- document.stories[''] << { :id => 100 }
81
-
82
- document.unused_ids(0).should == []
83
- document.unused_ids(1).should == [1]
84
- document.unused_ids(2).should == [1,3]
85
- document.unused_ids(3).should == [1,3,7]
86
- document.unused_ids(4).should == [1,3,7,8]
87
- end
88
-
89
- it "autofills ids" do
90
- document = Saga::Document.new
91
- document.autofill_ids
92
-
93
- document.stories[''] = []
94
- document.stories[''] << { :description => 'First story'}
95
- document.stories[''] << { :description => 'Second story', :stories => [
96
- { :description => 'First nested story' }, { :id => 15, :description => 'Second nested story'}
97
- ] }
98
-
99
- document.stories['Non-functional'] = []
100
- document.stories['Non-functional'] << { :id => 1, :description => 'Third story' }
101
-
102
- document.stories['Developer'] = []
103
- document.stories['Developer'] << { :description => 'Fourth story' }
104
- document.stories['Developer'] << { :id => 3, :description => 'Fifth story' }
105
-
106
- document.autofill_ids
107
- document.stories[''].map { |story| story[:id] }.should == [2, 4]
108
- document.stories[''][1][:stories].map { |story| story[:id] }.should == [5, 15]
109
- document.stories['Non-functional'].map { |story| story[:id] }.should == [1]
110
- document.stories['Developer'].map { |story| story[:id] }.should == [6, 3]
111
- end
112
- end
@@ -1,57 +0,0 @@
1
- require File.expand_path('../spec_helper', __FILE__)
2
-
3
- describe "Formatter" do
4
- before do
5
- @document = Saga::Document.new
6
- @document.title = 'Requirements API'
7
- @document.authors = [
8
- {:name => 'Thijs van der Vossen', :email => 'thijs@fngtps.com', :company => 'Fingertips', :website => 'http://www.fngtps.com'},
9
- {:name => 'Manfred Stienstra', :email => 'manfred@fngtps.com', :company => 'Fingertips', :website => 'http://www.fngtps.com'}
10
- ]
11
- @document.introduction = [
12
- 'A web service for interfacing with the service.', 'Exposes a public API to the application.', 'Uses <20> levels of redirection.'
13
- ]
14
- @document.stories = [
15
- ['General', [
16
- {:description => 'As a consumer I would like to use TLS (SSL) so that my connection with the API is secure', :id => 4, :status => 'todo', :notes => 'Use a self-signed CA certificate to create the certificates.', :stories => [
17
- { :description => 'As a consumer I would like to receive a certificate from the provider.', :id => 12, :status => 'done', :notes => 'The certificate for the CA.' },
18
- { :description => 'As a consumer I would like to receive a hosts file from the provider.', :id => 13, :status => 'done' }
19
- ]
20
- },
21
- { :description => 'As a consumer I would like to get a list of users', :id => 5, :status => 'todo' }
22
- ]]
23
- ]
24
- end
25
-
26
- it "formats a saga document to HTML" do
27
- html = Saga::Formatter.format(@document)
28
- html.should.include('<h1>Requirements <br />Requirements API</h1>')
29
- html.should.include('receive a certificate')
30
- end
31
-
32
- it "include the escaped introduction in the HTML output" do
33
- html = Saga::Formatter.format(@document)
34
- html.should.include('<p>Uses &lt;20&gt; levels of redirection.</p>')
35
- html.should.include('receive a certificate')
36
- end
37
-
38
- it "formats a saga document to saga" do
39
- saga = Saga::Formatter.saga_format(@document)
40
- saga.should.include('Requirements Requirements API')
41
- saga.should.include('receive a certificate')
42
- end
43
-
44
- describe "with an external template" do
45
- it "raises when the document.erb file doesn't exist" do
46
- lambda {
47
- Saga::Formatter.format(@document, :template => '/does/not/exist')
48
- }.should.raise(ArgumentError, "The template at path `/does/not/exist/document.erb' could not be found.")
49
- end
50
-
51
- it "omits the helpers.rb file when it doesn't exist" do
52
- formatter = Saga::Formatter.new(@document, :template => File.expand_path('../fixtures', __FILE__))
53
- formatter.expects(:load).never
54
- formatter.format.should.not.be.empty
55
- end
56
- end
57
- end
@@ -1,169 +0,0 @@
1
- require File.expand_path('../spec_helper', __FILE__)
2
-
3
- module ParserHelper
4
- def parser
5
- @parser ||= Saga::Parser.new
6
- end
7
-
8
- def parse(input)
9
- Saga::Parser.parse(input)
10
- end
11
-
12
- def parse_title
13
- parser.parse("Requirements API\n\n")
14
- end
15
-
16
- def parse_introduction
17
- parser.parse("This document describes our API.\n\n")
18
- end
19
-
20
- def parse_story_marker
21
- parser.parse('USER STORIES')
22
- end
23
-
24
- def parse_header
25
- parser.parse('Storage')
26
- end
27
-
28
- def parse_story
29
- parser.parse('As a recorder I would like to add a recording so that it becomes available. - #1 todo')
30
- end
31
-
32
- def parse_story_notes
33
- parser.parse(' “Your recording was created successfully.”')
34
- end
35
-
36
- def parse_nested_story
37
- parser.parse('| As a recorder I would like to add a recording so that it becomes available. - todo')
38
- end
39
-
40
- def parse_nested_story_notes
41
- parser.parse('| “Your recording was created successfully.”')
42
- end
43
-
44
- def parse_definition
45
- parser.parse('Other: Stories that don’t fit anywhere else.')
46
- end
47
- end
48
-
49
- describe "Parser" do
50
- it "should initialize and parse" do
51
- document = Saga::Parser.parse('')
52
- document.should.be.kind_of?(Saga::Document)
53
- end
54
-
55
- it "should initialize and parse a reference document" do
56
- document = Saga::Parser.parse(File.read(File.expand_path('../cases/document.txt', __FILE__)))
57
- document.should.be.kind_of?(Saga::Document)
58
- document.length.should == 3
59
- end
60
- end
61
-
62
- describe "A Parser, concerning the handling of input" do
63
- extend ParserHelper
64
- before { @parser = nil }
65
-
66
- it "interprets the first line of the document as a title" do
67
- document = parse('Requirements API')
68
- document.title.should == 'API'
69
-
70
- document = parse('Record and Search')
71
- document.title.should == 'Record and Search'
72
- end
73
-
74
- it "interprets authors" do
75
- document = parse('- Manfred Stienstra')
76
- document.authors.map { |author| author[:name] }.should == ['Manfred Stienstra']
77
- end
78
-
79
- it "interprets the introduction" do
80
- parse_title
81
- parse_introduction
82
- parser.document.introduction.should == ['This document describes our API.']
83
- end
84
-
85
- it "interprets stories without a header as being a gobal story" do
86
- parse_title
87
- parse_introduction
88
- parse_story_marker
89
- parse_story
90
-
91
- parser.document.stories.keys.should == ['']
92
- parser.document.stories[''].length.should == 1
93
- parser.document.stories[''].first[:id].should == 1
94
- end
95
-
96
- it "interprets stories with a header as being part of that section" do
97
- parse_title
98
- parse_introduction
99
- parse_story_marker
100
- parse_header
101
- parse_story
102
-
103
- parser.document.stories.keys.should == ['Storage']
104
- parser.document.stories['Storage'].length.should == 1
105
- parser.document.stories['Storage'].first[:id].should == 1
106
- end
107
-
108
- it "interprets a comment after a story as being part of the story" do
109
- parse_story_marker
110
- parse_story
111
- parse_story_notes
112
-
113
- parser.document.stories.keys.should == ['']
114
- parser.document.stories[''].length.should == 1
115
- parser.document.stories[''].first[:id].should == 1
116
- parser.document.stories[''].first[:notes].should == '“Your recording was created successfully.”'
117
- end
118
-
119
- it "interprets nested story as part of the parent story" do
120
- parse_story_marker
121
- parse_story
122
- parse_story_notes
123
- parse_nested_story
124
- parse_nested_story_notes
125
- parse_nested_story
126
- parse_nested_story_notes
127
-
128
- parser.document.stories.keys.should == ['']
129
- parser.document.stories[''].length.should == 1
130
- first_story = parser.document.stories[''][0]
131
- first_story[:id].should == 1
132
- first_story[:notes].should == '“Your recording was created successfully.”'
133
-
134
- first_story[:stories].length.should == 2
135
- first_story[:stories][0][:notes].should == '“Your recording was created successfully.”'
136
- first_story[:stories][1][:notes].should == '“Your recording was created successfully.”'
137
- end
138
-
139
- it "interprets definitions without a header as being a gobal definition" do
140
- parse_title
141
- parse_introduction
142
- parse_story_marker
143
- parse_definition
144
-
145
- parser.document.definitions.keys.should == ['']
146
- parser.document.definitions[''].length.should == 1
147
- parser.document.definitions[''].first[:title].should == 'Other'
148
- end
149
-
150
- it "interprets definitions with a header as being part of that section" do
151
- parse_title
152
- parse_introduction
153
- parse_story_marker
154
- parse_header
155
- parse_definition
156
-
157
- parser.document.definitions.keys.should == ['Storage']
158
- parser.document.definitions['Storage'].length.should == 1
159
- parser.document.definitions['Storage'].first[:title].should == 'Other'
160
- end
161
-
162
- it "properly parses hard cases" do
163
- parse_story_marker
164
- parser.parse('As a member I would like the app to keep the information it got from Twitter up-to-date so that changes I make on Twitter get propagated to my listing.')
165
-
166
- story = parser.document.stories[''].first
167
- story[:description].should == 'As a member I would like the app to keep the information it got from Twitter up-to-date so that changes I make on Twitter get propagated to my listing.'
168
- end
169
- end
@@ -1,79 +0,0 @@
1
- require File.expand_path('../spec_helper', __FILE__)
2
-
3
- describe "An empty Planning" do
4
- before do
5
- @document = Saga::Document.new
6
- @planning = Saga::Planning.new(@document)
7
- end
8
-
9
- it "shows an empty planning message" do
10
- @planning.to_s.should == 'There are no stories yet.'
11
- end
12
- end
13
-
14
- describe "A Planning for unestimated stories" do
15
- before do
16
- @document = Saga::Document.new
17
- @document.stories[''] = [{}, {}, {:stories => [{}, {}]}]
18
- @planning = Saga::Planning.new(@document)
19
- end
20
-
21
- it "shows a planning" do
22
- @planning.to_s.should == "Unestimated : 5 stories"
23
- end
24
- end
25
-
26
- describe "A Planning for estimated and unestimated stories" do
27
- before do
28
- @document = Saga::Document.new
29
- @document.stories[''] = [{}, {}, {}]
30
- @document.stories['Member'] = [{}, {:estimate => [6, :hours], :stories => [{:estimate => [6, :hours]}]}, {}]
31
- @planning = Saga::Planning.new(@document)
32
- end
33
-
34
- it "shows a planning" do
35
- @planning.to_s.should ==
36
- "Unplanned : 12 (2 stories)\n"+
37
- "------------------------------\n"+
38
- "Total : 12 (2 stories)\n"+
39
- "\n"+
40
- "Unestimated : 5 stories"
41
- end
42
- end
43
-
44
- describe "A simple Planning" do
45
- before do
46
- @document = Saga::Document.new
47
- @document.stories[''] = [{:estimate => [12, :hours]}]
48
- @planning = Saga::Planning.new(@document)
49
- end
50
-
51
- it "shows a planning" do
52
- @planning.to_s.should ==
53
- "Unplanned : 12 (1 story)\n"+
54
- "----------------------------\n"+
55
- "Total : 12 (1 story)"
56
- end
57
- end
58
-
59
- describe "A complicated Planning" do
60
- before do
61
- @document = Saga::Document.new
62
- @document.stories[''] = [{:estimate => [12, :hours], :iteration => 1}, {:estimate => [8, :hours], :stories => [{}, {}]}]
63
- @document.stories['Developer'] = [{:estimate => [1, :weeks], :iteration => 2,:stories => [{:estimate => [2, :hours], :iteration => 2}, {:estimate => [1, :hours]}]}, {:estimate => [1, :hours], :iteration => 2}]
64
- @document.stories['Writer'] = [{:estimate => [5, :hours], :iteration => 1}, {:estimate => [2, :hours], :iteration => 3}]
65
- @planning = Saga::Planning.new(@document)
66
- end
67
-
68
- it "shows a planning" do
69
- @planning.to_s.should ==
70
- "Unplanned : 9 (2 stories)\n"+
71
- "Iteration 1 : 17 (2 stories)\n"+
72
- "Iteration 2 : 43 (3 stories)\n"+
73
- "Iteration 3 : 2 (1 story)\n"+
74
- "------------------------------\n"+
75
- "Total : 71 (8 stories)\n"+
76
- "\n"+
77
- "Unestimated : 2 stories"
78
- end
79
- end
@@ -1,137 +0,0 @@
1
- require File.expand_path('../spec_helper', __FILE__)
2
- require 'singleton'
3
-
4
- module OutputHelper
5
- class Collector
6
- attr_reader :written
7
- def initialize
8
- @written = []
9
- end
10
-
11
- def write(string)
12
- @written << string
13
- end
14
- end
15
-
16
- def collect_stdout(&block)
17
- collector = Collector.new
18
- stdout = $stdout
19
- $stdout = collector
20
- begin
21
- block.call
22
- ensure
23
- $stdout = stdout
24
- end
25
- collector.written.join
26
- end
27
- end
28
-
29
- describe "A Runner" do
30
- extend OutputHelper
31
-
32
- it "shows a help text when invoked without a command and options" do
33
- runner = Saga::Runner.new([])
34
- collect_stdout do
35
- runner.run
36
- end.should == runner.parser.to_s
37
- end
38
-
39
- it "shows a help test when the -h option is used" do
40
- runner = Saga::Runner.new(%w(-h))
41
- runner.stubs(:exit)
42
- collect_stdout do
43
- runner.run
44
- end.should == runner.parser.to_s*2 # Because we stub exit it runs twice ):
45
- end
46
-
47
- it "generates a requirements stub to can get started" do
48
- Saga::Runner.stubs(:author).returns({:name => "Manfred Stienstra"})
49
- runner = Saga::Runner.new(%w(new))
50
- output = collect_stdout do
51
- runner.run
52
- end
53
- output.should.include('Requirements Title')
54
- output.should.include('- Manfred Stienstra')
55
- end
56
-
57
- it "knows information about the user currently logged in to the system" do
58
- author = Saga::Runner.author
59
- author[:name].should.not.be.nil
60
- end
61
-
62
- it "converts the provided filename" do
63
- runner = Saga::Runner.new(%w(requirements.txt))
64
- runner.expects(:convert).with(File.expand_path('requirements.txt'), {}).returns('output')
65
- collect_stdout do
66
- runner.run
67
- end.should == "output\n"
68
- end
69
-
70
- it "converts the provided filename when the convert command is given" do
71
- runner = Saga::Runner.new(%w(convert requirements.txt))
72
- runner.expects(:convert).with(File.expand_path('requirements.txt'), {}).returns('output')
73
- collect_stdout do
74
- runner.run
75
- end.should == "output\n"
76
- end
77
-
78
- it "converts the provided filename with an external template" do
79
- Saga::Parser.stubs(:parse)
80
- File.stubs(:read)
81
- Saga::Formatter.expects(:format).with do |_, options|
82
- options[:template].should == File.expand_path('path/to/a/template')
83
- end
84
- runner = Saga::Runner.new(%W(convert --template path/to/a/template requirements.txt))
85
- collect_stdout { runner.run }
86
- end
87
-
88
- it "inspects the parsed document" do
89
- runner = Saga::Runner.new(%w(inspect requirements.txt))
90
- runner.expects(:write_parsed_document).with(File.expand_path('requirements.txt'))
91
- runner.run
92
- end
93
-
94
- it "autofills the parsed document" do
95
- runner = Saga::Runner.new(%w(autofill requirements.txt))
96
- runner.expects(:autofill).with(File.expand_path('requirements.txt')).returns('output')
97
- collect_stdout do
98
- runner.run
99
- end.should == "output\n"
100
- end
101
-
102
- it "shows an overview of the time planned in the different iterations" do
103
- runner = Saga::Runner.new(%w(planning requirements.txt))
104
- runner.expects(:planning).with(File.expand_path('requirements.txt')).returns('output')
105
- collect_stdout do
106
- runner.run
107
- end.should == "output\n"
108
- end
109
-
110
- it "copies the default template to the specified path" do
111
- begin
112
- destination = "/tmp/saga-template-dir"
113
- Saga::Runner.new(%W(template #{destination})).run
114
- File.read(File.join(destination, 'helpers.rb')).should ==
115
- File.read(File.join(Saga::Formatter.template_path, 'default/helpers.rb'))
116
- File.read(File.join(destination, 'document.erb')).should ==
117
- File.read(File.join(Saga::Formatter.template_path, 'default/document.erb'))
118
- ensure
119
- FileUtils.rm_rf(destination)
120
- end
121
- end
122
-
123
- it "complains when tryin to create a template at an existing path" do
124
- begin
125
- destination = "/tmp/saga-template-dir"
126
- FileUtils.mkdir_p(destination)
127
- runner = Saga::Runner.new(%W(template #{destination}))
128
- collect_stdout do
129
- runner.run
130
- end.should == "The directory `#{destination}' already exists!\n"
131
- File.should.not.exist File.join(destination, 'helpers.rb')
132
- File.should.not.exist File.join(destination, 'document.erb')
133
- ensure
134
- FileUtils.rm_rf(destination)
135
- end
136
- end
137
- end
@@ -1,35 +0,0 @@
1
- require File.expand_path('../spec_helper', __FILE__)
2
-
3
- describe "Saga" do
4
- before do
5
- @document = Saga::Document.new
6
- @document.title = 'Requirements API'
7
- @document.authors = [
8
- {:name => 'Thijs van der Vossen', :email => 'thijs@fngtps.com', :company => 'Fingertips', :website => 'http://www.fngtps.com'},
9
- {:name => 'Manfred Stienstra', :email => 'manfred@fngtps.com', :company => 'Fingertips', :website => 'http://www.fngtps.com'}
10
- ]
11
- @document.introduction = [
12
- 'A web service for interfacing with the service.', 'Exposes a public API to the application.'
13
- ]
14
- @document.stories = ActiveSupport::OrderedHash.new
15
- [
16
- ['General', [
17
- {:description => 'As a consumer I would like to use TLS (SSL) so that my connection with the API is secure', :id => 4, :status => 'todo', :notes => 'Use a self-signed CA certificate to create the certificates.' }
18
- ]]
19
- ].each do |key, stories|
20
- @document.stories[key] = stories
21
- end
22
- end
23
-
24
- it "round-trips through the parser and formatter" do
25
- document = @document
26
- 2.times do
27
- saga = Saga::Formatter.saga_format(document)
28
- document = Saga::Parser.parse(saga)
29
- end
30
-
31
- document.title.should == @document.title
32
- document.authors.should == @document.authors
33
- document.stories.should == @document.stories
34
- end
35
- end
@@ -1,141 +0,0 @@
1
- require File.expand_path('../spec_helper', __FILE__)
2
-
3
- module CasesHelper
4
- def _parse_expected(line)
5
- eval(line[3..-1])
6
- end
7
-
8
- def each_case(path)
9
- filename = File.expand_path("../cases/#{path}.txt", __FILE__)
10
- input = ''
11
- File.readlines(filename).each do |line|
12
- if line.start_with?('=>')
13
- yield input, _parse_expected(line)
14
- input = ''
15
- else
16
- input << "#{line}\n"
17
- end
18
- end
19
- end
20
- end
21
-
22
- describe "Tokenizer" do
23
- extend CasesHelper
24
-
25
- it "tokenizes story attributes input" do
26
- each_case('story_attributes') do |input, expected|
27
- Saga::Tokenizer.tokenize_story_attributes(input).should == expected
28
- end
29
- end
30
-
31
- it "tokenizes story input" do
32
- each_case('story') do |input, expected|
33
- Saga::Tokenizer.tokenize_story(input).should == expected
34
- end
35
- end
36
-
37
- it "tokenizes hard stories" do
38
- Saga::Tokenizer.tokenize_story('As a member I would like the app to keep the information it got from Twitter up-to-date so that changes I make on Twitter get propagated to my listing.').should == {
39
- :description => 'As a member I would like the app to keep the information it got from Twitter up-to-date so that changes I make on Twitter get propagated to my listing.'
40
- }
41
- end
42
-
43
- it "tokenizes definition input" do
44
- each_case('definition') do |input, expected|
45
- Saga::Tokenizer.tokenize_definition(input).should == expected
46
- end
47
- end
48
-
49
- it "tokenizes author input" do
50
- each_case('author') do |input, expected|
51
- Saga::Tokenizer.tokenize_author(input).should == expected
52
- end
53
- end
54
- end
55
-
56
- describe "A Tokenizer" do
57
- before do
58
- @parser = stub('Parser')
59
- @tokenizer = Saga::Tokenizer.new(@parser)
60
- end
61
-
62
- it "sends a tokenized story to the parser" do
63
- line = 'As a recorder I would like to use TLS (SSL) so that my connection with the storage API is secure and I can be sure of the API’s identity. - #4 todo'
64
- story = Saga::Tokenizer.tokenize_story(line)
65
-
66
- @parser.expects(:handle_story).with(story)
67
- @tokenizer.process_line(line)
68
- end
69
-
70
- it "sends a tokenized note to the parser" do
71
- line = ' Optionally support SSL'
72
- notes = line.strip
73
-
74
- @parser.expects(:handle_notes).with(notes)
75
- @tokenizer.process_line(line)
76
- end
77
-
78
- it "doesn't mistake a story note with a semicolon as a definition" do
79
- line = ' It would be nice if we could use http://www.braintreepaymentsolutions.com/'
80
- @parser.expects(:handle_notes).with(line.strip)
81
- @tokenizer.process_line(line)
82
- end
83
-
84
- it "sends a nested tokenized story to the parser" do
85
- line = '| As a recorder I would like to use TLS (SSL) so that my connection with the storage API is secure and I can be sure of the API’s identity. - #4 todo'
86
- story = Saga::Tokenizer.tokenize_story(line[1..-1])
87
-
88
- @parser.expects(:handle_nested_story).with(story)
89
- @tokenizer.process_line(line)
90
- end
91
-
92
- it "sends a nested tokenized note to the parser" do
93
- line = '| Optionally support SSL'
94
- notes = line[4..-1]
95
-
96
- @parser.expects(:handle_notes).with(notes)
97
- @tokenizer.process_line(line)
98
- end
99
-
100
- it "sends a tokenized author to the parser" do
101
- line = '- Manfred Stienstra, manfred@fngtps.com'
102
- author = Saga::Tokenizer.tokenize_author(line)
103
-
104
- @parser.expects(:handle_author).with(author)
105
- @tokenizer.process_line(line)
106
- end
107
-
108
- it "sends a tokenized definition to the parser" do
109
- line = 'Author: Someone who writes'
110
- definition = Saga::Tokenizer.tokenize_definition(line)
111
-
112
- @parser.expects(:handle_definition).with(definition)
113
- @tokenizer.process_line(line)
114
- end
115
-
116
- it "send a tokenize defintion to the parser (slighly more complex)" do
117
- line = 'Search and retrieval: Stories related to selecting and retrieving recordings.'
118
- definition = Saga::Tokenizer.tokenize_definition(line)
119
-
120
- @parser.expects(:handle_definition).with(definition)
121
- @tokenizer.process_line(line)
122
- end
123
-
124
- it "forwards plain strings to the parser" do
125
- [
126
- 'Requirements User Application',
127
- 'USER STORIES',
128
- ''
129
- ].each do |line|
130
- @parser.expects(:handle_string).with(line)
131
- @tokenizer.process_line(line)
132
- end
133
- end
134
-
135
- it "processes lines from the input" do
136
- input = File.read(File.expand_path("../cases/story.txt", __FILE__))
137
- count = input.split("\n").length
138
- @tokenizer.expects(:process_line).times(count)
139
- @tokenizer.process(input)
140
- end
141
- end
@@ -1,11 +0,0 @@
1
- begin
2
- require 'rubygems'
3
- rescue LoadError
4
- end
5
-
6
- require 'bacon'
7
- require 'mocha-on-bacon'
8
-
9
- Bacon.extend Bacon::TapOutput
10
- $:.unshift(File.expand_path('../../lib', __FILE__))
11
- require 'saga'