instrument 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,71 @@
1
+ # ++
2
+ # Instrument, Copyright (c) 2008 Day Automation Systems, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ # --
23
+
24
+ require "instrument/control"
25
+
26
+ module Instrument
27
+ ##
28
+ # A module which you can mixin to allow for abbreviated control
29
+ # creation.
30
+ #
31
+ # == Example
32
+ #
33
+ # include Instrument::ControlBuilder
34
+ #
35
+ # select_control(:name => "base", :selections => [
36
+ # {:label => "One", :value => "1"},
37
+ # {:label => "Two", :value => "2"},
38
+ # {:label => "Three", :value => "3"},
39
+ # {:label => "Four", :value => "4"}
40
+ # ]).to_xhtml
41
+ module ControlBuilder
42
+ ##
43
+ # Prevents Kernel#select from being accidentally called.
44
+ #
45
+ # @param [Array] params the method's parameters
46
+ # @param [Proc] block the block being passed to the method
47
+ # @return [Instrument::Control] the control being created
48
+ def select(*params, &block) # :nodoc:
49
+ return self.method_missing(:select, *params, &block)
50
+ end
51
+
52
+ ##
53
+ # Initializes Instrument::Control subclasses by name.
54
+ #
55
+ # @param [Symbol] method the method being called
56
+ # @param [Array] params the method's parameters
57
+ # @param [Proc] block the block being passed to the method
58
+ # @return [Instrument::Control] the control being created
59
+ # @raise NoMethodError if the method wasn't handled
60
+ def method_missing(method, *params, &block)
61
+ control_class = ::Instrument::Control.lookup(method.to_s)
62
+ if control_class != nil
63
+ return control_class.new(*params, &block)
64
+ else
65
+ raise NoMethodError,
66
+ "undefined method `#{method}' for " +
67
+ "#{self.inspect}:#{self.class.name}"
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,35 @@
1
+ # ++
2
+ # Instrument, Copyright (c) 2008 Day Automation Systems, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ # --
23
+
24
+ module Instrument
25
+ ##
26
+ # Exception raised when a template cannot be found.
27
+ class ResourceNotFoundError < StandardError
28
+ end
29
+
30
+ ##
31
+ # Exception raised when a template is found, but it uses an unknown
32
+ # template engine.
33
+ class InvalidTemplateEngineError < StandardError
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ # ++
2
+ # Instrument, Copyright (c) 2008 Day Automation Systems, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ # --
23
+
24
+ # Used to prevent the class/module from being loaded more than once
25
+ unless defined? Instrument::VERSION
26
+ module Instrument #:nodoc:
27
+ module VERSION #:nodoc:
28
+ MAJOR = 0
29
+ MINOR = 1
30
+ TINY = 0
31
+
32
+ STRING = [MAJOR, MINOR, TINY].join('.')
33
+ end
34
+ end
35
+ end
@@ -0,0 +1 @@
1
+ %img{:src => source, :alt => alternate_text}
@@ -0,0 +1,19 @@
1
+ require "uuidtools"
2
+ require "time"
3
+ xml.instruct! :xml, :version=>"1.0"
4
+ xml.feed("xmlns" => "http://www.w3.org/2005/Atom", "xml:lang" => "en_US") do
5
+ xml.id("urn:uuid:4a11e26e-239c-11dd-adf9-001ec2186a45")
6
+ xml.title("Select Control")
7
+ xml.subtitle("Yes, this is silly, but you get the idea.")
8
+ xml.updated(Time.now.iso8601)
9
+ for selection in selections
10
+ xml.entry do
11
+ xml.id(
12
+ UUID.sha1_create(UUID_URL_NAMESPACE, "#" + selection.value).to_uri
13
+ )
14
+ xml.title(selection.label)
15
+ xml.link("#" + selection.value)
16
+ xml.updated(Time.now.iso8601)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,2 @@
1
+ # This directory exists to test that a directory cannot be loaded
2
+ # accidentally as if it were a template.
@@ -0,0 +1,5 @@
1
+ select :id => element_id, :name => element_name do
2
+ for selection in selections
3
+ option selection.label, :value => selection.value
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ {
2
+ "select": {
3
+ "id": "<%= element_id %>",
4
+ "name": "<%= element_name %>",
5
+ "options": [
6
+ <% for selection in selections %>
7
+ {
8
+ "label": "<%= selection.label %>",
9
+ "value": "<%= selection.value %>"
10
+ }
11
+ <% end %>
12
+ ]
13
+ }
14
+ }
@@ -0,0 +1,2 @@
1
+ # This is a bogus format.
2
+ # No handler will be registered to handle it.
@@ -0,0 +1,4 @@
1
+ %select{:id => element_id, :name => element_name}
2
+ - for selection in selections
3
+ %option{:value => selection.value}
4
+ = selection.label
@@ -0,0 +1,2 @@
1
+ %divide_by_zero_test
2
+ = 0 / 0
@@ -0,0 +1,37 @@
1
+ spec_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
2
+ require File.join(spec_dir, "spec_helper")
3
+
4
+ class ImageControl < Instrument::Control
5
+ def source
6
+ return self.options[:source] || self.options[:src]
7
+ end
8
+
9
+ def alternate_text
10
+ return self.options[:alternate_text] || self.options[:alt]
11
+ end
12
+ end
13
+
14
+ # Verifies that Kernel#select isn't accidentally being called.
15
+ class Select < Instrument::Control
16
+ end
17
+
18
+ describe Instrument::ControlBuilder do
19
+ class ExtendedObject
20
+ include Instrument::ControlBuilder
21
+ end
22
+
23
+ before :all do
24
+ @extended_object = ExtendedObject.new
25
+ end
26
+
27
+ it "should enable mixins to function" do
28
+ @extended_object.image_control.class.should == ImageControl
29
+ @extended_object.select.class.should == Select
30
+ end
31
+
32
+ it "should still raise an Exception for non-existent methods" do
33
+ (lambda do
34
+ @extended_object.bogus
35
+ end).should raise_error(NoMethodError)
36
+ end
37
+ end
@@ -0,0 +1,179 @@
1
+ spec_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
2
+ require File.join(spec_dir, "spec_helper")
3
+
4
+ class SelectControl < Instrument::Control
5
+ class Option
6
+ def initialize(label, value)
7
+ @label, @value = label, value
8
+ end
9
+
10
+ attr_accessor :label
11
+ attr_accessor :value
12
+ end
13
+
14
+ def element_id
15
+ return self.options[:id] || self.options[:name]
16
+ end
17
+
18
+ def element_name
19
+ return self.options[:name]
20
+ end
21
+
22
+ def selections
23
+ if !defined?(@selections) || @selections == nil
24
+ @selections = []
25
+ for selection in self.options[:selections]
26
+ if selection.kind_of?(Hash)
27
+ @selections << Option.new(selection[:label], selection[:value])
28
+ else
29
+ @selections << Option.new(selection, selection)
30
+ end
31
+ end
32
+ end
33
+ return @selections
34
+ end
35
+ end
36
+
37
+ class SuperSelectControl < SelectControl
38
+ end
39
+
40
+ describe Instrument::Control do
41
+ it "should be able to look up subclasses by name" do
42
+ Instrument::Control.lookup("select_control").should ==
43
+ SelectControl
44
+ Instrument::Control.lookup("super_select_control").should ==
45
+ SuperSelectControl
46
+ end
47
+
48
+ it "should have RAILS_ROOT/app/controls in the $CONTROL_PATH" do
49
+ $CONTROL_PATH.should include(File.join(RAILS_ROOT, "app/controls"))
50
+ end
51
+
52
+ it "should not allow invalid types to be used" do
53
+ (lambda do
54
+ Instrument::Control.processor(:bogus)
55
+ end).should raise_error(ArgumentError)
56
+ end
57
+
58
+ it "should initialize subclasses via method_missing" do
59
+ Instrument::Control.new.select_control.class.should == SelectControl
60
+ end
61
+
62
+ it "should still raise an Exception for non-existent methods" do
63
+ (lambda do
64
+ Instrument::Control.new.bogus
65
+ end).should raise_error(NoMethodError)
66
+ end
67
+
68
+ it "should raise an Exception for non-existent formats" do
69
+ (lambda do
70
+ SelectControl.new.to_bogus
71
+ end).should raise_error(Instrument::ResourceNotFoundError)
72
+ end
73
+
74
+ it "should raise an Exception if a directory is found instead of a file" do
75
+ (lambda do
76
+ SelectControl.new.to_directory
77
+ end).should raise_error(Instrument::ResourceNotFoundError)
78
+ end
79
+
80
+ it "should raise an Exception if a directory is found instead of a file" do
81
+ (lambda do
82
+ SelectControl.new.to_txt
83
+ end).should raise_error(Instrument::InvalidTemplateEngineError)
84
+ end
85
+
86
+ it "should raise an Exception if a template raises an Exception" do
87
+ (lambda do
88
+ SelectControl.new.to_xml
89
+ end).should raise_error(ZeroDivisionError)
90
+ end
91
+ end
92
+
93
+ describe Instrument::Control, "when rendered as XHTML with Haml" do
94
+ before :all do
95
+ @control = SelectControl.new(:name => "base", :selections => [
96
+ "First", "Second", "Third", "Home"
97
+ ])
98
+ @xhtml = @control.to_xhtml
99
+ end
100
+
101
+ it "should have the correct id and name" do
102
+ @xhtml.should match(/<select id="base" name="base">/)
103
+ end
104
+
105
+ it "should have options for all of the given selections" do
106
+ @xhtml.should match(/<option value="First"/)
107
+ @xhtml.should match(/<option value="Second"/)
108
+ @xhtml.should match(/<option value="Third"/)
109
+ @xhtml.should match(/<option value="Home"/)
110
+ end
111
+ end
112
+
113
+ describe Instrument::Control, "when rendered as HTML with Markaby" do
114
+ before :all do
115
+ @control = SelectControl.new(:name => "base", :selections => [
116
+ "First", "Second", "Third", "Home"
117
+ ])
118
+ @html = @control.to_html
119
+ end
120
+
121
+ it "should have the correct id and name" do
122
+ # Ordering of attributes is indeterminate.
123
+ @html.should match(/<select/)
124
+ @html.should match(/id="base"/)
125
+ @html.should match(/name="base"/)
126
+ end
127
+
128
+ it "should have options for all of the given selections" do
129
+ @html.should match(/<option value="First"/)
130
+ @html.should match(/<option value="Second"/)
131
+ @html.should match(/<option value="Third"/)
132
+ @html.should match(/<option value="Home"/)
133
+ end
134
+ end
135
+
136
+ describe Instrument::Control, "when rendered as Atom with XML Builder" do
137
+ before :all do
138
+ @control = SelectControl.new(:name => "base", :selections => [
139
+ "First", "Second", "Third", "Home"
140
+ ])
141
+ @atom = @control.to_atom
142
+ end
143
+
144
+ it "should have the correct id and name" do
145
+ @atom.should match(/<title>Select Control<\/title>/)
146
+ end
147
+
148
+ it "should have options for all of the given selections" do
149
+ @atom.should match(/<title>First<\/title>/)
150
+ @atom.should match(/<title>Second<\/title>/)
151
+ @atom.should match(/<title>Third<\/title>/)
152
+ @atom.should match(/<title>Home<\/title>/)
153
+ end
154
+ end
155
+
156
+ describe Instrument::Control, "when rendered as JSON with Erubis" do
157
+ before :all do
158
+ @control = SelectControl.new(:name => "base", :selections => [
159
+ "First", "Second", "Third", "Home"
160
+ ])
161
+ @atom = @control.to_json
162
+ end
163
+
164
+ it "should have the correct id and name" do
165
+ @atom.should match(/"id": "base"/)
166
+ @atom.should match(/"name": "base"/)
167
+ end
168
+
169
+ it "should have options for all of the given selections" do
170
+ @atom.should match(/"label": "First"/)
171
+ @atom.should match(/"value": "First"/)
172
+ @atom.should match(/"label": "Second"/)
173
+ @atom.should match(/"value": "Second"/)
174
+ @atom.should match(/"label": "Third"/)
175
+ @atom.should match(/"value": "Third"/)
176
+ @atom.should match(/"label": "Home"/)
177
+ @atom.should match(/"value": "Home"/)
178
+ end
179
+ end
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,13 @@
1
+ # We need to test for the presence of RAILS_ROOT in the $CONTROL_PATH
2
+ if !defined?(RAILS_ROOT)
3
+ RAILS_ROOT = "somewhere/over/the/rainbow"
4
+ end
5
+
6
+ spec_dir = File.expand_path(File.dirname(__FILE__))
7
+ lib_dir = File.expand_path(File.join(spec_dir, "../lib"))
8
+
9
+ $:.unshift(lib_dir)
10
+ $:.uniq!
11
+
12
+ require "instrument"
13
+ $CONTROL_PATH.unshift(File.join(spec_dir, "control_templates"))
@@ -0,0 +1,43 @@
1
+ module Rake
2
+ def self.browse(filepath)
3
+ if RUBY_PLATFORM =~ /mswin/
4
+ system(filepath)
5
+ else
6
+ try_browsers = lambda do
7
+ result = true
8
+ if !(`which firefox 2>&1` =~ /no firefox/)
9
+ system("firefox #{filepath}")
10
+ elsif !(`which mozilla 2>&1` =~ /no mozilla/)
11
+ system("mozilla #{filepath}")
12
+ elsif !(`which netscape 2>&1` =~ /no netscape/)
13
+ system("netscape #{filepath}")
14
+ elsif !(`which links 2>&1` =~ /no links/)
15
+ system("links #{filepath}")
16
+ elsif !(`which lynx 2>&1` =~ /no lynx/)
17
+ system("lynx #{filepath}")
18
+ else
19
+ result = false
20
+ end
21
+ result
22
+ end
23
+ opened = false
24
+ if RUBY_PLATFORM =~ /darwin/
25
+ opened = true
26
+ system("open #{filepath}")
27
+ elsif !(`which gnome-open 2>&1` =~ /no gnome-open/)
28
+ success =
29
+ !(`gnome-open #{filepath} 2>&1` =~ /There is no default action/)
30
+ if !success
31
+ opened = try_browsers.call()
32
+ else
33
+ opened = true
34
+ end
35
+ else
36
+ opened = try_browsers.call()
37
+ end
38
+ if !opened
39
+ puts "Don't know how to browse to location."
40
+ end
41
+ end
42
+ end
43
+ end