pivotal_doc 1.1.0

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.
Files changed (48) hide show
  1. data/.gitignore +5 -0
  2. data/README +37 -0
  3. data/Rakefile +49 -0
  4. data/VERSION +1 -0
  5. data/assets/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  6. data/assets/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  7. data/assets/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
  8. data/assets/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  9. data/assets/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  10. data/assets/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  11. data/assets/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  12. data/assets/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  13. data/assets/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  14. data/assets/css/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
  15. data/assets/css/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
  16. data/assets/css/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
  17. data/assets/css/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
  18. data/assets/css/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
  19. data/assets/css/ui-lightness/jquery-ui-1.8.5.custom.css +572 -0
  20. data/assets/js/jquery-1.4.2.min.js +154 -0
  21. data/assets/js/jquery-ui-1.8.5.custom.min.js +778 -0
  22. data/ext/date.rb +9 -0
  23. data/lib/pivotal_doc/configuration.rb +37 -0
  24. data/lib/pivotal_doc/exceptions.rb +22 -0
  25. data/lib/pivotal_doc/generator.rb +30 -0
  26. data/lib/pivotal_doc/generators/base.rb +52 -0
  27. data/lib/pivotal_doc/generators/html.rb +14 -0
  28. data/lib/pivotal_doc/generators/text.rb +12 -0
  29. data/lib/pivotal_doc/release.rb +50 -0
  30. data/lib/pivotal_doc.rb +14 -0
  31. data/pivotal_doc.gemspec +106 -0
  32. data/spec/fixtures/configs.yml +11 -0
  33. data/spec/fixtures/iterations.yml +4 -0
  34. data/spec/fixtures/projects.yml +11 -0
  35. data/spec/fixtures/stories.yml +87 -0
  36. data/spec/lib/configuration_spec.rb +88 -0
  37. data/spec/lib/generator_spec.rb +57 -0
  38. data/spec/lib/generators/base_spec.rb +64 -0
  39. data/spec/lib/generators/html_spec.rb +40 -0
  40. data/spec/lib/generators/text_spec.rb +25 -0
  41. data/spec/lib/release_spec.rb +92 -0
  42. data/spec/spec_helper.rb +9 -0
  43. data/spec/support/mocks_helper.rb +31 -0
  44. data/spec/support/pt_api_helpers.rb +42 -0
  45. data/templates/fancy.haml +74 -0
  46. data/templates/html_gen.haml +53 -0
  47. data/templates/text_gen.txt +0 -0
  48. metadata +164 -0
