rhet-butler 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/bin/rhet-butler +5 -0
  2. data/default-configuration/assets/apple-touch-icon-precomposed.png +0 -0
  3. data/default-configuration/assets/apple-touch-icon.png +0 -0
  4. data/default-configuration/assets/favicon.ico +0 -0
  5. data/default-configuration/assets/fonts/opensans/v6/MTP_ySUJH_bn48VBG8sNSonF5uFdDttMLvmWuJdhhgs.ttf +0 -0
  6. data/default-configuration/assets/fonts/opensans/v6/PRmiXeptR36kaC0GEAetxi8cqLH4MEiSE0ROcU-qHOA.ttf +0 -0
  7. data/default-configuration/assets/fonts/opensans/v6/cJZKeOuBrn4kERxqtaUH3aCWcynf_cDxXwCLxiixG1c.ttf +0 -0
  8. data/default-configuration/assets/fonts/opensans/v6/xjAJXh38I15wypJXxuGMBp0EAVxt0G0biEntp43Qt6E.ttf +0 -0
  9. data/default-configuration/assets/fonts/ptsans/v5/0XxGQsSc1g4rdRdjJKZrNC3USBnSvpkopQaUR-2r7iU.ttf +0 -0
  10. data/default-configuration/assets/fonts/ptsans/v5/FUDHvzEKSJww3kCxuiAo2A.ttf +0 -0
  11. data/default-configuration/assets/fonts/ptsans/v5/PIPMHY90P7jtyjpXuZ2cLKCWcynf_cDxXwCLxiixG1c.ttf +0 -0
  12. data/default-configuration/assets/fonts/ptsans/v5/lILlYDvubYemzYzN7GbLkInF5uFdDttMLvmWuJdhhgs.ttf +0 -0
  13. data/default-configuration/assets/fonts/ptserif/v5/03aPdn7fFF3H6ngCgAlQzC3USBnSvpkopQaUR-2r7iU.ttf +0 -0
  14. data/default-configuration/assets/fonts/ptserif/v5/EgBlzoNBIHxNPCMwXaAhYPesZW2xOQ-xsNqO47m55DA.ttf +0 -0
  15. data/default-configuration/assets/fonts/ptserif/v5/Foydq9xJp--nfYIx2TBz9fEr6Hm6RMS0v1dtXsGir4g.ttf +0 -0
  16. data/default-configuration/assets/fonts/ptserif/v5/QABk9IxT-LFTJ_dQzv7xpJ0EAVxt0G0biEntp43Qt6E.ttf +0 -0
  17. data/default-configuration/assets/javascript/highlight.js/LICENSE +24 -0
  18. data/default-configuration/assets/javascript/highlight.js/README.md +143 -0
  19. data/default-configuration/assets/javascript/highlight.js/README.ru.md +149 -0
  20. data/default-configuration/assets/javascript/highlight.js/classref.txt +568 -0
  21. data/default-configuration/assets/javascript/highlight.pack.js +1 -0
  22. data/default-configuration/assets/javascript/impress.js +800 -0
  23. data/default-configuration/assets/javascript/sockjs-0.2.1.js +2014 -0
  24. data/default-configuration/assets/javascript/sockjs-0.3.js +2314 -0
  25. data/default-configuration/assets/rhet-butler.jpg +0 -0
  26. data/default-configuration/assets/stylesheets/google-open-sans.css +72 -0
  27. data/default-configuration/assets/stylesheets/highlight/solarized_dark.css +88 -0
  28. data/default-configuration/assets/stylesheets/presentation.css +483 -0
  29. data/default-configuration/assets/stylesheets/presenter/presentation.css +477 -0
  30. data/default-configuration/assets/stylesheets/setup.css +0 -0
  31. data/default-configuration/common/config.yaml +4 -0
  32. data/default-configuration/common/templates/header-javascript.html +3 -0
  33. data/default-configuration/common/templates/presentation.html.erb +44 -0
  34. data/default-configuration/common/templates/presenter-qr.html.erb +77 -0
  35. data/default-configuration/common/templates/stylesheets.html.erb +3 -0
  36. data/default-configuration/presenter/config.yaml +7 -0
  37. data/default-configuration/presenter/templates/live-javascript.html.erb +26 -0
  38. data/default-configuration/presenter/templates/slide-notes.html.erb +3 -0
  39. data/default-configuration/presenter/templates/stylesheets.html.erb +3 -0
  40. data/default-configuration/viewer/config.yaml +7 -0
  41. data/default-configuration/viewer/templates/live-javascript.html.erb +16 -0
  42. data/default-configuration/viewer/templates/slide-notes.html.erb +0 -0
  43. data/lib/rhet-butler/arrangement.rb +78 -0
  44. data/lib/rhet-butler/command-line.rb +49 -0
  45. data/lib/rhet-butler/configuration.rb +76 -0
  46. data/lib/rhet-butler/file-manager.rb +126 -0
  47. data/lib/rhet-butler/html-generator.rb +29 -0
  48. data/lib/rhet-butler/layout-rule.rb +57 -0
  49. data/lib/rhet-butler/messaging.rb +58 -0
  50. data/lib/rhet-butler/slide-group.rb +56 -0
  51. data/lib/rhet-butler/slide-includer.rb +34 -0
  52. data/lib/rhet-butler/slide-loader.rb +361 -0
  53. data/lib/rhet-butler/slide.rb +164 -0
  54. data/lib/rhet-butler/static-generator.rb +44 -0
  55. data/lib/rhet-butler/web/assets-app.rb +40 -0
  56. data/lib/rhet-butler/web/main-app.rb +139 -0
  57. data/lib/rhet-butler/web/presentation-app.rb +50 -0
  58. data/lib/rhet-butler/web/qr-display-app.rb +37 -0
  59. data/lib/rhet-butler/yaml-schema.rb +9 -0
  60. data/lib/rhet-butler/yaml-type.rb +23 -0
  61. data/lib/rhet-butler.rb +2 -0
  62. data/spec/arrangements.rb +76 -0
  63. data/spec/html-generation.rb +48 -0
  64. data/spec/presentation-view.rb +72 -0
  65. data/spec/rhet-butler.rb +59 -0
  66. data/spec/slide-loader.rb +51 -0
  67. data/spec/slide-processing.rb +73 -0
  68. data/spec_support/gem_test_suite.rb +17 -0
  69. metadata +324 -0
