darthapo-comatose 2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +171 -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 +20 -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 +10 -0
- data/install.rb +16 -0
- data/lib/acts_as_versioned.rb +543 -0
- data/lib/comatose.rb +23 -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 +348 -0
- data/lib/comatose_admin_helper.rb +37 -0
- data/lib/comatose_controller.rb +141 -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 +12 -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 +157 -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
|
+
})();
|