data/ext/date.rb ADDED
@@ -0,0 +1,9 @@
1
+ class Date
2
+ def standard_format
3
+ self.strftime("%m-%d-%Y")
4
+ end
5
+
6
+ def fancy_format
7
+ self.strftime("%b %d, %Y")
8
+ end
9
+ end
@@ -0,0 +1,37 @@
1
+ module PivotalDoc
2
+ class Configuration
3
+ attr_accessor :settings
4
+ attr_reader :authenticated
5
+ alias :authenticated? :authenticated
6
+
7
+ def initialize(settings)
8
+ @settings= settings.respond_to?(:merge) ? settings : YAML::load(File.new(settings))
9
+ end
10
+
11
+ def projects
12
+ self.settings['projects']
13
+ end
14
+
15
+ def output_path
16
+ self.settings['output_path']
17
+ end
18
+
19
+ def authenticate!
20
+ return if @authenticated
21
+ connection.token ? PT::Client.token=connection.token : PT::Client.token(connection.username, connection.password)
22
+ @authenticated= true
23
+ end
24
+
25
+ private
26
+ def connection
27
+ return @connection if @connection
28
+ @connection= Connection.new
29
+ @connection.token= settings['token']
30
+ @connection.username= settings['username']
31
+ @connection.password= settings['password']
32
+ @connection
33
+ end
34
+ end
35
+
36
+ class Connection < Struct.new(:token, :username, :password); end
37
+ end
@@ -0,0 +1,22 @@
1
+ module PivotalDoc
2
+ class PivotalDocException < Exception
3
+ end
4
+ class FormatNotSupported < PivotalDocException
5
+ def initialize(format)
6
+ @format= format
7
+ end
8
+
9
+ def message
10
+ "The format (#{@format}) is not currently supported"
11
+ end
12
+ end
13
+ class TemplateNonExistent < PivotalDocException
14
+ def initialize(template_name)
15
+ @template_name= template_name
16
+ end
17
+
18
+ def message
19
+ "The template named \"#{@template_name}\" doesn't exist?"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,30 @@
1
+ module PivotalDoc
2
+ class Generator
3
+ class << self
4
+ attr_accessor :releases
5
+ attr_reader :config
6
+
7
+ def generate(format, settings={})
8
+ @config= PivotalDoc::Configuration.new(settings)
9
+ @config.authenticate!
10
+ raise FormatNotSupported.new(format) unless generators.has_key?(format)
11
+ collect_releases!
12
+ releases.each do |release|
13
+ generators[format].new(release, config.settings).render_doc
14
+ end
15
+ true
16
+ end
17
+
18
+ def generators
19
+ { :text=>Generators::Text, :html=>Generators::HTML }
20
+ end
21
+
22
+ def collect_releases!
23
+ @releases= []
24
+ self.config.projects.each do |name, _attrs|
25
+ @releases << Release.new(PT::Project.find(_attrs['id'].to_i))
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,52 @@
1
+ module PivotalDoc
2
+ module Generators
3
+ class Base
4
+ def initialize(release, options={})
5
+ @release= release
6
+ @options= options
7
+ end
8
+
9
+ def output_path
10
+ @options['output_path'] || absolute_path
11
+ end
12
+
13
+ def output_file
14
+ name= @options['output_file']
15
+ unless name
16
+ name=@release.name || self.object_id.to_s
17
+ name.gsub!(/\//, '') and name.gsub!(/\s/,'')
18
+ end
19
+ File.join(output_path, (name + output_ext))
20
+ end
21
+
22
+ def output_ext; '.default' end
23
+
24
+ def absolute_path
25
+ File.dirname(__FILE__)
26
+ end
27
+
28
+ def render_doc(output='')
29
+ begin
30
+ FileUtils.mkdir_p(output_path)
31
+ f= File.open(self.output_file, 'w+')
32
+ f.write(output)
33
+ rescue Exception=>e
34
+ $stdout.print(e.message)
35
+ $stdout.flush
36
+ ensure
37
+ f.close if f
38
+ end
39
+ end
40
+
41
+ def template
42
+ path= File.join(PROJECT_ROOT, 'templates', template_name)
43
+ raise TemplateNonExistent.new(template_name) unless File.exists?(path)
44
+ @template ||= File.read(path)
45
+ end
46
+
47
+ def template_name
48
+ raise 'Not Implemented!'
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,14 @@
1
+ module PivotalDoc
2
+ module Generators
3
+ class HTML < Base
4
+ def template_name
5
+ @options[:template_name] || 'html_gen.haml'
6
+ end
7
+ def output_ext; '.html' end
8
+ def render_doc
9
+ html= Haml::Engine.new(template).render(Object.new, {:release=>@release})
10
+ super(html)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ module PivotalDoc
2
+ module Generators
3
+ class Text < Base
4
+ def template_name; 'text_gen.txt' end
5
+ def output_ext; '.txt' end
6
+ def output; '' end
7
+ def render_doc
8
+ super(output)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,50 @@
1
+ module PivotalDoc
2
+ class Release
3
+ attr_reader :project
4
+ attr_reader :iteration
5
+
6
+ def initialize(project, iteration=nil)
7
+ @project= project
8
+ @iteration= (iteration || latest_iteration)
9
+ end
10
+
11
+ def me
12
+ @me ||= self.iteration.stories.detect{|s| s.story_type.downcase=='release'} if self.iteration.stories
13
+ end
14
+
15
+ def name
16
+ me.name if me.respond_to?(:name)
17
+ end
18
+
19
+ def project_name
20
+ @project.name
21
+ end
22
+
23
+ def latest_iteration
24
+ PT::Iteration.done(@project, :offset=>'-1').first
25
+ end
26
+
27
+ def stories
28
+ @stories ||= filter_stories
29
+ end
30
+
31
+ def bugs
32
+ @bugs ||= filter_stories('bug')
33
+ end
34
+
35
+ def chores
36
+ @chores ||= filter_stories('chore')
37
+ end
38
+
39
+ [:stories, :bugs, :chores].each do |m|
40
+ define_method("#{m}_delivered") { self.send(m).size }
41
+ end
42
+
43
+ private
44
+ def filter_stories(type='feature')
45
+ self.iteration.stories.reject do |s|
46
+ s.story_type.downcase != type || s.current_state.downcase != 'accepted'
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'yaml'
3
+ require 'pivotal-tracker'
4
+ require 'haml'
5
+ PT= PivotalTracker unless defined?(PT)
6
+ PROJECT_ROOT= File.join(File.dirname(__FILE__), '/../') unless defined?(PROJECT_ROOT)
7
+
8
+ Dir[File.expand_path(File.join(File.dirname(__FILE__),'../ext','**','*.rb'))].each {|f| require f}
9
+ Dir[File.expand_path(File.join(File.dirname(__FILE__),'pivotal_doc/','**','*.rb'))].each {|f| require f}
10
+
11
+ if ENV['mode'] == 'test'
12
+ require 'spec'
13
+ require 'spec/autorun'
14
+ end
@@ -0,0 +1,106 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{pivotal_doc}
8
+ s.version = "1.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Tim Linquist"]
12
+ s.date = %q{2010-10-29}
13
+ s.description = %q{
14
+ Automated release notes for apps hosted on pivotaltracker.com.
15
+ Allows release notes to be generated for any project on pivotaltracker.com by retrieving the latest iteration for the specified project and displaying the completed features, bugs, and chores.
16
+ }
17
+ s.email = %q{tim.linquist@gmail.com}
18
+ s.extra_rdoc_files = [
19
+ "README"
20
+ ]
21
+ s.files = [
22
+ ".gitignore",
23
+ "README",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "assets/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png",
27
+ "assets/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png",
28
+ "assets/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png",
29
+ "assets/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png",
30
+ "assets/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png",
31
+ "assets/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png",
32
+ "assets/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png",
33
+ "assets/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png",
34
+ "assets/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png",
35
+ "assets/css/ui-lightness/images/ui-icons_222222_256x240.png",
36
+ "assets/css/ui-lightness/images/ui-icons_228ef1_256x240.png",
37
+ "assets/css/ui-lightness/images/ui-icons_ef8c08_256x240.png",
38
+ "assets/css/ui-lightness/images/ui-icons_ffd27a_256x240.png",
39
+ "assets/css/ui-lightness/images/ui-icons_ffffff_256x240.png",
40
+ "assets/css/ui-lightness/jquery-ui-1.8.5.custom.css",
41
+ "assets/js/jquery-1.4.2.min.js",
42
+ "assets/js/jquery-ui-1.8.5.custom.min.js",
43
+ "ext/date.rb",
44
+ "lib/pivotal_doc.rb",
45
+ "lib/pivotal_doc/configuration.rb",
46
+ "lib/pivotal_doc/exceptions.rb",
47
+ "lib/pivotal_doc/generator.rb",
48
+ "lib/pivotal_doc/generators/base.rb",
49
+ "lib/pivotal_doc/generators/html.rb",
50
+ "lib/pivotal_doc/generators/text.rb",
51
+ "lib/pivotal_doc/release.rb",
52
+ "pivotal_doc.gemspec",
53
+ "spec/fixtures/configs.yml",
54
+ "spec/fixtures/iterations.yml",
55
+ "spec/fixtures/projects.yml",
56
+ "spec/fixtures/stories.yml",
57
+ "spec/lib/configuration_spec.rb",
58
+ "spec/lib/generator_spec.rb",
59
+ "spec/lib/generators/base_spec.rb",
60
+ "spec/lib/generators/html_spec.rb",
61
+ "spec/lib/generators/text_spec.rb",
62
+ "spec/lib/release_spec.rb",
63
+ "spec/spec_helper.rb",
64
+ "spec/support/mocks_helper.rb",
65
+ "spec/support/pt_api_helpers.rb",
66
+ "templates/fancy.haml",
67
+ "templates/html_gen.haml",
68
+ "templates/text_gen.txt"
69
+ ]
70
+ s.homepage = %q{http://github.com/timo3377/pivotal_doc}
71
+ s.rdoc_options = ["--charset=UTF-8"]
72
+ s.require_paths = ["lib"]
73
+ s.rubygems_version = %q{1.3.7}
74
+ s.summary = %q{A release documentation generator for pivotaltracker.com}
75
+ s.test_files = [
76
+ "spec/lib/configuration_spec.rb",
77
+ "spec/lib/generator_spec.rb",
78
+ "spec/lib/generators/base_spec.rb",
79
+ "spec/lib/generators/html_spec.rb",
80
+ "spec/lib/generators/text_spec.rb",
81
+ "spec/lib/release_spec.rb",
82
+ "spec/spec_helper.rb",
83
+ "spec/support/mocks_helper.rb",
84
+ "spec/support/pt_api_helpers.rb"
85
+ ]
86
+
87
+ if s.respond_to? :specification_version then
88
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
89
+ s.specification_version = 3
90
+
91
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
92
+ s.add_runtime_dependency(%q<pivotal-tracker>, [">= 0.2.1"])
93
+ s.add_runtime_dependency(%q<haml>, [">= 0"])
94
+ s.add_development_dependency(%q<rspec>, [">= 0"])
95
+ else
96
+ s.add_dependency(%q<pivotal-tracker>, [">= 0.2.1"])
97
+ s.add_dependency(%q<haml>, [">= 0"])
98
+ s.add_dependency(%q<rspec>, [">= 0"])
99
+ end
100
+ else
101
+ s.add_dependency(%q<pivotal-tracker>, [">= 0.2.1"])
102
+ s.add_dependency(%q<haml>, [">= 0"])
103
+ s.add_dependency(%q<rspec>, [">= 0"])
104
+ end
105
+ end
106
+
@@ -0,0 +1,11 @@
1
+ username: humpie
2
+ password: dome
3
+ token: some_funky_guid
4
+ projects:
5
+ github:
6
+ id: 1
7
+ members:
8
+ - [
9
+ 'hot.box@superhighme.com',
10
+ 'hammer.time@rockyajaw.com'
11
+ ]
@@ -0,0 +1,4 @@
1
+ - finish: 2010-08-31T07:00:00+00:00
2
+ id: 1
3
+ number: 1
4
+ start: 2010-08-10T07:00:00+00:00
@@ -0,0 +1,11 @@
1
+ - account: Awesome Guys
2
+ current_velocity: 3
3
+ id: 42411
4
+ initial_velocity: 4
5
+ iteration_length: 3
6
+ last_activity_at: 2010-09-16T19:41:29+00:00
7
+ name: My Hotness
8
+ point_scale: "0,1,2,3"
9
+ use_https: false
10
+ velocity_scheme: Average of 3 iterations
11
+ week_start_day: Tuesday
@@ -0,0 +1,87 @@
1
+ - accepted_at: 2010-08-30T16:14:23+00:00
2
+ attachments: []
3
+ created_at: 2010-08-05T18:09:40+00:00
4
+ current_state: Delivered
5
+ description: Deploy core component of app to staging.
6
+ estimate: 2
7
+ id: 1
8
+ integration_id:
9
+ jira_id:
10
+ jira_url:
11
+ labels:
12
+ name: Create staging env for app
13
+ other_id:
14
+ owned_by: Tim Linquist
15
+ project_id: 42411
16
+ requested_by: Tim Linquist
17
+ story_type: feature
18
+ url: http://www.pivotaltracker.com/story/show/1,
19
+
20
+ - created_at: 2010-08-06T19:46:38+00:00
21
+ current_state: accepted
22
+ description:
23
+ estimate: 1
24
+ id: 2
25
+ integration_id:
26
+ jira_id:
27
+ jira_url:
28
+ labels:
29
+ name: Eliminate Bots from app
30
+ other_id:
31
+ owned_by: Tim Linquist
32
+ project_id: 42411
33
+ requested_by: Tim Linquist
34
+ story_type: feature
35
+ url: http://www.pivotaltracker.com/story/show/2
36
+
37
+ - created_at: 2010-08-06T19:46:38+00:00
38
+ current_state: accepted
39
+ description: MongoDB server
40
+ estimate: 2
41
+ id: 3
42
+ integration_id:
43
+ jira_id:
44
+ jira_url:
45
+ labels:
46
+ name: Mongo Master host
47
+ other_id:
48
+ owned_by: Tim Linquist
49
+ project_id: 42411
50
+ requested_by: Tim Linquist
51
+ story_type: chore
52
+ url: http://www.pivotaltracker.com/story/show/3
53
+
54
+ - created_at: 2010-08-06T19:46:38+00:00
55
+ current_state: accepted
56
+ description: The app isn't working
57
+ estimate: 2
58
+ id: 4
59
+ integration_id:
60
+ jira_id:
61
+ jira_url:
62
+ labels:
63
+ name: The app needs to work better than it does
64
+ other_id:
65
+ owned_by: Tim Linquist
66
+ project_id: 42411
67
+ requested_by: Tim Linquist
68
+ story_type: bug
69
+ url: http://www.pivotaltracker.com/story/show/4
70
+
71
+ - created_at: 2010-08-06T19:46:38+00:00
72
+ current_state: Not Yet Started
73
+ description:
74
+ estimate:
75
+ id: 5
76
+ integration_id:
77
+ jira_id:
78
+ jira_url:
79
+ labels:
80
+ name: Grateful Dead Sprint
81
+ other_id:
82
+ owned_by: Project Owner
83
+ project_id: 42411
84
+ requested_by: Product Manager
85
+ story_type: release
86
+ url: http://www.pivotaltracker.com/story/show/5
87
+
@@ -0,0 +1,88 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe PivotalDoc::Configuration do
4
+ before(:each) do
5
+ @connection= PivotalDoc::Connection.new('A18das1', 'radical', 'dude')
6
+ @config= PivotalDoc::Configuration.new(File.join(File.dirname(__FILE__), '/../fixtures/', 'configs.yml'))
7
+ end
8
+
9
+ it "should load the settings from the file" do
10
+ @config.settings.should be_an_instance_of(Hash)
11
+ end
12
+
13
+ it "should load the settings from the options" do
14
+ settings= {:test=>'parameter'}
15
+ config= PivotalDoc::Configuration.new(settings)
16
+ config.settings.should eql(settings)
17
+ end
18
+
19
+ describe "Authenticating" do
20
+ before(:each) do
21
+ @config.instance_variable_set(:@connection, @connection)
22
+ end
23
+
24
+ after(:each) do
25
+ @config.instance_variable_set(:@authenticated, false)
26
+ end
27
+
28
+ it "should set the token if it's configured" do
29
+ PT::Client.should_receive(:token=).with(@connection.token)
30
+ @config.authenticate!
31
+ end
32
+
33
+ it "should set the token via the username & password if the token isn't configured" do
34
+ @connection.token= nil
35
+ PT::Client.should_receive(:token).with(@connection.username, @connection.password)
36
+ @config.authenticate!
37
+ end
38
+
39
+ it "should not set the token again if the client is already authenticated" do
40
+ PT::Client.should_receive(:token=).exactly(:once)
41
+ @config.authenticate!
42
+ @config.authenticate!
43
+ end
44
+ end
45
+
46
+ describe "A Project" do
47
+ before(:each) do
48
+ @projects= @config.projects
49
+ @project= @projects.fetch(@projects.keys.first)
50
+ end
51
+
52
+ it "should know all of the projects" do
53
+ @projects.should_not be_empty
54
+ end
55
+
56
+ it "should know the members" do
57
+ @project['members'].should be_an_instance_of(Array)
58
+ end
59
+
60
+ it "should know its id" do
61
+ @project['id'].should be_an_instance_of(Fixnum)
62
+ end
63
+ end
64
+
65
+ describe "Connection" do
66
+ after(:each) do
67
+ @config.instance_variable_set(:@connection, nil)
68
+ end
69
+
70
+ [:token, :username, :password].each do |property|
71
+ connection= PivotalDoc::Connection.new
72
+ it "should have the #{property} property" do
73
+ connection.should respond_to(property)
74
+ end
75
+ end
76
+
77
+ it "should not redefine the connection" do
78
+ PivotalDoc::Connection.should_receive(:new).exactly(:once).and_return(@connection)
79
+ @config.send(:connection)
80
+ end
81
+
82
+ it "should default to the config.yml settings" do
83
+ %w(token username password).each do |_attr|
84
+ @config.send(:connection).send(_attr.to_sym).should eql(@config.settings[_attr])
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,57 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe PivotalDoc::Generator do
4
+ before(:each) do
5
+ @config= PivotalDoc::Configuration.new(File.join(File.dirname(__FILE__), '/../fixtures/', 'configs.yml'))
6
+ PivotalDoc::Configuration.stub!(:new).and_return(@config)
7
+ PivotalDoc::Generator.generators.values.each do |g|
8
+ generator= mock(g.to_s)
9
+ g.stub!(:new).and_return(generator)
10
+ generator.stub!(:render_doc)
11
+ end
12
+ end
13
+
14
+ describe "Configuring" do
15
+ before(:each) do
16
+ PivotalDoc::Generator.stub!(:collect_releases!)
17
+ PivotalDoc::Generator.releases= []
18
+ end
19
+
20
+ it "should create a config object from the settings" do
21
+ settings= {}
22
+ @config.stub!(:authenticate!)
23
+ PivotalDoc::Configuration.should_receive(:new).with(settings).and_return(@config)
24
+ PivotalDoc::Generator.generate(:html, settings)
25
+ PivotalDoc::Generator.config.should eql(@config)
26
+ end
27
+
28
+ it "should authenticate against pivotal before generating the release docs" do
29
+ @config.should_receive(:authenticate!)
30
+ PivotalDoc::Generator.generate(:html)
31
+ end
32
+ end
33
+
34
+ describe "generation" do
35
+ before(:each) do
36
+ @config.stub!(:authenticate!).and_return(true)
37
+ @release= mocks_helper(:release)
38
+ PT::Project.stub!(:find).and_return(@release.project)
39
+ PivotalDoc::Release.stub!(:new).and_return(@release)
40
+ end
41
+
42
+ describe "Formattting" do
43
+ before(:each) do
44
+ @options={:my_custom_option=>'my custom value'}
45
+ @html_gen= PivotalDoc::Generators::HTML.new({})
46
+ @html_gen.stub!(:render_doc)
47
+ end
48
+ it "should render the release with the specified format and custom settings" do
49
+ PivotalDoc::Generators::HTML.should_receive(:new).with(@release, @config.settings).and_return(@html_gen)
50
+ PivotalDoc::Generator.generate(:html)
51
+ end
52
+ it "should raise an error if the specified format isn't supported" do
53
+ lambda{ PivotalDoc::Generator.generate(:unsupported) }.should raise_error(PivotalDoc::FormatNotSupported)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,64 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe PivotalDoc::Generators::Base do
4
+ before(:each) do
5
+ @release= mocks_helper(:release)
6
+ @base= PivotalDoc::Generators::Base.new(@release)
7
+ end
8
+ it "should raise an exception if the template doesn't exist" do
9
+ @base.stub!(:template_name).and_return('non-existent.txt')
10
+ lambda{@base.template}.should raise_error(PivotalDoc::TemplateNonExistent)
11
+ end
12
+
13
+ describe "Rendering the doc" do
14
+ before(:each) do
15
+ @base.stub!(:template).and_return('index.txt')
16
+ end
17
+
18
+ after(:each) do
19
+ File.delete(@base.output_file) if File.exists?(@base.output_file)
20
+ end
21
+
22
+ describe "options" do
23
+ it "should be a fully qualified file" do
24
+ base= PivotalDoc::Generators::Base.new(@release, {:output_file=>'my_file'})
25
+ f= File.open(base.output_file, 'w')
26
+ f.should be_an_instance_of(File)
27
+ File.delete(f.path)
28
+ end
29
+
30
+ it "should use the output_file if present" do
31
+ base= PivotalDoc::Generators::Base.new(@release, {'output_file'=>'my_file'})
32
+ base.output_file.should =~ /\/my_file/
33
+ end
34
+
35
+ it "should default the output_file to the release's name (unique filename for multiple projects)" do
36
+ base= PivotalDoc::Generators::Base.new(@release)
37
+ base.output_file.should =~ /\/#{@release.name}/
38
+ end
39
+
40
+ it "should use the output_path if present" do
41
+ base= PivotalDoc::Generators::Base.new(@release, {'output_path'=>'my_path'})
42
+ base.output_path.should =~ /^my_path/
43
+ end
44
+
45
+ it "should default the output_path to the relative directory" do
46
+ base= PivotalDoc::Generators::Base.new(@release)
47
+ base.output_path.should =~ /^#{base.absolute_path}/
48
+ end
49
+ end
50
+
51
+ it "should open the output file and write the output" do
52
+ output= 'My custom output'
53
+ @base.render_doc(output)
54
+ File.read(@base.output_file).should eql(output)
55
+ end
56
+
57
+ it "should handle any exceptions and output STDOUT" do
58
+ File.stub!(:open).and_raise(Exception.new('A MAJOR CATASTROPHE'))
59
+ $stdout.should_receive(:print).with('A MAJOR CATASTROPHE')
60
+ $stdout.should_receive(:flush)
61
+ @base.render_doc
62
+ end
63
+ end
64
+ end