ceritium-rails-footnotes 3.4
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.
- data/MIT-LICENSE +21 -0
- data/README +147 -0
- data/Rakefile +19 -0
- data/lib/rails-footnotes.rb +20 -0
- data/lib/rails-footnotes/backtracer.rb +34 -0
- data/lib/rails-footnotes/footnotes.rb +333 -0
- data/lib/rails-footnotes/notes/abstract_note.rb +163 -0
- data/lib/rails-footnotes/notes/components_note.rb +79 -0
- data/lib/rails-footnotes/notes/controller_note.rb +55 -0
- data/lib/rails-footnotes/notes/cookies_note.rb +19 -0
- data/lib/rails-footnotes/notes/env_note.rb +19 -0
- data/lib/rails-footnotes/notes/files_note.rb +44 -0
- data/lib/rails-footnotes/notes/filters_note.rb +53 -0
- data/lib/rails-footnotes/notes/general_note.rb +19 -0
- data/lib/rails-footnotes/notes/javascripts_note.rb +16 -0
- data/lib/rails-footnotes/notes/layout_note.rb +28 -0
- data/lib/rails-footnotes/notes/log_note.rb +36 -0
- data/lib/rails-footnotes/notes/params_note.rb +19 -0
- data/lib/rails-footnotes/notes/partials_note.rb +36 -0
- data/lib/rails-footnotes/notes/queries_note.rb +146 -0
- data/lib/rails-footnotes/notes/routes_note.rb +59 -0
- data/lib/rails-footnotes/notes/session_note.rb +15 -0
- data/lib/rails-footnotes/notes/stylesheets_note.rb +16 -0
- data/lib/rails-footnotes/notes/view_note.rb +29 -0
- data/test/footnotes_test.rb +199 -0
- data/test/notes/abstract_note_test.rb +107 -0
- data/test/test_helper.rb +9 -0
- metadata +82 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/files_note"
|
2
|
+
|
3
|
+
module Footnotes
|
4
|
+
module Notes
|
5
|
+
class JavascriptsNote < FilesNote
|
6
|
+
def title
|
7
|
+
"Javascripts (#{@files.length})"
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
def scan_text(text)
|
12
|
+
text.scan(/<script[^>]+src\s*=\s*['"]([^>?'"]+\.js)/im).flatten
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/abstract_note"
|
2
|
+
|
3
|
+
module Footnotes
|
4
|
+
module Notes
|
5
|
+
class LayoutNote < AbstractNote
|
6
|
+
def initialize(controller)
|
7
|
+
@controller = controller
|
8
|
+
end
|
9
|
+
|
10
|
+
def row
|
11
|
+
:edit
|
12
|
+
end
|
13
|
+
|
14
|
+
def link
|
15
|
+
escape(Footnotes::Filter.prefix(filename, 1, 1))
|
16
|
+
end
|
17
|
+
|
18
|
+
def valid?
|
19
|
+
prefix? && @controller.active_layout
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
def filename
|
24
|
+
@controller.active_layout.filename
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/abstract_note"
|
2
|
+
|
3
|
+
module Footnotes
|
4
|
+
module Notes
|
5
|
+
class LogNote < AbstractNote
|
6
|
+
def initialize(controller)
|
7
|
+
@controller = controller
|
8
|
+
end
|
9
|
+
|
10
|
+
def content
|
11
|
+
escape(log_tail).gsub("\n","<br />")
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
def log_tail
|
16
|
+
filename = if RAILS_DEFAULT_LOGGER.instance_variable_get('@log')
|
17
|
+
RAILS_DEFAULT_LOGGER.instance_variable_get('@log').path
|
18
|
+
else
|
19
|
+
RAILS_DEFAULT_LOGGER.instance_variable_get('@logdev').filename
|
20
|
+
end
|
21
|
+
file_string = File.open(filename).read.to_s
|
22
|
+
|
23
|
+
# We try to select the specified action from the log
|
24
|
+
# If we can't find it, we get the last 100 lines
|
25
|
+
#
|
26
|
+
if rindex = file_string.rindex('Processing '+@controller.controller_class_name+'#'+@controller.action_name)
|
27
|
+
file_string[rindex..-1].gsub(/\e\[.+?m/, '')
|
28
|
+
else
|
29
|
+
lines = file_string.split("\n")
|
30
|
+
index = [lines.size-100,0].max
|
31
|
+
lines[index..-1].join("\n")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/abstract_note"
|
2
|
+
|
3
|
+
module Footnotes
|
4
|
+
module Notes
|
5
|
+
class ParamsNote < AbstractNote
|
6
|
+
def initialize(controller)
|
7
|
+
@params = controller.params.symbolize_keys
|
8
|
+
end
|
9
|
+
|
10
|
+
def title
|
11
|
+
"Params (#{@params.length})"
|
12
|
+
end
|
13
|
+
|
14
|
+
def content
|
15
|
+
escape(@params.inspect)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/log_note"
|
2
|
+
|
3
|
+
module Footnotes
|
4
|
+
module Notes
|
5
|
+
class PartialsNote < LogNote
|
6
|
+
def initialize(controller)
|
7
|
+
@controller = controller
|
8
|
+
@template = controller.instance_variable_get('@template')
|
9
|
+
@partials = get_partials
|
10
|
+
end
|
11
|
+
|
12
|
+
def content
|
13
|
+
result = '<ul>'
|
14
|
+
@partials.collect.each do |partial|
|
15
|
+
full_filename = File.join(File.expand_path(RAILS_ROOT), 'app', 'views', partial.first.to_s)
|
16
|
+
result += "<li><a href='#{Footnotes::Filter.prefix}#{full_filename}'>"
|
17
|
+
result += "#{partial.last}</a></li>"
|
18
|
+
end
|
19
|
+
result += '</ul>'
|
20
|
+
|
21
|
+
result
|
22
|
+
end
|
23
|
+
|
24
|
+
def title
|
25
|
+
"Partials (#{@partials.length})"
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def get_partials
|
30
|
+
partials = escape(log_tail).scan(/Rendered.*\(/).collect{|x| x.gsub('Rendered ', '').gsub('(', '').strip}.uniq
|
31
|
+
partials[0..partials.length].collect{|partial| [@template.send(:_pick_template, partial), partial]}
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/abstract_note"
|
2
|
+
|
3
|
+
module Footnotes
|
4
|
+
module Notes
|
5
|
+
class QueriesNote < AbstractNote
|
6
|
+
@@sql = []
|
7
|
+
cattr_accessor :sql
|
8
|
+
|
9
|
+
def self.start!(controller)
|
10
|
+
@@sql = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.to_sym
|
14
|
+
:queries
|
15
|
+
end
|
16
|
+
|
17
|
+
def title
|
18
|
+
"Queries (#{@@sql.length})"
|
19
|
+
end
|
20
|
+
|
21
|
+
def stylesheet
|
22
|
+
<<-STYLESHEET
|
23
|
+
#queries_debug_info table td, #queries_debug_info table th{border:1px solid #A00; padding:0 3px; text-align:center;}
|
24
|
+
#queries_debug_info table thead, #queries_debug_info table tbody {color:#A00;}
|
25
|
+
#queries_debug_info p {background-color:#F3F3FF; border:1px solid #CCC; margin:12px; padding:4px 6px;}
|
26
|
+
#queries_debug_info a:hover {text-decoration:underline;}
|
27
|
+
STYLESHEET
|
28
|
+
end
|
29
|
+
|
30
|
+
def content
|
31
|
+
html = ''
|
32
|
+
|
33
|
+
@@sql.each_with_index do |item, i|
|
34
|
+
sql_links = []
|
35
|
+
sql_links << "<a href=\"#\" style=\"color:#A00;\" onclick=\"Footnotes.toggle('qtable_#{i}');return false\">explain</a>" if item.explain
|
36
|
+
sql_links << "<a href=\"#\" style=\"color:#00A;\" onclick=\"Footnotes.toggle('qtrace_#{i}');return false\">trace</a>" if item.trace
|
37
|
+
|
38
|
+
html << <<-HTML
|
39
|
+
<b id="qtitle_#{i}">#{escape(item.type.to_s.upcase)}</b> (#{sql_links.join(' | ')})<br />
|
40
|
+
#{print_name_and_time(item.name, item.time)}<br />
|
41
|
+
#{print_query(item.query)}<br />
|
42
|
+
#{print_explain(i, item.explain) if item.explain}
|
43
|
+
<p id="qtrace_#{i}" style="display:none;">#{parse_trace(item.trace) if item.trace}</p><br />
|
44
|
+
HTML
|
45
|
+
end
|
46
|
+
|
47
|
+
return html
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
def parse_explain(results)
|
52
|
+
table = []
|
53
|
+
table << results.fetch_fields.map(&:name)
|
54
|
+
results.each{|row| table << row}
|
55
|
+
table
|
56
|
+
end
|
57
|
+
|
58
|
+
def parse_trace(trace)
|
59
|
+
trace.map do |t|
|
60
|
+
s = t.split(':')
|
61
|
+
%[<a href="#{escape(Footnotes::Filter.prefix("#{RAILS_ROOT}/#{s[0]}", s[1].to_i, 1))}">#{escape(t)}</a><br />]
|
62
|
+
end.join
|
63
|
+
end
|
64
|
+
|
65
|
+
def print_name_and_time(name, time)
|
66
|
+
"#{escape(name || 'SQL')} (#{sprintf('%f', time)}s)"
|
67
|
+
end
|
68
|
+
|
69
|
+
def print_query(query)
|
70
|
+
escape(query.to_s.gsub(/(\s)+/, ' ').gsub('`', ''))
|
71
|
+
end
|
72
|
+
|
73
|
+
def print_explain(i, explain)
|
74
|
+
mount_table(parse_explain(explain), :id => "qtable_#{i}", :style => 'margin:10px;display:none;')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
module Extensions
|
80
|
+
class Sql
|
81
|
+
attr_accessor :type, :name, :time, :query, :explain, :trace
|
82
|
+
|
83
|
+
def initialize(type, name, time, query, explain)
|
84
|
+
@type = type
|
85
|
+
@name = name
|
86
|
+
@time = time
|
87
|
+
@query = query
|
88
|
+
@explain = explain
|
89
|
+
|
90
|
+
# Strip, select those ones from app and reject first two, because they are from the plugin
|
91
|
+
@trace = Kernel.caller.collect(&:strip).select{|i| i.gsub!(/^#{RAILS_ROOT}\//im, '') }[2..-1]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
module QueryAnalyzer
|
96
|
+
def self.included(base)
|
97
|
+
base.class_eval do
|
98
|
+
alias_method_chain :execute, :analyzer
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def execute_with_analyzer(query, name = nil)
|
103
|
+
query_results = nil
|
104
|
+
time = Benchmark.realtime { query_results = execute_without_analyzer(query, name) }
|
105
|
+
|
106
|
+
if query =~ /^(select|create|update|delete)\b/i
|
107
|
+
type = $&.downcase.to_sym
|
108
|
+
explain = nil
|
109
|
+
|
110
|
+
if adapter_name == 'MySQL' && type == :select
|
111
|
+
log_silence do
|
112
|
+
explain = execute_without_analyzer("EXPLAIN #{query}", name)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
Footnotes::Notes::QueriesNote.sql << Footnotes::Extensions::Sql.new(type, name, time, query, explain)
|
116
|
+
end
|
117
|
+
|
118
|
+
query_results
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
module AbstractAdapter
|
123
|
+
def log_silence
|
124
|
+
result = nil
|
125
|
+
if @logger
|
126
|
+
@logger.silence do
|
127
|
+
result = yield
|
128
|
+
end
|
129
|
+
else
|
130
|
+
result = yield
|
131
|
+
end
|
132
|
+
result
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
if Footnotes::Notes::QueriesNote.included?
|
140
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.send :include, Footnotes::Extensions::AbstractAdapter
|
141
|
+
ActiveRecord::ConnectionAdapters.local_constants.each do |adapter|
|
142
|
+
next unless adapter =~ /.*[^Abstract]Adapter$/
|
143
|
+
next if adapter =~ /SQLite.Adapter$/
|
144
|
+
eval("ActiveRecord::ConnectionAdapters::#{adapter}").send :include, Footnotes::Extensions::QueryAnalyzer
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/abstract_note"
|
2
|
+
|
3
|
+
module Footnotes
|
4
|
+
module Notes
|
5
|
+
class RoutesNote < AbstractNote
|
6
|
+
def initialize(controller)
|
7
|
+
@controller = controller
|
8
|
+
@parsed_routes = parse_routes
|
9
|
+
end
|
10
|
+
|
11
|
+
def legend
|
12
|
+
"Routes for #{@controller.class.to_s}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def content
|
16
|
+
mount_table(@parsed_routes.unshift([:path, :name, :options, :requirements]))
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
def parse_routes
|
21
|
+
routes_with_name = ActionController::Routing::Routes.named_routes.to_a.flatten
|
22
|
+
|
23
|
+
return ActionController::Routing::Routes.filtered_routes(:controller => @controller.controller_name).collect do |route|
|
24
|
+
# Catch routes name if exists
|
25
|
+
i = routes_with_name.index(route)
|
26
|
+
name = i ? routes_with_name[i-1].to_s : ''
|
27
|
+
|
28
|
+
# Catch segments requirements
|
29
|
+
req = {}
|
30
|
+
route.segments.each do |segment|
|
31
|
+
next unless segment.is_a?(ActionController::Routing::DynamicSegment) && segment.regexp
|
32
|
+
req[segment.key.to_sym] = segment.regexp
|
33
|
+
end
|
34
|
+
|
35
|
+
[escape(name), route.segments.join, route.requirements.reject{|key,value| key == :controller}.inspect, req.inspect]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
module Extensions
|
42
|
+
module Routes
|
43
|
+
# Filter routes according to the filter sent
|
44
|
+
#
|
45
|
+
def filtered_routes(filter = {})
|
46
|
+
return [] unless filter.is_a?(Hash)
|
47
|
+
return routes.reject do |r|
|
48
|
+
filter_diff = filter.diff(r.requirements)
|
49
|
+
route_diff = r.requirements.diff(filter)
|
50
|
+
(filter_diff == filter) || (filter_diff != route_diff)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
if Footnotes::Notes::RoutesNote.included?
|
58
|
+
ActionController::Routing::RouteSet.send :include, Footnotes::Extensions::Routes
|
59
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/abstract_note"
|
2
|
+
|
3
|
+
module Footnotes
|
4
|
+
module Notes
|
5
|
+
class SessionNote < AbstractNote
|
6
|
+
def initialize(controller)
|
7
|
+
@session = (controller.session.instance_variable_get("@data") || {}).symbolize_keys
|
8
|
+
end
|
9
|
+
|
10
|
+
def content
|
11
|
+
escape(@session.inspect)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/files_note"
|
2
|
+
|
3
|
+
module Footnotes
|
4
|
+
module Notes
|
5
|
+
class StylesheetsNote < FilesNote
|
6
|
+
def title
|
7
|
+
"Stylesheets (#{@files.length})"
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
def scan_text(text)
|
12
|
+
text.scan(/<link[^>]+href\s*=\s*['"]([^>?'"]+\.css)/im).flatten
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/abstract_note"
|
2
|
+
|
3
|
+
module Footnotes
|
4
|
+
module Notes
|
5
|
+
class ViewNote < AbstractNote
|
6
|
+
def initialize(controller)
|
7
|
+
@controller = controller
|
8
|
+
@template = controller.instance_variable_get(:@template)
|
9
|
+
end
|
10
|
+
|
11
|
+
def row
|
12
|
+
:edit
|
13
|
+
end
|
14
|
+
|
15
|
+
def link
|
16
|
+
escape(Footnotes::Filter.prefix(filename, 1, 1))
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?
|
20
|
+
prefix? && @template && @template.template
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
def filename
|
25
|
+
@template.template.filename
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
require 'action_controller'
|
4
|
+
require 'action_controller/test_case'
|
5
|
+
require 'action_controller/test_process'
|
6
|
+
|
7
|
+
class FootnotesController < ActionController::Base; attr_accessor :template, :performed_render; end
|
8
|
+
|
9
|
+
module Footnotes::Notes
|
10
|
+
class TestNote < AbstractNote
|
11
|
+
def self.to_sym; :test; end
|
12
|
+
def valid?; true; end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class FootnotesTest < Test::Unit::TestCase
|
17
|
+
def setup
|
18
|
+
@controller = FootnotesController.new
|
19
|
+
@controller.request = ActionController::TestRequest.new
|
20
|
+
@controller.response = ActionController::TestResponse.new
|
21
|
+
@controller.response.body = $html.dup
|
22
|
+
|
23
|
+
Footnotes::Filter.notes = [ :test ]
|
24
|
+
Footnotes::Filter.multiple_notes = false
|
25
|
+
@footnotes = Footnotes::Filter.new(@controller)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_footnotes_controller
|
29
|
+
index = @controller.response.body.index(/This is the HTML page/)
|
30
|
+
assert_equal 334, index
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_foonotes_included
|
34
|
+
footnotes_perform!
|
35
|
+
assert_not_equal $html, @controller.response.body
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_footnotes_not_included_when_request_is_xhr
|
39
|
+
@controller.request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
|
40
|
+
@controller.request.env['HTTP_ACCEPT'] = 'text/javascript, text/html, application/xml, text/xml, */*'
|
41
|
+
|
42
|
+
footnotes_perform!
|
43
|
+
assert_equal $html, @controller.response.body
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_footnotes_not_included_when_content_type_is_javascript
|
47
|
+
@controller.response.headers['Content-Type'] = 'text/javascript'
|
48
|
+
|
49
|
+
footnotes_perform!
|
50
|
+
assert_equal $html, @controller.response.body
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_footnotes_included_when_content_type_is_html
|
54
|
+
@controller.response.headers['Content-Type'] = 'text/html'
|
55
|
+
|
56
|
+
footnotes_perform!
|
57
|
+
assert_not_equal $html, @controller.response.body
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_footnotes_included_when_content_type_is_nil
|
61
|
+
footnotes_perform!
|
62
|
+
assert_not_equal $html, @controller.response.body
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_not_included_when_body_is_not_a_string
|
66
|
+
@controller.response.body = Proc.new{ Time.now }
|
67
|
+
assert_nothing_raised do
|
68
|
+
footnotes_perform!
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_footnotes_prefix
|
73
|
+
assert_equal 'txmt://open?url=file://%s&line=%d&column=%d', Footnotes::Filter.prefix
|
74
|
+
assert_equal 'txmt://open?url=file://file&line=0&column=0', Footnotes::Filter.prefix('file', 0, 0)
|
75
|
+
assert_equal 'txmt://open?url=file://file&line=10&column=10', Footnotes::Filter.prefix('file', 10, 10)
|
76
|
+
assert_equal 'txmt://open?url=file://file&line=10&column=10', Footnotes::Filter.prefix('file', 10, 10, 10)
|
77
|
+
assert_equal 'txmt://open?url=file://file&line=10&column=10', Footnotes::Filter.prefix('file', '10', '10')
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_notes_are_initialized
|
81
|
+
footnotes_perform!
|
82
|
+
test_note = @footnotes.instance_variable_get('@notes').first
|
83
|
+
assert 'Footnotes::Notes::TestNote', test_note.class
|
84
|
+
assert :test, test_note.to_sym
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_notes_links
|
88
|
+
note = Footnotes::Notes::TestNote.new
|
89
|
+
note.expects(:row).times(2)
|
90
|
+
@footnotes.instance_variable_set(:@notes, [note])
|
91
|
+
footnotes_perform!
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_notes_fieldset
|
95
|
+
note = Footnotes::Notes::TestNote.new
|
96
|
+
note.expects(:has_fieldset?).times(3)
|
97
|
+
@footnotes.instance_variable_set(:@notes, [note])
|
98
|
+
footnotes_perform!
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_multiple_notes
|
102
|
+
Footnotes::Filter.multiple_notes = true
|
103
|
+
note = Footnotes::Notes::TestNote.new
|
104
|
+
note.expects(:has_fieldset?).times(2)
|
105
|
+
@footnotes.instance_variable_set(:@notes, [note])
|
106
|
+
footnotes_perform!
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_notes_are_reset
|
110
|
+
note = Footnotes::Notes::TestNote.new
|
111
|
+
note.class.expects(:close!)
|
112
|
+
@footnotes.instance_variable_set(:@notes, [note])
|
113
|
+
@footnotes.send(:close!, @controller)
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_links_helper
|
117
|
+
note = Footnotes::Notes::TestNote.new
|
118
|
+
assert_equal '<a href="#" onclick="">Test</a>', @footnotes.send(:link_helper, note)
|
119
|
+
|
120
|
+
note.expects(:link).times(1).returns(:link)
|
121
|
+
assert_equal '<a href="link" onclick="">Test</a>', @footnotes.send(:link_helper, note)
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_links_helper_has_fieldset?
|
125
|
+
note = Footnotes::Notes::TestNote.new
|
126
|
+
note.expects(:has_fieldset?).times(1).returns(true)
|
127
|
+
assert_equal '<a href="#" onclick="Footnotes.hideAllAndToggle(\'test_debug_info\');return false;">Test</a>', @footnotes.send(:link_helper, note)
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_links_helper_onclick
|
131
|
+
note = Footnotes::Notes::TestNote.new
|
132
|
+
note.expects(:onclick).times(2).returns(:onclick)
|
133
|
+
assert_equal '<a href="#" onclick="onclick">Test</a>', @footnotes.send(:link_helper, note)
|
134
|
+
|
135
|
+
note.expects(:has_fieldset?).times(1).returns(true)
|
136
|
+
assert_equal '<a href="#" onclick="onclick">Test</a>', @footnotes.send(:link_helper, note)
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_insert_style
|
140
|
+
@controller.response.body = "<head></head><split><body></body>"
|
141
|
+
@footnotes = Footnotes::Filter.new(@controller)
|
142
|
+
footnotes_perform!
|
143
|
+
assert @controller.response.body.split('<split>').first.include?('<!-- Footnotes Style -->')
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_insert_footnotes_inside_body
|
147
|
+
@controller.response.body = "<head></head><split><body></body>"
|
148
|
+
@footnotes = Footnotes::Filter.new(@controller)
|
149
|
+
footnotes_perform!
|
150
|
+
assert @controller.response.body.split('<split>').last.include?('<!-- End Footnotes -->')
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_insert_footnotes_inside_holder
|
154
|
+
@controller.response.body = "<head></head><split><div id='footnotes_holder'></div>"
|
155
|
+
@footnotes = Footnotes::Filter.new(@controller)
|
156
|
+
footnotes_perform!
|
157
|
+
assert @controller.response.body.split('<split>').last.include?('<!-- End Footnotes -->')
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_insert_text
|
161
|
+
@footnotes.send(:insert_text, :after, /<head>/, "Graffiti")
|
162
|
+
after = " <head>Graffiti\n"
|
163
|
+
assert_equal after, @controller.response.body.to_a[2]
|
164
|
+
|
165
|
+
@footnotes.send(:insert_text, :before, /<\/body>/, "Notes")
|
166
|
+
after = " Notes</body>\n"
|
167
|
+
assert_equal after, @controller.response.body.to_a[12]
|
168
|
+
end
|
169
|
+
|
170
|
+
protected
|
171
|
+
# First we make sure that footnotes will perform (long life to mocha!)
|
172
|
+
# Then we call add_footnotes!
|
173
|
+
#
|
174
|
+
def footnotes_perform!
|
175
|
+
@controller.template.expects(:instance_variable_get).returns(true)
|
176
|
+
@controller.template.expects(:template_format).returns('html')
|
177
|
+
@controller.performed_render = true
|
178
|
+
|
179
|
+
Footnotes::Filter.start!(@controller)
|
180
|
+
@footnotes.add_footnotes!
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
$html = <<HTML
|
185
|
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
186
|
+
<html>
|
187
|
+
<head>
|
188
|
+
<title>HTML to XHTML Example: HTML page</title>
|
189
|
+
<link rel="Stylesheet" href="htmltohxhtml.css" type="text/css" media="screen">
|
190
|
+
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
191
|
+
</head>
|
192
|
+
<body>
|
193
|
+
<p>This is the HTML page. It works and is encoded just like any HTML page you
|
194
|
+
have previously done. View <a href="htmltoxhtml2.htm">the XHTML version</a> of
|
195
|
+
this page to view the difference between HTML and XHTML.</p>
|
196
|
+
<p>You will be glad to know that no changes need to be made to any of your CSS files.</p>
|
197
|
+
</body>
|
198
|
+
</html>
|
199
|
+
HTML
|