staugaard-comatose 2.0.2
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/CHANGELOG +176 -0
- data/INSTALL +19 -0
- data/LICENSE +20 -0
- data/MANIFEST +91 -0
- data/README.rdoc +148 -0
- data/Rakefile +122 -0
- data/SPECS +61 -0
- data/about.yml +7 -0
- data/bin/comatose +109 -0
- data/comatose.gemspec +113 -0
- data/generators/comatose_migration/USAGE +15 -0
- data/generators/comatose_migration/comatose_migration_generator.rb +59 -0
- data/generators/comatose_migration/templates/migration.rb +35 -0
- data/generators/comatose_migration/templates/v4_upgrade.rb +15 -0
- data/generators/comatose_migration/templates/v6_upgrade.rb +23 -0
- data/generators/comatose_migration/templates/v7_upgrade.rb +22 -0
- data/init.rb +2 -0
- data/install.rb +16 -0
- data/lib/acts_as_versioned.rb +543 -0
- data/lib/comatose.rb +33 -0
- data/lib/comatose/comatose_drop.rb +79 -0
- data/lib/comatose/configuration.rb +68 -0
- data/lib/comatose/page_wrapper.rb +119 -0
- data/lib/comatose/processing_context.rb +69 -0
- data/lib/comatose/tasks/admin.rb +60 -0
- data/lib/comatose/tasks/data.rb +82 -0
- data/lib/comatose/tasks/setup.rb +52 -0
- data/lib/comatose/version.rb +4 -0
- data/lib/comatose_admin_controller.rb +349 -0
- data/lib/comatose_admin_helper.rb +37 -0
- data/lib/comatose_controller.rb +142 -0
- data/lib/comatose_helper.rb +3 -0
- data/lib/comatose_page.rb +141 -0
- data/lib/liquid.rb +52 -0
- data/lib/liquid/block.rb +96 -0
- data/lib/liquid/context.rb +190 -0
- data/lib/liquid/document.rb +17 -0
- data/lib/liquid/drop.rb +48 -0
- data/lib/liquid/errors.rb +7 -0
- data/lib/liquid/extensions.rb +53 -0
- data/lib/liquid/file_system.rb +62 -0
- data/lib/liquid/htmltags.rb +64 -0
- data/lib/liquid/standardfilters.rb +111 -0
- data/lib/liquid/standardtags.rb +399 -0
- data/lib/liquid/strainer.rb +42 -0
- data/lib/liquid/tag.rb +25 -0
- data/lib/liquid/template.rb +88 -0
- data/lib/liquid/variable.rb +39 -0
- data/lib/redcloth.rb +1129 -0
- data/lib/support/class_options.rb +36 -0
- data/lib/support/inline_rendering.rb +48 -0
- data/lib/support/route_mapper.rb +50 -0
- data/lib/text_filters.rb +138 -0
- data/lib/text_filters/markdown.rb +14 -0
- data/lib/text_filters/markdown_smartypants.rb +15 -0
- data/lib/text_filters/none.rb +8 -0
- data/lib/text_filters/rdoc.rb +13 -0
- data/lib/text_filters/simple.rb +8 -0
- data/lib/text_filters/textile.rb +15 -0
- data/rails/init.rb +3 -0
- data/resources/layouts/comatose_admin_template.html.erb +28 -0
- data/resources/public/images/collapsed.gif +0 -0
- data/resources/public/images/expanded.gif +0 -0
- data/resources/public/images/no-children.gif +0 -0
- data/resources/public/images/page.gif +0 -0
- data/resources/public/images/spinner.gif +0 -0
- data/resources/public/images/title-hover-bg.gif +0 -0
- data/resources/public/javascripts/comatose_admin.js +401 -0
- data/resources/public/stylesheets/comatose_admin.css +381 -0
- data/tasks/comatose.rake +9 -0
- data/test/behaviors.rb +106 -0
- data/test/fixtures/comatose_pages.yml +96 -0
- data/test/functional/comatose_admin_controller_test.rb +112 -0
- data/test/functional/comatose_controller_test.rb +44 -0
- data/test/javascripts/test.html +26 -0
- data/test/javascripts/test_runner.js +307 -0
- data/test/test_helper.rb +43 -0
- data/test/unit/class_options_test.rb +52 -0
- data/test/unit/comatose_page_test.rb +128 -0
- data/test/unit/processing_context_test.rb +108 -0
- data/test/unit/text_filters_test.rb +52 -0
- data/views/comatose_admin/_form.html.erb +96 -0
- data/views/comatose_admin/_page_list_item.html.erb +60 -0
- data/views/comatose_admin/delete.html.erb +18 -0
- data/views/comatose_admin/edit.html.erb +5 -0
- data/views/comatose_admin/index.html.erb +18 -0
- data/views/comatose_admin/new.html.erb +5 -0
- data/views/comatose_admin/reorder.html.erb +30 -0
- data/views/comatose_admin/versions.html.erb +40 -0
- data/views/layouts/comatose_admin.html.erb +814 -0
- data/views/layouts/comatose_admin_customize.html.erb +28 -0
- data/views/layouts/comatose_content.html.erb +17 -0
- metadata +147 -0
@@ -0,0 +1,96 @@
|
|
1
|
+
# ComatosePage attributes
|
2
|
+
# - parent_id
|
3
|
+
# - title
|
4
|
+
# - full_path
|
5
|
+
# - slug
|
6
|
+
# - keywords
|
7
|
+
# - body
|
8
|
+
# - author
|
9
|
+
# - filter_type
|
10
|
+
# - position
|
11
|
+
# - version
|
12
|
+
# - updated_on
|
13
|
+
# - created_on
|
14
|
+
|
15
|
+
root:
|
16
|
+
id: 1
|
17
|
+
parent_id:
|
18
|
+
full_path: ""
|
19
|
+
slug: home-page
|
20
|
+
title: Home Page
|
21
|
+
body: |-
|
22
|
+
h1. {{ page.title }}
|
23
|
+
|
24
|
+
This is your *home page*.
|
25
|
+
author: Comatose
|
26
|
+
keywords: "test, cms"
|
27
|
+
filter_type: Textile
|
28
|
+
position: 0
|
29
|
+
created_on: <%= 10.days.ago.to_s :db %>
|
30
|
+
updated_on: <%= 10.days.ago.to_s :db %>
|
31
|
+
|
32
|
+
faq:
|
33
|
+
id: 2
|
34
|
+
parent_id: 1
|
35
|
+
full_path: "faq"
|
36
|
+
slug: faq
|
37
|
+
title: Frequently Asked Questions
|
38
|
+
body: |-
|
39
|
+
h1. {{ page.title }}
|
40
|
+
{% for c in page.children %}
|
41
|
+
h2. {{ c.link }}
|
42
|
+
|
43
|
+
{{ c.to_html }}
|
44
|
+
|
45
|
+
{% endfor %}
|
46
|
+
created_on: <%= 10.days.ago.to_s :db %>
|
47
|
+
updated_on: <%= 10.days.ago.to_s :db %>
|
48
|
+
author: Comatose
|
49
|
+
keywords: faq
|
50
|
+
filter_type: Textile
|
51
|
+
position: 0
|
52
|
+
|
53
|
+
question_one:
|
54
|
+
id: 3
|
55
|
+
parent_id: 2
|
56
|
+
full_path: "faq/question-one"
|
57
|
+
slug: question-one
|
58
|
+
title: Question One?
|
59
|
+
body: |-
|
60
|
+
Content for *question one*.
|
61
|
+
created_on: <%= 10.days.ago.to_s :db %>
|
62
|
+
updated_on: <%= 10.days.ago.to_s :db %>
|
63
|
+
author: Comatose
|
64
|
+
keywords: faq
|
65
|
+
filter_type: Textile
|
66
|
+
position: 0
|
67
|
+
|
68
|
+
question_two:
|
69
|
+
id: 4
|
70
|
+
parent_id: 2
|
71
|
+
full_path: "faq/question-two"
|
72
|
+
slug: question-two
|
73
|
+
title: Question Two?
|
74
|
+
body: |-
|
75
|
+
Content for *question two*.
|
76
|
+
created_on: <%= 10.days.ago.to_s :db %>
|
77
|
+
updated_on: <%= 10.days.ago.to_s :db %>
|
78
|
+
author: Comatose
|
79
|
+
keywords: faq
|
80
|
+
filter_type: Textile
|
81
|
+
position: 1
|
82
|
+
|
83
|
+
param_driven:
|
84
|
+
id: 5
|
85
|
+
parent_id: 1
|
86
|
+
full_path: "params"
|
87
|
+
slug: params
|
88
|
+
title: Params
|
89
|
+
body: |-
|
90
|
+
I'm {{ extra }}
|
91
|
+
created_on: <%= 10.days.ago.to_s :db %>
|
92
|
+
updated_on: <%= 10.days.ago.to_s :db %>
|
93
|
+
author: Comatose
|
94
|
+
keywords:
|
95
|
+
filter_type: Textile
|
96
|
+
position: 0
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require 'comatose_admin_controller'
|
3
|
+
require 'comatose_admin_helper'
|
4
|
+
require 'text_filters'
|
5
|
+
|
6
|
+
# Re-raise errors caught by the controller.
|
7
|
+
class ComatoseAdminController
|
8
|
+
def rescue_action(e) raise e end
|
9
|
+
end
|
10
|
+
|
11
|
+
class ComatoseAdminControllerTest < Test::Unit::TestCase
|
12
|
+
|
13
|
+
fixtures :comatose_pages
|
14
|
+
|
15
|
+
def setup
|
16
|
+
@controller = ComatoseAdminController.new
|
17
|
+
@request = ActionController::TestRequest.new
|
18
|
+
@response = ActionController::TestResponse.new
|
19
|
+
end
|
20
|
+
|
21
|
+
should "show the index action" do
|
22
|
+
get :index
|
23
|
+
assert_response :success
|
24
|
+
assert assigns(:root_pages)
|
25
|
+
end
|
26
|
+
|
27
|
+
should "show the new action" do
|
28
|
+
get :new
|
29
|
+
assert_response :success
|
30
|
+
assert assigns(:page)
|
31
|
+
end
|
32
|
+
|
33
|
+
should "successfully create pages" do
|
34
|
+
post :new, :page=>{:title=>"Test page", :body=>'This is a *test*', :parent_id=>1, :filter_type=>'Textile'}
|
35
|
+
assert_response :redirect
|
36
|
+
assert_redirected_to :controller=>'comatose_admin', :action=>'index'
|
37
|
+
end
|
38
|
+
|
39
|
+
should "create a page with an empty body" do
|
40
|
+
post :new, :page=>{:title=>"Test page", :body=>nil, :parent_id=>1, :filter_type=>'Textile'}
|
41
|
+
assert_response :redirect
|
42
|
+
assert_redirected_to :controller=>'comatose_admin', :action=>'index'
|
43
|
+
end
|
44
|
+
|
45
|
+
should "not create a page with a missing title" do
|
46
|
+
post :new, :page=>{:title=>nil, :body=>'This is a *test*', :parent_id=>1, :filter_type=>'Textile'}
|
47
|
+
assert_response :success
|
48
|
+
assert assigns.has_key?('page'), "Page assignment"
|
49
|
+
assert (assigns['page'].errors.length > 0), "Page errors"
|
50
|
+
assert_equal 'must be present', assigns['page'].errors.on('title')
|
51
|
+
end
|
52
|
+
|
53
|
+
should "not create a page associated to an invalid parent" do
|
54
|
+
post :new, :page=>{:title=>'Test page', :body=>'This is a *test*', :parent_id=>nil, :filter_type=>'Textile'}
|
55
|
+
assert_response :success
|
56
|
+
assert assigns.has_key?('page'), "Page assignment"
|
57
|
+
assert (assigns['page'].errors.length > 0), "Page errors"
|
58
|
+
assert_equal 'must be present', assigns['page'].errors.on('parent_id')
|
59
|
+
end
|
60
|
+
|
61
|
+
should "contain all the correct options for filter_type" do
|
62
|
+
get :new
|
63
|
+
assert_response :success
|
64
|
+
assert_select 'SELECT[id=page_filter_type]>*', :count=>TextFilters.all_titles.length
|
65
|
+
end
|
66
|
+
|
67
|
+
should "show the edit action" do
|
68
|
+
get :edit, :id=>1
|
69
|
+
assert_response :success
|
70
|
+
end
|
71
|
+
|
72
|
+
should "update pages with valid data" do
|
73
|
+
post :edit, :id=>1, :page=>{ :title=>'A new title' }
|
74
|
+
assert_response :redirect
|
75
|
+
assert_redirected_to :action=>"index"
|
76
|
+
end
|
77
|
+
|
78
|
+
should "not update pages with invalid data" do
|
79
|
+
post :edit, :id=>1, :page=>{ :title=>nil }
|
80
|
+
assert_response :success
|
81
|
+
assert_equal 'must be present', assigns['page'].errors.on('title')
|
82
|
+
end
|
83
|
+
|
84
|
+
should "delete a page" do
|
85
|
+
post :delete, :id=>1
|
86
|
+
assert_response :redirect
|
87
|
+
assert_redirected_to :action=>"index"
|
88
|
+
end
|
89
|
+
|
90
|
+
should "reorder pages" do
|
91
|
+
q1 = comatose_page :question_one
|
92
|
+
assert_not_nil q1
|
93
|
+
assert_difference q1, :position do
|
94
|
+
post :reorder, :id=>q1.parent.id, :page=>q1.id, :cmd=>'down'
|
95
|
+
assert_response :redirect
|
96
|
+
assert_redirected_to :action=>"reorder"
|
97
|
+
q1.reload
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
should "set runtime mode" do
|
102
|
+
assert_equal :plugin, ComatoseAdminController.runtime_mode
|
103
|
+
comatose_admin_view_path = File.expand_path(File.join( File.dirname(__FILE__), '..', '..', 'views'))
|
104
|
+
|
105
|
+
if ComatoseAdminController.respond_to?(:template_root)
|
106
|
+
assert_equal comatose_admin_view_path, ComatoseAdminController.template_root
|
107
|
+
else
|
108
|
+
assert ComatoseAdminController.view_paths.include?(comatose_admin_view_path)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require 'comatose_controller'
|
3
|
+
require 'comatose_helper'
|
4
|
+
|
5
|
+
# Re-raise errors caught by the controller.
|
6
|
+
class ComatoseController
|
7
|
+
def rescue_action(e) raise e end
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
class ComatoseControllerTest < Test::Unit::TestCase
|
12
|
+
|
13
|
+
fixtures :comatose_pages
|
14
|
+
|
15
|
+
def setup
|
16
|
+
@controller = ComatoseController.new
|
17
|
+
@request = ActionController::TestRequest.new
|
18
|
+
@response = ActionController::TestResponse.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_truth
|
22
|
+
assert true
|
23
|
+
end
|
24
|
+
|
25
|
+
should "show pages based on path_info" do
|
26
|
+
|
27
|
+
# Get the faq page...
|
28
|
+
get :show, :page=>'faq', :index=>'', :layout=>'comatose_content.html.erb', :use_cache=>'false'
|
29
|
+
assert_response :success
|
30
|
+
assert_tag :tag=>'h1', :child=>/Frequently Asked Questions/
|
31
|
+
|
32
|
+
# Get a question page using rails 2.0 array style...
|
33
|
+
get :show, :page=>['faq','question-one'], :index=>'', :layout=>'comatose_content.html.erb', :use_cache=>'false'
|
34
|
+
assert_response :success
|
35
|
+
assert_tag :tag=>'title', :child=>/Question/
|
36
|
+
|
37
|
+
# Get a question page using rails 1.x path style...
|
38
|
+
get :show, :page=>ActionController::Routing::PathSegment::Result.new_escaped(['faq','question-one']),
|
39
|
+
:index=>'', :layout=>'comatose_content.html.erb', :use_cache=>'false'
|
40
|
+
assert_response :success
|
41
|
+
assert_tag :tag=>'title', :child=>/Question/
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<html>
|
2
|
+
<!-- Required Scripts -->
|
3
|
+
<script src="../../../../../public/javascripts/prototype.js" type="text/javascript"></script>
|
4
|
+
<script src="../../../../../public/javascripts/effects.js" type="text/javascript"></script>
|
5
|
+
<script src="../../../../../public/javascripts/dragdrop.js" type="text/javascript"></script>
|
6
|
+
<script src="../../../../../public/javascripts/controls.js" type="text/javascript"></script>
|
7
|
+
<script src="../../resources/public/javascripts/comatose_admin.js"></script>
|
8
|
+
<!-- Unit Tests -->
|
9
|
+
|
10
|
+
<script>
|
11
|
+
var Tests = {
|
12
|
+
title: "Comatose JS Tests",
|
13
|
+
// description: "Methods that start with testFail test that assertions fail property.",
|
14
|
+
|
15
|
+
test_String_toSlug: function() {
|
16
|
+
assertEqual( 'hello-how-are-you', 'Hello, How Are You?'.toSlug() );
|
17
|
+
assertEqual( 'i-have-too-much-space', 'I have too much space'.toSlug() );
|
18
|
+
assertEqual( 'what-about-dashes', 'What about - dashes?'.toSlug() );
|
19
|
+
assertEqual( 'a-bizarre-title', 'A !@!@#$%^&*()_+{} Bizarre TiTle!'.toSlug() );
|
20
|
+
assertEqual( '001-numbers-too', '001 Numbers too'.toSlug() );
|
21
|
+
}
|
22
|
+
}
|
23
|
+
</script>
|
24
|
+
<!-- UnitTestRunner -->
|
25
|
+
<script src="test_runner.js"></script>
|
26
|
+
</html>
|
@@ -0,0 +1,307 @@
|
|
1
|
+
/*
|
2
|
+
= Test Framework
|
3
|
+
version 1.0
|
4
|
+
created by M@ McCray (http://www.mattmccray.com)
|
5
|
+
|
6
|
+
This is a simple JavaScript test framework.
|
7
|
+
|
8
|
+
= TODO:
|
9
|
+
|
10
|
+
* Add support for calling Tests.setup() and Tests.teardown()
|
11
|
+
* Documentation!
|
12
|
+
* Add support for methods that don't start with 'test'?
|
13
|
+
* Make test method names more English?
|
14
|
+
*/
|
15
|
+
|
16
|
+
// We're gonna run all this in it's own scope so it doesn't pollute the test namespace
|
17
|
+
(function(){
|
18
|
+
var HTML = {
|
19
|
+
_all_tags: ['a','abbr','acronym','address','area','b','base','bdo','big','blockquote','body','br','button','caption','cite','code','col','colgroup','dd','del','dfn','div','dl','DOCTYPE','dt','em','fieldset','form','h1','h2','h3','h4','h5','h6','head','html','hr','i','img','input','ins','kbd','label','legend','li','link','map','meta','noscript','object','ol','optgroup','option','p','param','pre','q','samp','script','select','small','span','strong','style','sub','sup','table','tbody','td','textarea','tfoot','th','thead','title','tr','tt','ul'],
|
20
|
+
_init: function() {
|
21
|
+
for(var $i=0; $i<this._all_tags.length; $i++) {
|
22
|
+
var $tag = this._all_tags[$i]
|
23
|
+
eval( 'HTML.'+ $tag +' = function (){ return HTML._write_tag("'+ $tag +'", arguments); }' );
|
24
|
+
//this[$tag] = new Function("return HTML._write_tag('"+ $tag +"', arguments);")
|
25
|
+
this.namespace += ';var '+ $tag +' = HTML.'+ $tag;
|
26
|
+
}
|
27
|
+
},
|
28
|
+
_write_tag: function(tag, options) {
|
29
|
+
var $content = ''; var $atts = "";
|
30
|
+
for(var $i=0; $i<options.length; $i++) {
|
31
|
+
var $arg = options[$i];
|
32
|
+
if (typeof($arg) == 'string' || typeof($arg) == 'number')
|
33
|
+
$content += $arg.toString();
|
34
|
+
else if (typeof($arg) == 'function')
|
35
|
+
$content += $arg();
|
36
|
+
else if ( $arg instanceof Object)
|
37
|
+
for($prop in $arg) $atts += ' '+ $prop +'="'+ $arg[$prop] +'"';
|
38
|
+
}
|
39
|
+
if($content == '')
|
40
|
+
return '<'+ tag + $atts +'/>';
|
41
|
+
else
|
42
|
+
return '<'+ tag + $atts +'>'+ $content +'</'+ tag +'>';
|
43
|
+
},
|
44
|
+
namespace: 'var text = HTML.text',
|
45
|
+
toString: function() { return this.namespace; },
|
46
|
+
text: function() {
|
47
|
+
var $content='';
|
48
|
+
for(var $i=0; $i<arguments.length; $i++) $content += arguments[$i].toString();
|
49
|
+
return $content;
|
50
|
+
}
|
51
|
+
};
|
52
|
+
HTML._init();
|
53
|
+
eval(HTML.namespace);
|
54
|
+
|
55
|
+
var list_html = "";
|
56
|
+
var page_title = "Test Cases";
|
57
|
+
var page_desc = "";
|
58
|
+
|
59
|
+
window.methodList = [];
|
60
|
+
if( typeof(Tests) != 'undefined' ) {
|
61
|
+
if(Tests.title) page_title = Tests.title;
|
62
|
+
if(Tests.description) page_desc = Tests.description;
|
63
|
+
|
64
|
+
for(func in Tests) {
|
65
|
+
if(/test/.test(func)) {
|
66
|
+
methodList.push(func);
|
67
|
+
list_html += li ({id:func, 'class':'untested'},
|
68
|
+
span (func.toString()),
|
69
|
+
div (' ', {id: (func +'-error')})
|
70
|
+
)
|
71
|
+
}
|
72
|
+
}
|
73
|
+
} else {
|
74
|
+
list_html = li('No tests defined!', {'class':'fail'})
|
75
|
+
}
|
76
|
+
|
77
|
+
// Generate HTML
|
78
|
+
|
79
|
+
if( page_desc != '' ) page_desc = p( page_desc,{'class':'description'});
|
80
|
+
|
81
|
+
document.write(
|
82
|
+
head (
|
83
|
+
title ( "(", page_title, ")", " :: JavaScript Test Framework" ),
|
84
|
+
style (
|
85
|
+
"BODY { font-family:Helvetica,Verdana,Sans-Serif; background:#E0E0E0; }",
|
86
|
+
"LI { padding:3px; }",
|
87
|
+
"H1 { margin-top:0; color:navy; }",
|
88
|
+
"INPUT { font-size:105%; font-weight:bold; }",
|
89
|
+
"#main { width:650px; margin:0 auto; background:#FFF; padding:20px; border:1px solid #BBB; }",
|
90
|
+
"#status { padding:10px; }",
|
91
|
+
"#sidebar { background:#F0F0F0; float:right; width:200px; padding:5px 15px; font-size:85%; border:10px solid white; border-top:0px; }",
|
92
|
+
".description { background:#FFC; padding:10px; font-size:85%; }",
|
93
|
+
".credit { padding:0px 2px; font-size:90%; color:gray; }",
|
94
|
+
".untested { color:#C5C5C5; }",
|
95
|
+
".untested SPAN { color:black; }",
|
96
|
+
".pass { color:#0F0; }",
|
97
|
+
".pass SPAN { color:#363; }",
|
98
|
+
".fail { color:red; }",
|
99
|
+
".fail DIV { font-size:85%; color:#666; }",
|
100
|
+
".fail SPAN { color:maroon; }",
|
101
|
+
".fail UL { margin:0px; padding:0px; padding-left:10px; list-style:none; }",
|
102
|
+
".fail LI { padding:2px; }",
|
103
|
+
".assertion-type { color:black !important; font-weight:bold; }",
|
104
|
+
".exception-type { color:red !important; font-weight:bold; }"
|
105
|
+
)
|
106
|
+
),
|
107
|
+
body (
|
108
|
+
div ({id:'main'},
|
109
|
+
div ({id:'sidebar'},
|
110
|
+
p ("This is a simple JavaScript test framework."),
|
111
|
+
p ("To read the tests, just view-source."),
|
112
|
+
p ("Created by M@ McCray. Released under the MIT license.", {'class':'credit'})
|
113
|
+
),
|
114
|
+
h1 (page_title),
|
115
|
+
page_desc,
|
116
|
+
ul ({id:'test-list'},
|
117
|
+
list_html
|
118
|
+
),
|
119
|
+
table( tr(
|
120
|
+
td(
|
121
|
+
input ({ type:'button', onclick:'runAllTests()', value:'Run All Tests'})
|
122
|
+
),
|
123
|
+
td(
|
124
|
+
div (' ',{id:'status'})
|
125
|
+
)
|
126
|
+
))
|
127
|
+
),
|
128
|
+
div (' ', {id:'work-area'})
|
129
|
+
)
|
130
|
+
);
|
131
|
+
|
132
|
+
window.assertionCount = 0;
|
133
|
+
window.assertionFailCount = 0;
|
134
|
+
window.assertionErrorCount = 0;
|
135
|
+
|
136
|
+
var assertionFailures = [];
|
137
|
+
|
138
|
+
// Exported functions
|
139
|
+
window.runAllTests = function() {
|
140
|
+
var errors = [];
|
141
|
+
assertionCount = 0;
|
142
|
+
assertionFailCount = 0;
|
143
|
+
|
144
|
+
forEach(methodList, function(func){
|
145
|
+
setStatus('Evaluating '+ func +'...');
|
146
|
+
|
147
|
+
assertionFailures = [];
|
148
|
+
assertionExceptions = [];
|
149
|
+
try {
|
150
|
+
Tests[func]()
|
151
|
+
} catch (ex) {
|
152
|
+
assertionErrorCount++;
|
153
|
+
assertionExceptions.push(ex)
|
154
|
+
}
|
155
|
+
if( assertionFailures.length == 0 && assertionExceptions.length == 0) {
|
156
|
+
$(func).className = 'pass';
|
157
|
+
} else {
|
158
|
+
$(func).className = 'fail';
|
159
|
+
var results = ""
|
160
|
+
|
161
|
+
forEach(assertionFailures, function(err){
|
162
|
+
results += li (
|
163
|
+
span (err.assertionType, {'class':'assertion-type'}), ': ',
|
164
|
+
(err.message || err.extraInformation)
|
165
|
+
);
|
166
|
+
});
|
167
|
+
|
168
|
+
forEach(assertionExceptions, function(err){
|
169
|
+
results += li (
|
170
|
+
span ('Error', {'class':'exception-type'}), ': ',
|
171
|
+
(err.description || err.message || err)
|
172
|
+
);
|
173
|
+
});
|
174
|
+
|
175
|
+
setResults( func, ul (results) )
|
176
|
+
}
|
177
|
+
});
|
178
|
+
|
179
|
+
setStatus( div (
|
180
|
+
assertionCount,
|
181
|
+
" assertions, ",
|
182
|
+
span ((assertionCount - assertionFailCount), {'class':'pass'}),
|
183
|
+
" passed",
|
184
|
+
show_if (assertionFailCount, text( ", ",
|
185
|
+
span (assertionFailCount, {'class':'fail'}),
|
186
|
+
" failed" )
|
187
|
+
),
|
188
|
+
show_if (assertionErrorCount, text( ", ",
|
189
|
+
span (assertionErrorCount, {'class':'fail'}),
|
190
|
+
" error(s)")
|
191
|
+
),
|
192
|
+
"."
|
193
|
+
));
|
194
|
+
}
|
195
|
+
|
196
|
+
// Assertions
|
197
|
+
window.assert = function(condition, msg) {
|
198
|
+
window.assertionCount++;
|
199
|
+
if(!condition) {
|
200
|
+
ex = 'true was expected, but value was '+ condition;
|
201
|
+
assertError(msg, 'assert', ex);
|
202
|
+
}
|
203
|
+
}
|
204
|
+
|
205
|
+
window.assertFalse = function(condition, msg) {
|
206
|
+
window.assertionCount++;
|
207
|
+
if(condition) {
|
208
|
+
ex = 'false was expected, but value was '+ condition;
|
209
|
+
assertError(msg, 'assertFalse', ex);
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
window.assertNull = function(condition, msg) {
|
214
|
+
window.assertionCount++;
|
215
|
+
if(null != condition) {
|
216
|
+
ex = 'null was expected, but value was '+ condition;
|
217
|
+
assertError(msg, 'assertNull', ex);
|
218
|
+
}
|
219
|
+
}
|
220
|
+
|
221
|
+
window.assertNotNull = function(condition, msg) {
|
222
|
+
window.assertionCount++;
|
223
|
+
if(null == condition) {
|
224
|
+
ex = 'null was not expected, but value was '+ condition;
|
225
|
+
assertError(msg, 'assertNotNull', ex);
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
window.assertEqual = function(condition1, condition2, msg) {
|
230
|
+
window.assertionCount++;
|
231
|
+
ex = condition1 +' was expected, but value was '+ condition2;
|
232
|
+
if(condition1 != condition2) {
|
233
|
+
assertError(msg, 'assertEqual', ex);
|
234
|
+
}
|
235
|
+
}
|
236
|
+
|
237
|
+
window.assertNotEqual = function(condition1, condition2, msg) {
|
238
|
+
window.assertionCount++;
|
239
|
+
if(condition1 == condition2) {
|
240
|
+
ex = condition1 +' was not expected, but value was '+ condition2;
|
241
|
+
assertError(msg, 'assertNotEqual', ex);
|
242
|
+
}
|
243
|
+
}
|
244
|
+
|
245
|
+
window.assertUndefined = function(object, msg) {
|
246
|
+
window.assertionCount++;
|
247
|
+
if(object != 'undefined' ) {
|
248
|
+
ex = object +' was defined';
|
249
|
+
assertError(msg, 'assertUndefined', ex);
|
250
|
+
}
|
251
|
+
}
|
252
|
+
|
253
|
+
window.assertDefined = function(object, msg) {
|
254
|
+
window.assertionCount++;
|
255
|
+
if(object == 'undefined' ) {
|
256
|
+
ex = object +' was undefined';
|
257
|
+
assertError(msg, 'assertDefined', ex);
|
258
|
+
}
|
259
|
+
}
|
260
|
+
|
261
|
+
// Private functions
|
262
|
+
function $(elem) {
|
263
|
+
return document.getElementById(elem);
|
264
|
+
}
|
265
|
+
|
266
|
+
function log() {
|
267
|
+
var msg = [];
|
268
|
+
forEach(arguments, function(arg){ msg.push( arg || '' ); });
|
269
|
+
if(window.console && window.console.log) {
|
270
|
+
window.console.log(msg.join(' '))
|
271
|
+
} else if(window.console && window.console.info) {
|
272
|
+
window.console.info(msg.join(' '))
|
273
|
+
}
|
274
|
+
}
|
275
|
+
|
276
|
+
function forEach(array, block, context) {
|
277
|
+
for (var i = 0; i < array.length; i++) {
|
278
|
+
block.call(context, array[i], i, array);
|
279
|
+
}
|
280
|
+
}
|
281
|
+
|
282
|
+
function show_if(list, html) {
|
283
|
+
if(list > 0)
|
284
|
+
return html;
|
285
|
+
else
|
286
|
+
return '';
|
287
|
+
}
|
288
|
+
|
289
|
+
function setStatus(msg) {
|
290
|
+
$('status').innerHTML = msg;
|
291
|
+
}
|
292
|
+
|
293
|
+
function setResults(func, msg) {
|
294
|
+
$(func+'-error').innerHTML = msg;
|
295
|
+
}
|
296
|
+
|
297
|
+
function assertError(errorMessage, assertionType, extraInfo) {
|
298
|
+
window.assertionFailCount++;
|
299
|
+
assertionFailures.push({
|
300
|
+
assertionType: assertionType,
|
301
|
+
message: errorMessage,
|
302
|
+
extraInformation: extraInfo.toString().replace(/</g, '<'),
|
303
|
+
description: errorMessage +"\n"+ extraInfo.toString().replace(/</g, '<')
|
304
|
+
});
|
305
|
+
}
|
306
|
+
|
307
|
+
})();
|