@@ -0,0 +1,139 @@
1
+ require 'rack/builder'
2
+ require 'rack/handler'
3
+ require 'thin'
4
+ require 'rhet-butler/web/presentation-app'
5
+ require 'rhet-butler/web/assets-app'
6
+ require 'rhet-butler/web/qr-display-app'
7
+ require 'rhet-butler/file-manager'
8
+ require 'rhet-butler/messaging'
9
+
10
+
11
+ module RhetButler
12
+ module Web
13
+ class SelectiveAuth < Rack::Auth::Basic
14
+ def call(env)
15
+ #XXX This is to work around a Chrome bug:
16
+ #https://code.google.com/p/chromium/issues/detail?id=123862 #ok
17
+ #When fixed upstream, this'll come out and we'll stop supporting old
18
+ #versions of Chrome.
19
+ #As is, under SSL this is kinda secure (i.e. not at all) because the
20
+ #WS details are secret
21
+ if /^http/ =~ env["rack.url_scheme"] and env["HTTP_UPGRADE"] != "websocket"
22
+ super
23
+ else
24
+ @app.call(env)
25
+ end
26
+ end
27
+ end
28
+
29
+ class MainApp
30
+ def initialize(file_manager)
31
+ @file_manager = file_manager
32
+ end
33
+
34
+ # Notes re filesets config and slides:
35
+ # All PresentationApps need the same slides but different configs
36
+ # (including templates, etc.)
37
+ #
38
+ # So: there need to be TWO valises:
39
+ #
40
+ # 1) The slides valise - including slidesets that might get included -
41
+ # this one is common between all Apps
42
+ #
43
+ # 2) The config valise - there should be a "common" base to this, and a
44
+ # role specific variation. Built special, because the /viewer app should
45
+ # allow for config in the root of the project etc, while the /presenter
46
+ # version should require special config (since I'm assuming a boring
47
+ # presentation view)
48
+ #
49
+ def slides
50
+ @file_manager.slide_files
51
+ end
52
+
53
+ #Simply renders the bodies of the viewer and presenter apps to make sure
54
+ #there aren't any exceptions
55
+ def check
56
+ viewer_app = PresentationApp.new(:viewer, @file_manager)
57
+ presenter_app = PresentationApp.new(:presenter, @file_manager)
58
+ viewer_app.body
59
+ presenter_app.body
60
+ #XXX static generator "populate assets" - make sure all the assets
61
+ #render as well
62
+ end
63
+
64
+ def build_authentication_block(creds_config)
65
+ return (proc do |user, pass|
66
+ creds_config.username == user &&
67
+ creds_config.password == pass
68
+ end)
69
+ end
70
+
71
+ def app
72
+ sockjs_options = {
73
+ :sockjs_url => "/assets/javascript/sockjs-0.2.1.js",
74
+ :queue => SlideMessageQueue.new
75
+ }
76
+
77
+ viewer_app = PresentationApp.new(:viewer, @file_manager)
78
+ presenter_app = PresentationApp.new(:presenter, @file_manager)
79
+ assets_app = AssetsApp.new(@file_manager)
80
+ qr_app = QrDisplayApp.new(@file_manager, "/presenter")
81
+ presenter_config = presenter_app.configuration
82
+ auth_validation = build_authentication_block(presenter_config)
83
+
84
+ Rack::Builder.new do
85
+ #SockJS.debug!
86
+
87
+ map "/live/follower" do
88
+ run Rack::SockJS.new(FollowerSession, sockjs_options)
89
+ end
90
+
91
+ map "/live/leader" do
92
+ use SelectiveAuth, "Rhet Butler Presenter", &auth_validation
93
+ run Rack::SockJS.new(LeaderSession, sockjs_options)
94
+ end
95
+
96
+ use Rack::ShowExceptions
97
+
98
+ map "/assets" do
99
+ run assets_app
100
+ end
101
+
102
+ map "/qr" do
103
+ run qr_app
104
+ end
105
+
106
+ map "/presenter" do
107
+ use SelectiveAuth, "Rhet Butler Presenter", &auth_validation
108
+ run presenter_app
109
+ end
110
+
111
+ run lambda{|env|
112
+ if env["PATH_INFO"] == "/"
113
+ viewer_app.call(env)
114
+ else
115
+ assets_app.call(env)
116
+ end
117
+ }
118
+ end
119
+ end
120
+
121
+ def start
122
+ configuration = @file_manager.base_config
123
+
124
+ puts "Starting server. Try one of these:"
125
+ require 'system/getifaddrs'
126
+ System.get_all_ifaddrs.each do |interface|
127
+ puts " http://#{interface[:inet_addr].to_s}:#{configuration.serve_port}/"
128
+ puts " http://#{interface[:inet_addr].to_s}:#{configuration.serve_port}/qr"
129
+ end
130
+ EM.run do
131
+ thin = Rack::Handler.get("thin")
132
+ thin.run(app.to_app, :Host => "0.0.0.0", :Port => configuration.serve_port) do |server|
133
+ server.threaded = true
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,50 @@
1
+ require 'rhet-butler/html-generator'
2
+ require 'rhet-butler/slide-loader'
3
+
4
+ module RhetButler
5
+ module Web
6
+ class PresentationApp
7
+ def initialize(aspect, file_manager)
8
+ @file_manager = file_manager
9
+ @aspect = aspect
10
+ end
11
+
12
+ def configuration
13
+ @file_manager.aspect_config(@aspect)
14
+ end
15
+
16
+ def template_handler
17
+ @file_manager.aspect_templates(@aspect)
18
+ end
19
+
20
+ def slides_valise
21
+ @file_manager.slide_files
22
+ end
23
+
24
+ def slides
25
+ @slides ||=
26
+ begin
27
+ slide_loader = SlideLoader.new(slides_valise, configuration)
28
+ slide_loader.load_slides
29
+ end
30
+ end
31
+
32
+ def html_generator
33
+ @html_generator ||=
34
+ begin
35
+ generator = HTMLGenerator.new(configuration, template_handler)
36
+ generator.slides = slides
37
+ generator
38
+ end
39
+ end
40
+
41
+ def body
42
+ @body ||= html_generator.render(configuration.root_slide_template)
43
+ end
44
+
45
+ def call(env)
46
+ [200, {'Content-Type' => "text/html"}, [body]]
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,37 @@
1
+ require 'rqrcode'
2
+
3
+ module RhetButler
4
+ module Web
5
+ class QrDisplayApp
6
+ def initialize(files, path)
7
+ @config = files.aspect_config(:presenter)
8
+ @templates = files.aspect_templates(:presenter)
9
+ @path = path
10
+ end
11
+
12
+ attr_reader :template_handler
13
+
14
+ def call(env)
15
+ url = [env["rack.url_scheme"], "://"]
16
+ if env["HTTP_HOST"].nil? or env["HTTP_HOST"].empty?
17
+ url << env["SERVER_NAME"]
18
+ url << ":"
19
+ url << env["SERVER_PORT"]
20
+ else
21
+ url << env["HTTP_HOST"]
22
+ end
23
+ view_url = url.join("") + "/"
24
+
25
+ url << @path
26
+ url = url.join("")
27
+ qr = RQRCode::QRCode.new(url, :size => 5)
28
+
29
+ mime_type = "text/html"
30
+ generator = HTMLGenerator.new(@config, @templates)
31
+ [200, {'Content-Type' => mime_type}, [
32
+ generator.render("presenter-qr.html", qr, :view_url => view_url, :presenter_url => url)
33
+ ]]
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,9 @@
1
+ require 'rhet-butler/slide'
2
+ require 'rhet-butler/slide-group'
3
+ require 'rhet-butler/slide-includer'
4
+ require 'rhet-butler/layout-rule'
5
+
6
+ YAML.add_tag('!slide', RhetButler::Slide)
7
+ YAML.add_tag('!group', RhetButler::SlideGroup)
8
+ YAML.add_tag('!include', RhetButler::Includer)
9
+ YAML.add_tag('!layout-rule', RhetButler::LayoutRule)
@@ -0,0 +1,23 @@
1
+ module RhetButler
2
+ module YamlType
3
+ def check_config_hash(config_hash)
4
+ expected_keys = self.class.required_config + self.class.optional_config
5
+ weird_keys = config_hash.keys.find_all{|key| !expected_keys.include?(key)}
6
+ missing_keys = self.class.required_config.find_all{|key|
7
+ !config_hash.has_key?(key)
8
+ }
9
+ unless weird_keys.empty?
10
+ warn "Found weird keys: #{weird_keys.inspect} in #{config_hash.inspect}"
11
+ end
12
+ unless missing_keys.empty?
13
+ raise "Missing required keys: #{missing_keys.inspect} in #{config_hash.inspect}"
14
+ end
15
+ end
16
+
17
+ def value_from_config(name)
18
+ if @config_hash.has_key?(name)
19
+ yield(@config_hash[name])
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,2 @@
1
+ module RhetButler
2
+ end
@@ -0,0 +1,76 @@
1
+ require 'rhet-butler/arrangement'
2
+ require 'rhet-butler/slide'
3
+ require 'rhet-butler/slide-loader'
4
+
5
+ describe RhetButler::Arrangement do
6
+ let :slides do
7
+ (1..5).map do |num|
8
+ RhetButler::Slide.new.tap do |slide|
9
+ slide.content = "Slide ##{num}"
10
+ end
11
+ end
12
+ end
13
+
14
+ let :arranger do
15
+ arranger = RhetButler::SlideArranger.new
16
+ arranger.root_arrangement = arrangement
17
+ arranger
18
+ end
19
+
20
+ let :arranged do
21
+ arranger.traverse
22
+ arranger.slides
23
+ end
24
+
25
+ describe "digression" do
26
+ let :arrangement do
27
+ arrangement = RhetButler::Arrangement["linear"].new(1000, 0)
28
+ digression = RhetButler::Arrangement["linear-digress"].new(0, 1000)
29
+ digression.slides = (1..3).map do |num|
30
+ RhetButler::Slide.new.tap do |slide|
31
+ slide.content = "Aside ##{num}"
32
+ end
33
+ end
34
+ arrangement.slides = slides
35
+ arrangement.slides.insert(4, digression)
36
+ arrangement
37
+ end
38
+
39
+ it "should still last slide a 5000,0" do
40
+ arranged.last.position.x.should == 5000
41
+ arranged.last.position.y.should == 0
42
+ end
43
+
44
+ it "should have 8 slides" do
45
+ arranged.should have(8).slides
46
+ end
47
+
48
+ it "should put the last digression slide at 4000,3000" do
49
+ arranged[6].position.x.should == 4000
50
+ arranged[6].position.y.should == 3000
51
+ end
52
+ end
53
+
54
+ describe "horizontal" do
55
+ let :arrangement do
56
+ arrangement = RhetButler::Arrangement["horizontal"].new
57
+ arrangement.slides = slides
58
+ arrangement
59
+ end
60
+
61
+ it "should all at the same y position" do
62
+ arranged.map do |slide|
63
+ slide.position.y
64
+ end.uniq.should have(1).value
65
+ end
66
+
67
+ it "should monotonically increase x position" do
68
+ arranged.each_cons(2).map do |left, right|
69
+ right.position.x - left.position.x
70
+ end.each do |difference|
71
+ difference.should > 0
72
+ end
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,48 @@
1
+ require 'rhet-butler/html-generator'
2
+ require 'rhet-butler/file-manager'
3
+ require 'rhet-butler/slide'
4
+ require 'rhet-butler/configuration'
5
+
6
+ describe RhetButler::HTMLGenerator do
7
+ let :slides do
8
+ one = RhetButler::Slide.new
9
+ one.content = "A test slide"
10
+ [ one ]
11
+ end
12
+
13
+ let :files do
14
+ manager = RhetButler::FileManager.new
15
+ end
16
+
17
+ let :template_handler do
18
+ files.aspect_templates(:viewer)
19
+ end
20
+
21
+ let :configuration do
22
+ files.aspect_config(:viewer)
23
+ end
24
+
25
+ let :generator do
26
+ described_class.new(configuration, template_handler).tap do |gen|
27
+ gen.slides = slides
28
+ end
29
+ end
30
+
31
+ let :root_template do
32
+ "presentation.html"
33
+ end
34
+
35
+ let :html do
36
+ generator.render(root_template)
37
+ end
38
+
39
+ it "should produce text from slides" do
40
+ html.should be_a(String)
41
+ end
42
+
43
+ it "should produce good HTML" do
44
+ expect do
45
+ Nokogiri::HTML::Document.parse(html, nil, nil, Nokogiri::XML::ParseOptions::DEFAULT_XML)
46
+ end.to_not raise_error
47
+ end
48
+ end
@@ -0,0 +1,72 @@
1
+ require 'rhet-butler/web/main-app'
2
+ require 'rhet-butler/file-manager'
3
+ require 'rhet-butler/configuration'
4
+ require 'rack/test'
5
+
6
+ describe RhetButler::Web::MainApp do
7
+ describe "presentation view" do
8
+ include Rack::Test::Methods
9
+
10
+ let :files do
11
+ RhetButler::FileManager.new
12
+ end
13
+
14
+ let :app do
15
+ described_class.new(files).app
16
+ end
17
+
18
+ describe "/" do
19
+ before :each do
20
+ get "/"
21
+ end
22
+
23
+ it "should serve a presentation" do
24
+ last_response.should be_ok
25
+ end
26
+
27
+ it "should have a script tag for impress.js" do
28
+ doc = Nokogiri::HTML(last_response.body)
29
+ doc.xpath("//script[contains(@src, 'impress.js')]").should_not be_empty
30
+ end
31
+ end
32
+
33
+ describe "/javascript/impress.js" do
34
+ before :each do
35
+ get "/javascript/impress.js"
36
+ end
37
+
38
+ it "should serve the javascript" do
39
+ last_response.should be_ok
40
+ end
41
+
42
+ it "should serve as application/javascript" do
43
+ last_response.headers["Content-Type"].should == "application/javascript"
44
+ end
45
+
46
+ end
47
+
48
+ describe "/assets/javascript/impress.js" do
49
+ before :each do
50
+ get "/assets/javascript/impress.js"
51
+ end
52
+
53
+ it "should serve the javascript" do
54
+ last_response.should be_ok
55
+ end
56
+
57
+ it "should serve as application/javascript" do
58
+ last_response.headers["Content-Type"].should == "application/javascript"
59
+ end
60
+
61
+ end
62
+
63
+
64
+ it "should have get WebSocket commands to sync with presenter"
65
+
66
+ it "should be able to split from presenter"
67
+
68
+ it "should be able to resync with presenter"
69
+
70
+ it "should have a resource for the current presenter's slide"
71
+ end
72
+ end
@@ -0,0 +1,59 @@
1
+ require 'rhet-butler'
2
+
3
+ describe RhetButler do
4
+ describe "web server" do
5
+ describe "presentation view" do
6
+ it "should serve a presentation"
7
+
8
+ it "should include impress.js"
9
+
10
+ it "should have get WebSocket commands to sync with presenter"
11
+
12
+ it "should be able to split from presenter"
13
+
14
+ it "should be able to resync with presenter"
15
+
16
+ it "should have a resource for the current presenter's slide"
17
+ end
18
+
19
+ describe "passive view" do
20
+ it "should serve the presentation"
21
+
22
+ it "should not respond to key press events"
23
+ end
24
+
25
+ describe "presenter's view" do
26
+ it "should serve a presenter's view"
27
+
28
+ it "should include a link to the presentation"
29
+
30
+ it "should include the live presentation in an iframe"
31
+
32
+ it "should use a different arrangement for the presentation"
33
+ end
34
+
35
+ describe "review view" do
36
+ it "should update the slides automatically when the files change"
37
+
38
+ it "should update processed assets automatically"
39
+ end
40
+ end
41
+
42
+ describe "slide processing" do
43
+ describe "text processing" do
44
+ it "should process slide text as directed"
45
+
46
+ it "should transform Markdown to HTML"
47
+
48
+ it "should transform asset macros"
49
+
50
+ it "should insert slides from set references"
51
+
52
+ it "should nest slides from set references"
53
+ end
54
+
55
+ describe "asset handling" do
56
+ it "should process SASS files and provide CSS links"
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,51 @@
1
+ require 'valise'
2
+ require 'rhet-butler/configuration'
3
+ require 'rhet-butler/slide-loader'
4
+
5
+ describe RhetButler::SlideLoader do
6
+ let :files do
7
+ Valise::Set.define do
8
+ stemmed("slides") do
9
+ rw 'spec_support/fixtures/project'
10
+ end
11
+ rw 'spec_support/fixtures/project'
12
+
13
+ handle "config.yaml", :yaml, :hash_merge
14
+ end
15
+ end
16
+
17
+ let :configuration do
18
+ RhetButler::Configuration.new(files)
19
+ end
20
+
21
+ let :loader do
22
+ described_class.new(files, configuration)
23
+ end
24
+
25
+ let :slides do
26
+ loader.load_slides
27
+ end
28
+
29
+ it "should parse YAML for the configs" do
30
+ slides.should have_at_least(1).slides
31
+ slides.should be_all{|slide| RhetButler::Slide === slide}
32
+ end
33
+
34
+ it "should have the included slide" do
35
+ slides.find do |slide|
36
+ slide.content =~ /included/
37
+ end.should_not be_nil
38
+ end
39
+
40
+ it "should have the slide group" do
41
+ slides.find do |slide|
42
+ slide.content =~ /grouped/
43
+ end.should_not be_nil
44
+ end
45
+
46
+ it "should allow sibling inclusions" do
47
+ expect do
48
+ slides
49
+ end.not_to raise_error
50
+ end
51
+ end
@@ -0,0 +1,73 @@
1
+ require 'rhet-butler/slide-loader'
2
+
3
+ describe RhetButler::SlideProcessor do
4
+ def slide(content)
5
+ slide = RhetButler::Slide.new
6
+ slide.content = content
7
+ slide
8
+ end
9
+
10
+ def group(*slides)
11
+ group = RhetButler::SlideGroup.new
12
+ group.slides = slides
13
+ group
14
+ end
15
+
16
+ let :slides do
17
+ [
18
+ slide("A"),
19
+ slide("B"),
20
+ group(slide("C"), slide("D"), slide("E"))
21
+ ]
22
+ end
23
+
24
+ let :root_group do
25
+ group(*slides)
26
+ end
27
+
28
+ let :root_arrangement do
29
+ RhetButler::Arrangement['horizontal'].new
30
+ end
31
+
32
+ let :blueprint do
33
+ [
34
+ RhetButler::LayoutRule.new.tap do |rule|
35
+ rule.layout_type = 'horizontal'
36
+ end
37
+ ]
38
+ end
39
+
40
+ let :default_slide_type do
41
+ "textile"
42
+ end
43
+
44
+ let :processor do
45
+ processor = RhetButler::SlideProcessor.new
46
+ processor.root_group = root_group
47
+ processor.blueprint = blueprint
48
+ processor.default_slide_type = default_slide_type
49
+ processor
50
+ end
51
+
52
+ let :result do
53
+ processor.process
54
+ processor.slides
55
+ end
56
+
57
+ it "should produce slides" do
58
+ result.each do |slide|
59
+ slide.should be_a_kind_of(RhetButler::Slide)
60
+ end
61
+ end
62
+
63
+ it "should have five slides" do
64
+ result.should have(5).slides
65
+
66
+ end
67
+
68
+ it "should put all the slides in order" do
69
+ result.map do |slide|
70
+ slide.content
71
+ end.should == %w{A B C D E}.map{|str| "<p>#{str}</p>"}
72
+ end
73
+ end
@@ -0,0 +1,17 @@
1
+ puts Dir::pwd
2
+ require 'test/unit'
3
+ begin
4
+ require 'spec'
5
+ rescue LoadError
6
+ false
7
+ end
8
+
9
+ class RSpecTest < Test::Unit::TestCase
10
+ def test_that_rspec_is_available
11
+ assert_nothing_raised("\n\n * RSpec isn't available - please run: gem install rspec *\n\n"){ ::Spec }
12
+ end
13
+
14
+ def test_that_specs_pass
15
+ assert(system(*%w{spec -f e -p **/*.rb spec}),"\n\n * Specs failed *\n\n")
16
+ end
17
+ end